mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
refactor(parser): use AstBuilder (#5743)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
bd48dfbf8b
commit
a4b55bf00e
8 changed files with 61 additions and 83 deletions
|
|
@ -421,20 +421,19 @@ impl<'a> ParserImpl<'a> {
|
||||||
} else {
|
} else {
|
||||||
MethodDefinitionType::MethodDefinition
|
MethodDefinitionType::MethodDefinition
|
||||||
};
|
};
|
||||||
let method_definition = MethodDefinition {
|
Ok(self.ast.class_element_method_definition(
|
||||||
r#type,
|
r#type,
|
||||||
span: self.end_span(span),
|
self.end_span(span),
|
||||||
|
decorators,
|
||||||
key,
|
key,
|
||||||
value,
|
value,
|
||||||
kind,
|
kind,
|
||||||
computed,
|
computed,
|
||||||
r#static,
|
r#static,
|
||||||
r#override,
|
r#override,
|
||||||
accessibility,
|
|
||||||
optional,
|
optional,
|
||||||
decorators,
|
accessibility,
|
||||||
};
|
))
|
||||||
Ok(ClassElement::MethodDefinition(self.ast.alloc(method_definition)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `FieldDefinition`[?Yield, ?Await] ;
|
/// `FieldDefinition`[?Yield, ?Await] ;
|
||||||
|
|
@ -464,23 +463,22 @@ impl<'a> ParserImpl<'a> {
|
||||||
} else {
|
} else {
|
||||||
PropertyDefinitionType::PropertyDefinition
|
PropertyDefinitionType::PropertyDefinition
|
||||||
};
|
};
|
||||||
let property_definition = PropertyDefinition {
|
Ok(self.ast.class_element_property_definition(
|
||||||
r#type,
|
r#type,
|
||||||
span: self.end_span(span),
|
self.end_span(span),
|
||||||
|
decorators,
|
||||||
key,
|
key,
|
||||||
value,
|
value,
|
||||||
computed,
|
computed,
|
||||||
r#static,
|
r#static,
|
||||||
declare,
|
declare,
|
||||||
r#override,
|
r#override,
|
||||||
|
optional,
|
||||||
|
definite,
|
||||||
readonly,
|
readonly,
|
||||||
type_annotation,
|
type_annotation,
|
||||||
accessibility,
|
accessibility,
|
||||||
optional,
|
))
|
||||||
definite,
|
|
||||||
decorators,
|
|
||||||
};
|
|
||||||
Ok(ClassElement::PropertyDefinition(self.ast.alloc(property_definition)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `ClassStaticBlockStatementList` :
|
/// `ClassStaticBlockStatementList` :
|
||||||
|
|
|
||||||
|
|
@ -338,13 +338,11 @@ impl<'a> ParserImpl<'a> {
|
||||||
|
|
||||||
pub(crate) fn parse_literal_regexp(&mut self) -> Result<RegExpLiteral<'a>> {
|
pub(crate) fn parse_literal_regexp(&mut self) -> Result<RegExpLiteral<'a>> {
|
||||||
let span = self.start_span();
|
let span = self.start_span();
|
||||||
|
|
||||||
// split out pattern
|
// split out pattern
|
||||||
let (pattern_end, flags) = self.read_regex()?;
|
let (pattern_end, flags) = self.read_regex()?;
|
||||||
let pattern_start = self.cur_token().start + 1; // +1 to exclude `/`
|
let pattern_start = self.cur_token().start + 1; // +1 to exclude `/`
|
||||||
let pattern_text = &self.source_text[pattern_start as usize..pattern_end as usize];
|
let pattern_text = &self.source_text[pattern_start as usize..pattern_end as usize];
|
||||||
self.bump_any();
|
self.bump_any();
|
||||||
|
|
||||||
let pattern = self
|
let pattern = self
|
||||||
.options
|
.options
|
||||||
.parse_regular_expression
|
.parse_regular_expression
|
||||||
|
|
@ -356,7 +354,6 @@ impl<'a> ParserImpl<'a> {
|
||||||
pat.map_or_else(|| RegExpPattern::Invalid(pattern_text), RegExpPattern::Pattern)
|
pat.map_or_else(|| RegExpPattern::Invalid(pattern_text), RegExpPattern::Pattern)
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
Ok(self.ast.reg_exp_literal(self.end_span(span), EmptyObject, RegExp { pattern, flags }))
|
Ok(self.ast.reg_exp_literal(self.end_span(span), EmptyObject, RegExp { pattern, flags }))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -471,7 +468,7 @@ impl<'a> ParserImpl<'a> {
|
||||||
}
|
}
|
||||||
_ => unreachable!("parse_template_literal"),
|
_ => unreachable!("parse_template_literal"),
|
||||||
}
|
}
|
||||||
Ok(TemplateLiteral { span: self.end_span(span), quasis, expressions })
|
Ok(self.ast.template_literal(self.end_span(span), quasis, expressions))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn parse_template_literal_expression(
|
pub(crate) fn parse_template_literal_expression(
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,3 @@
|
||||||
use std::cell::Cell;
|
|
||||||
|
|
||||||
use oxc_allocator::Box;
|
use oxc_allocator::Box;
|
||||||
use oxc_ast::ast::*;
|
use oxc_ast::ast::*;
|
||||||
use oxc_diagnostics::Result;
|
use oxc_diagnostics::Result;
|
||||||
|
|
@ -332,7 +330,7 @@ impl<'a> ParserImpl<'a> {
|
||||||
let id = self.cur_kind().is_binding_identifier().then(|| {
|
let id = self.cur_kind().is_binding_identifier().then(|| {
|
||||||
let (span, name) = self.parse_identifier_kind(Kind::Ident);
|
let (span, name) = self.parse_identifier_kind(Kind::Ident);
|
||||||
self.check_identifier(span, &name);
|
self.check_identifier(span, &name);
|
||||||
BindingIdentifier { span, name, symbol_id: Cell::default() }
|
self.ast.binding_identifier(span, name)
|
||||||
});
|
});
|
||||||
self.ctx = ctx;
|
self.ctx = ctx;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,10 +79,10 @@ impl<'a> CoverGrammar<'a, ArrayExpression<'a>> for ArrayAssignmentTarget<'a> {
|
||||||
}
|
}
|
||||||
ArrayExpressionElement::SpreadElement(elem) => {
|
ArrayExpressionElement::SpreadElement(elem) => {
|
||||||
if i == len - 1 {
|
if i == len - 1 {
|
||||||
rest = Some(AssignmentTargetRest {
|
rest = Some(p.ast.assignment_target_rest(
|
||||||
span: elem.span,
|
elem.span,
|
||||||
target: AssignmentTarget::cover(elem.unbox().argument, p)?,
|
AssignmentTarget::cover(elem.unbox().argument, p)?,
|
||||||
});
|
));
|
||||||
if let Some(span) = expr.trailing_comma {
|
if let Some(span) = expr.trailing_comma {
|
||||||
p.error(diagnostics::binding_rest_element_trailing_comma(span));
|
p.error(diagnostics::binding_rest_element_trailing_comma(span));
|
||||||
}
|
}
|
||||||
|
|
@ -94,12 +94,7 @@ impl<'a> CoverGrammar<'a, ArrayExpression<'a>> for ArrayAssignmentTarget<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ArrayAssignmentTarget {
|
Ok(p.ast.array_assignment_target(expr.span, elements, rest, expr.trailing_comma))
|
||||||
span: expr.span,
|
|
||||||
elements,
|
|
||||||
rest,
|
|
||||||
trailing_comma: expr.trailing_comma,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -119,8 +114,8 @@ impl<'a> CoverGrammar<'a, Expression<'a>> for AssignmentTargetMaybeDefault<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> CoverGrammar<'a, AssignmentExpression<'a>> for AssignmentTargetWithDefault<'a> {
|
impl<'a> CoverGrammar<'a, AssignmentExpression<'a>> for AssignmentTargetWithDefault<'a> {
|
||||||
fn cover(expr: AssignmentExpression<'a>, _p: &mut ParserImpl<'a>) -> Result<Self> {
|
fn cover(expr: AssignmentExpression<'a>, p: &mut ParserImpl<'a>) -> Result<Self> {
|
||||||
Ok(Self { span: expr.span, binding: expr.left, init: expr.right })
|
Ok(p.ast.assignment_target_with_default(expr.span, expr.left, expr.right))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -138,10 +133,10 @@ impl<'a> CoverGrammar<'a, ObjectExpression<'a>> for ObjectAssignmentTarget<'a> {
|
||||||
}
|
}
|
||||||
ObjectPropertyKind::SpreadProperty(spread) => {
|
ObjectPropertyKind::SpreadProperty(spread) => {
|
||||||
if i == len - 1 {
|
if i == len - 1 {
|
||||||
rest = Some(AssignmentTargetRest {
|
rest = Some(p.ast.assignment_target_rest(
|
||||||
span: spread.span,
|
spread.span,
|
||||||
target: AssignmentTarget::cover(spread.unbox().argument, p)?,
|
AssignmentTarget::cover(spread.unbox().argument, p)?,
|
||||||
});
|
));
|
||||||
} else {
|
} else {
|
||||||
return Err(diagnostics::spread_last_element(spread.span));
|
return Err(diagnostics::spread_last_element(spread.span));
|
||||||
}
|
}
|
||||||
|
|
@ -149,7 +144,7 @@ impl<'a> CoverGrammar<'a, ObjectExpression<'a>> for ObjectAssignmentTarget<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self { span: expr.span, properties, rest })
|
Ok(p.ast.object_assignment_target(expr.span, properties, rest))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -170,16 +165,18 @@ impl<'a> CoverGrammar<'a, ObjectProperty<'a>> for AssignmentTargetProperty<'a> {
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
let target = AssignmentTargetPropertyIdentifier { span: property.span, binding, init };
|
Ok(p.ast.assignment_target_property_assignment_target_property_identifier(
|
||||||
Ok(AssignmentTargetProperty::AssignmentTargetPropertyIdentifier(p.ast.alloc(target)))
|
property.span,
|
||||||
|
binding,
|
||||||
|
init,
|
||||||
|
))
|
||||||
} else {
|
} else {
|
||||||
let binding = AssignmentTargetMaybeDefault::cover(property.value, p)?;
|
let binding = AssignmentTargetMaybeDefault::cover(property.value, p)?;
|
||||||
let target = AssignmentTargetPropertyProperty {
|
Ok(p.ast.assignment_target_property_assignment_target_property_property(
|
||||||
span: property.span,
|
property.span,
|
||||||
name: property.key,
|
property.key,
|
||||||
binding,
|
binding,
|
||||||
};
|
))
|
||||||
Ok(AssignmentTargetProperty::AssignmentTargetPropertyProperty(p.ast.alloc(target)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -107,9 +107,8 @@ impl<'a> ParserImpl<'a> {
|
||||||
fn parse_import_default_specifier(&mut self) -> Result<ImportDeclarationSpecifier<'a>> {
|
fn parse_import_default_specifier(&mut self) -> Result<ImportDeclarationSpecifier<'a>> {
|
||||||
let span = self.start_span();
|
let span = self.start_span();
|
||||||
let local = self.parse_binding_identifier()?;
|
let local = self.parse_binding_identifier()?;
|
||||||
Ok(ImportDeclarationSpecifier::ImportDefaultSpecifier(
|
let span = self.end_span(span);
|
||||||
self.ast.alloc(ImportDefaultSpecifier { span: self.end_span(span), local }),
|
Ok(self.ast.import_declaration_specifier_import_default_specifier(span, local))
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// import * as name from "module-name"
|
// import * as name from "module-name"
|
||||||
|
|
@ -118,9 +117,8 @@ impl<'a> ParserImpl<'a> {
|
||||||
self.bump_any(); // advance `*`
|
self.bump_any(); // advance `*`
|
||||||
self.expect(Kind::As)?;
|
self.expect(Kind::As)?;
|
||||||
let local = self.parse_binding_identifier()?;
|
let local = self.parse_binding_identifier()?;
|
||||||
Ok(ImportDeclarationSpecifier::ImportNamespaceSpecifier(
|
let span = self.end_span(span);
|
||||||
self.ast.alloc(ImportNamespaceSpecifier { span: self.end_span(span), local }),
|
Ok(self.ast.import_declaration_specifier_import_namespace_specifier(span, local))
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// import { export1 , export2 as alias2 , [...] } from "module-name";
|
// import { export1 , export2 as alias2 , [...] } from "module-name";
|
||||||
|
|
@ -168,7 +166,7 @@ impl<'a> ParserImpl<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Some(WithClause { span: self.end_span(span), attributes_keyword, with_entries }))
|
Ok(Some(self.ast.with_clause(self.end_span(span), attributes_keyword, with_entries)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_import_attribute(&mut self) -> Result<ImportAttribute<'a>> {
|
fn parse_import_attribute(&mut self) -> Result<ImportAttribute<'a>> {
|
||||||
|
|
@ -179,7 +177,7 @@ impl<'a> ParserImpl<'a> {
|
||||||
};
|
};
|
||||||
self.expect(Kind::Colon)?;
|
self.expect(Kind::Colon)?;
|
||||||
let value = self.parse_literal_string()?;
|
let value = self.parse_literal_string()?;
|
||||||
Ok(ImportAttribute { span: self.end_span(span), key, value })
|
Ok(self.ast.import_attribute(self.end_span(span), key, value))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn parse_ts_export_assignment_declaration(
|
pub(crate) fn parse_ts_export_assignment_declaration(
|
||||||
|
|
@ -187,11 +185,9 @@ impl<'a> ParserImpl<'a> {
|
||||||
start_span: Span,
|
start_span: Span,
|
||||||
) -> Result<Box<'a, TSExportAssignment<'a>>> {
|
) -> Result<Box<'a, TSExportAssignment<'a>>> {
|
||||||
self.expect(Kind::Eq)?;
|
self.expect(Kind::Eq)?;
|
||||||
|
|
||||||
let expression = self.parse_assignment_expression_or_higher()?;
|
let expression = self.parse_assignment_expression_or_higher()?;
|
||||||
self.asi()?;
|
self.asi()?;
|
||||||
|
Ok(self.ast.alloc_ts_export_assignment(self.end_span(start_span), expression))
|
||||||
Ok(self.ast.alloc(TSExportAssignment { span: self.end_span(start_span), expression }))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn parse_ts_export_namespace(
|
pub(crate) fn parse_ts_export_namespace(
|
||||||
|
|
@ -200,11 +196,9 @@ impl<'a> ParserImpl<'a> {
|
||||||
let span = self.start_span();
|
let span = self.start_span();
|
||||||
self.expect(Kind::As)?;
|
self.expect(Kind::As)?;
|
||||||
self.expect(Kind::Namespace)?;
|
self.expect(Kind::Namespace)?;
|
||||||
|
|
||||||
let id = self.parse_identifier_name()?;
|
let id = self.parse_identifier_name()?;
|
||||||
self.asi()?;
|
self.asi()?;
|
||||||
|
Ok(self.ast.alloc_ts_namespace_export_declaration(self.end_span(span), id))
|
||||||
Ok(self.ast.alloc(TSNamespaceExportDeclaration { span: self.end_span(span), id }))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [Exports](https://tc39.es/ecma262/#sec-exports)
|
/// [Exports](https://tc39.es/ecma262/#sec-exports)
|
||||||
|
|
@ -453,15 +447,14 @@ impl<'a> ParserImpl<'a> {
|
||||||
(imported, local)
|
(imported, local)
|
||||||
} else {
|
} else {
|
||||||
let local = self.parse_binding_identifier()?;
|
let local = self.parse_binding_identifier()?;
|
||||||
let imported = IdentifierName { span: local.span, name: local.name.clone() };
|
(self.ast.module_export_name_identifier_name(local.span, local.name.clone()), local)
|
||||||
(ModuleExportName::IdentifierName(imported), local)
|
|
||||||
};
|
};
|
||||||
Ok(ImportDeclarationSpecifier::ImportSpecifier(self.ast.alloc(ImportSpecifier {
|
Ok(self.ast.import_declaration_specifier_import_specifier(
|
||||||
span: self.end_span(specifier_span),
|
self.end_span(specifier_span),
|
||||||
imported,
|
imported,
|
||||||
local,
|
local,
|
||||||
import_kind,
|
import_kind,
|
||||||
})))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ModuleExportName :
|
// ModuleExportName :
|
||||||
|
|
@ -548,6 +541,6 @@ impl<'a> ParserImpl<'a> {
|
||||||
let local = self.parse_module_export_name()?;
|
let local = self.parse_module_export_name()?;
|
||||||
let exported =
|
let exported =
|
||||||
if self.eat(Kind::As) { self.parse_module_export_name()? } else { local.clone() };
|
if self.eat(Kind::As) { self.parse_module_export_name()? } else { local.clone() };
|
||||||
Ok(ExportSpecifier { span: self.end_span(specifier_span), local, exported, export_kind })
|
Ok(self.ast.export_specifier(self.end_span(specifier_span), local, exported, export_kind))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -134,8 +134,7 @@ impl<'a> ParserImpl<'a> {
|
||||||
fn parse_property_definition_shorthand(&mut self) -> Result<Box<'a, ObjectProperty<'a>>> {
|
fn parse_property_definition_shorthand(&mut self) -> Result<Box<'a, ObjectProperty<'a>>> {
|
||||||
let span = self.start_span();
|
let span = self.start_span();
|
||||||
let identifier = self.parse_identifier_reference()?;
|
let identifier = self.parse_identifier_reference()?;
|
||||||
let key =
|
let key = self.ast.alloc_identifier_name(identifier.span, identifier.name.clone());
|
||||||
self.ast.alloc(IdentifierName { span: identifier.span, name: identifier.name.clone() });
|
|
||||||
// IdentifierReference ({ foo })
|
// IdentifierReference ({ foo })
|
||||||
let value = Expression::Identifier(self.ast.alloc(identifier.clone()));
|
let value = Expression::Identifier(self.ast.alloc(identifier.clone()));
|
||||||
// CoverInitializedName ({ foo = bar })
|
// CoverInitializedName ({ foo = bar })
|
||||||
|
|
|
||||||
|
|
@ -130,7 +130,7 @@ impl<'a> ParserImpl<'a> {
|
||||||
// Section 14.13 Labelled Statement
|
// Section 14.13 Labelled Statement
|
||||||
// Avoids lookahead for a labeled statement, which is on a hot path
|
// Avoids lookahead for a labeled statement, which is on a hot path
|
||||||
if self.eat(Kind::Colon) {
|
if self.eat(Kind::Colon) {
|
||||||
let label = LabelIdentifier { span: ident.span, name: ident.name.clone() };
|
let label = self.ast.label_identifier(ident.span, ident.name.clone());
|
||||||
let body = self.parse_statement_list_item(StatementContext::Label)?;
|
let body = self.parse_statement_list_item(StatementContext::Label)?;
|
||||||
return Ok(self.ast.statement_labeled(self.end_span(span), label, body));
|
return Ok(self.ast.statement_labeled(self.end_span(span), label, body));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -376,7 +376,7 @@ impl<'a> ParserImpl<'a> {
|
||||||
Kind::This => {
|
Kind::This => {
|
||||||
let span = self.start_span();
|
let span = self.start_span();
|
||||||
self.bump_any(); // bump `this`
|
self.bump_any(); // bump `this`
|
||||||
let this_type = TSThisType { span: self.end_span(span) };
|
let this_type = self.ast.ts_this_type(self.end_span(span));
|
||||||
if self.peek_at(Kind::Is) && !self.peek_token().is_on_new_line {
|
if self.peek_at(Kind::Is) && !self.peek_token().is_on_new_line {
|
||||||
return self.parse_this_type_predicate(this_type);
|
return self.parse_this_type_predicate(this_type);
|
||||||
}
|
}
|
||||||
|
|
@ -664,7 +664,7 @@ impl<'a> ParserImpl<'a> {
|
||||||
fn parse_this_type_node(&mut self) -> TSThisType {
|
fn parse_this_type_node(&mut self) -> TSThisType {
|
||||||
let span = self.start_span();
|
let span = self.start_span();
|
||||||
self.bump_any(); // bump `this`
|
self.bump_any(); // bump `this`
|
||||||
TSThisType { span: self.end_span(span) }
|
self.ast.ts_this_type(self.end_span(span))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_ts_type_constraint(&mut self) -> Result<Option<TSType<'a>>> {
|
fn parse_ts_type_constraint(&mut self) -> Result<Option<TSType<'a>>> {
|
||||||
|
|
@ -877,17 +877,15 @@ impl<'a> ParserImpl<'a> {
|
||||||
let element_type = self.parse_tuple_element_type()?;
|
let element_type = self.parse_tuple_element_type()?;
|
||||||
let span = self.end_span(span);
|
let span = self.end_span(span);
|
||||||
return Ok(if dotdotdot {
|
return Ok(if dotdotdot {
|
||||||
TSTupleElement::TSRestType(self.ast.alloc(TSRestType {
|
let type_annotation = self.ast.ts_type_named_tuple_member(
|
||||||
span,
|
self.end_span(member_span),
|
||||||
type_annotation: self.ast.ts_type_named_tuple_member(
|
element_type,
|
||||||
self.end_span(member_span),
|
label,
|
||||||
element_type,
|
// TODO: A tuple member cannot be both optional and rest. (TS5085)
|
||||||
label,
|
// See typescript suite <conformance/types/tuple/restTupleElements1.ts>
|
||||||
// TODO: A tuple member cannot be both optional and rest. (TS5085)
|
optional,
|
||||||
// See typescript suite <conformance/types/tuple/restTupleElements1.ts>
|
);
|
||||||
optional,
|
self.ast.ts_tuple_element_rest_type(span, type_annotation)
|
||||||
),
|
|
||||||
}))
|
|
||||||
} else {
|
} else {
|
||||||
TSTupleElement::from(self.ast.ts_type_named_tuple_member(
|
TSTupleElement::from(self.ast.ts_type_named_tuple_member(
|
||||||
span,
|
span,
|
||||||
|
|
@ -920,9 +918,7 @@ impl<'a> ParserImpl<'a> {
|
||||||
let span = self.start_span();
|
let span = self.start_span();
|
||||||
if self.eat(Kind::Dot3) {
|
if self.eat(Kind::Dot3) {
|
||||||
let ty = self.parse_ts_type()?;
|
let ty = self.parse_ts_type()?;
|
||||||
return Ok(TSTupleElement::TSRestType(
|
return Ok(self.ast.ts_tuple_element_rest_type(self.end_span(span), ty));
|
||||||
self.ast.alloc(TSRestType { span: self.end_span(span), type_annotation: ty }),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
let ty = self.parse_ts_type()?;
|
let ty = self.parse_ts_type()?;
|
||||||
if let TSType::JSDocNullableType(ty) = ty {
|
if let TSType::JSDocNullableType(ty) = ty {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue