fix(parser): correctly parse cls.fn<C> = x (#3208)

close: #3206
This commit is contained in:
Dunqing 2024-05-09 10:23:45 +08:00 committed by GitHub
parent 7113e850b4
commit 0ba7778e5e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 106 additions and 28 deletions

View file

@ -1123,6 +1123,7 @@ macro_rules! match_assignment_target {
| $ty::TSSatisfiesExpression(_)
| $ty::TSNonNullExpression(_)
| $ty::TSTypeAssertion(_)
| $ty::TSInstantiationExpression(_)
| $ty::ArrayAssignmentTarget(_)
| $ty::ObjectAssignmentTarget(_)
};
@ -1146,6 +1147,7 @@ pub enum SimpleAssignmentTarget<'a> {
TSSatisfiesExpression(Box<'a, TSSatisfiesExpression<'a>>) = 2,
TSNonNullExpression(Box<'a, TSNonNullExpression<'a>>) = 3,
TSTypeAssertion(Box<'a, TSTypeAssertion<'a>>) = 4,
TSInstantiationExpression(Box<'a, TSInstantiationExpression<'a>>) = 5,
// `MemberExpression` variants added here by `inherit_variants!` macro
@inherit MemberExpression
}
@ -1164,6 +1166,7 @@ macro_rules! match_simple_assignment_target {
| $ty::TSSatisfiesExpression(_)
| $ty::TSNonNullExpression(_)
| $ty::TSTypeAssertion(_)
| $ty::TSInstantiationExpression(_)
};
}
pub use match_simple_assignment_target;

View file

@ -313,6 +313,7 @@ macro_rules! inherit_variants {
TSSatisfiesExpression,
TSNonNullExpression,
TSTypeAssertion,
TSInstantiationExpression,
ArrayAssignmentTarget,
ObjectAssignmentTarget,
]
@ -344,6 +345,8 @@ macro_rules! inherit_variants {
TSNonNullExpression(Box<'a, TSNonNullExpression<'a>>) = 3,
/// Inherited from [`SimpleAssignmentTarget`]
TSTypeAssertion(Box<'a, TSTypeAssertion<'a>>) = 4,
/// Inherited from [`SimpleAssignmentTarget`]
TSInstantiationExpression(Box<'a, TSInstantiationExpression<'a>>) = 5,
// Inherited from `MemberExpression`
@inherit MemberExpression
@ -368,7 +371,8 @@ macro_rules! inherit_variants {
TSAsExpression,
TSSatisfiesExpression,
TSNonNullExpression,
TSTypeAssertion
TSTypeAssertion,
TSInstantiationExpression
]
);
};

View file

@ -276,6 +276,7 @@ impl<'a> GetSpan for AssignmentTarget<'a> {
Self::TSSatisfiesExpression(expr) => expr.span,
Self::TSNonNullExpression(expr) => expr.span,
Self::TSTypeAssertion(expr) => expr.span,
Self::TSInstantiationExpression(expr) => expr.span,
// `AssignmentTargetPattern`
Self::ComputedMemberExpression(expr) => expr.span,
Self::StaticMemberExpression(expr) => expr.span,
@ -464,6 +465,7 @@ impl<'a> GetSpan for ForStatementLeft<'a> {
Self::TSSatisfiesExpression(x) => x.span,
Self::TSNonNullExpression(x) => x.span,
Self::TSTypeAssertion(x) => x.span,
Self::TSInstantiationExpression(x) => x.span,
Self::ArrayAssignmentTarget(x) => x.span,
Self::ObjectAssignmentTarget(x) => x.span,
Self::UsingDeclaration(x) => x.span,
@ -479,6 +481,7 @@ impl<'a> GetSpan for SimpleAssignmentTarget<'a> {
Self::TSSatisfiesExpression(expr) => expr.span,
Self::TSNonNullExpression(expr) => expr.span,
Self::TSTypeAssertion(expr) => expr.span,
Self::TSInstantiationExpression(expr) => expr.span,
// `MemberExpression`
Self::ComputedMemberExpression(expr) => expr.span,
Self::StaticMemberExpression(expr) => expr.span,

View file

@ -1861,6 +1861,9 @@ pub mod walk {
SimpleAssignmentTarget::TSTypeAssertion(expr) => {
visitor.visit_expression(&expr.expression);
}
SimpleAssignmentTarget::TSInstantiationExpression(expr) => {
visitor.visit_expression(&expr.expression);
}
}
visitor.leave_node(kind);
}

View file

@ -1940,6 +1940,9 @@ pub mod walk_mut {
SimpleAssignmentTarget::TSTypeAssertion(expr) => {
visitor.visit_expression(&mut expr.expression);
}
SimpleAssignmentTarget::TSInstantiationExpression(expr) => {
visitor.visit_expression(&mut expr.expression);
}
}
visitor.leave_node(kind);
}

View file

@ -1790,6 +1790,7 @@ impl<'a, const MINIFY: bool> GenExpr<MINIFY> for SimpleAssignmentTarget<'a> {
Self::TSSatisfiesExpression(e) => e.expression.gen_expr(p, precedence, ctx),
Self::TSNonNullExpression(e) => e.expression.gen_expr(p, precedence, ctx),
Self::TSTypeAssertion(e) => e.gen_expr(p, precedence, ctx),
Self::TSInstantiationExpression(e) => e.expression.gen_expr(p, precedence, ctx),
}
}
}

View file

@ -127,6 +127,9 @@ fn assignment_target_eq_expr<'a>(
SimpleAssignmentTarget::TSTypeAssertion(ts_expr) => {
is_same_reference(&ts_expr.expression, right_expr, ctx)
}
SimpleAssignmentTarget::TSInstantiationExpression(ts_expr) => {
is_same_reference(&ts_expr.expression, right_expr, ctx)
}
};
}

View file

@ -248,6 +248,13 @@ impl<'a> ParserImpl<'a> {
}
}
pub(crate) fn re_lex_ts_r_angle(&mut self) {
let kind = self.cur_kind();
if matches!(kind, Kind::ShiftRight | Kind::ShiftRight3) {
self.token = self.lexer.re_lex_as_typescript_r_angle(kind);
}
}
pub(crate) fn checkpoint(&self) -> ParserCheckpoint<'a> {
ParserCheckpoint {
lexer: self.lexer.checkpoint(),

View file

@ -56,6 +56,9 @@ impl<'a> CoverGrammar<'a, Expression<'a>> for SimpleAssignmentTarget<'a> {
Ok(SimpleAssignmentTarget::TSNonNullExpression(expr))
}
Expression::TSTypeAssertion(expr) => Ok(SimpleAssignmentTarget::TSTypeAssertion(expr)),
Expression::TSInstantiationExpression(expr) => {
Ok(SimpleAssignmentTarget::TSInstantiationExpression(expr))
}
expr => Err(diagnostics::InvalidAssignment(expr.span()).into()),
}
}

View file

@ -644,7 +644,7 @@ impl Kind {
pub fn can_follow_type_arguments_in_expr(self) -> bool {
matches!(self, Self::LParen | Self::NoSubstitutionTemplate | Self::TemplateHead
| Self::Comma | Self::Dot | Self::QuestionDot | Self::RParen | Self::RBrack
| Self::Colon | Self::Semicolon | Self::Question | Self::Eq3 | Self::Eq2
| Self::Colon | Self::Semicolon | Self::Question | Self::Eq3 | Self::Eq2 | Self::Eq
| Self::Neq | Self::Neq2 | Self::Amp2 | Self::Pipe2 | Self::Question2
| Self::Caret | Self::Amp | Self::Pipe | Self::RCurly | Self::Eof)
}

View file

@ -14,4 +14,18 @@ impl<'a> Lexer<'a> {
self.lookahead.clear();
self.finish_next(kind)
}
/// Re-tokenize '>>' and '>>>' to '>'
pub(crate) fn re_lex_as_typescript_r_angle(&mut self, kind: Kind) -> Token {
let offset = match kind {
Kind::ShiftRight => 2,
Kind::ShiftRight3 => 3,
_ => unreachable!(),
};
self.token.start = self.offset() - offset;
self.source.back(offset as usize - 1);
let kind = Kind::RAngle;
self.lookahead.clear();
self.finish_next(kind)
}
}

View file

@ -154,11 +154,21 @@ impl<'a> NormalList<'a> for TSInterfaceOrObjectBodyList<'a> {
pub struct TSTypeArgumentList<'a> {
pub params: Vec<'a, TSType<'a>>,
in_expression: bool,
}
impl<'a> TSTypeArgumentList<'a> {
pub fn parse(p: &mut ParserImpl<'a>, in_expression: bool) -> Result<Self> {
let mut list = Self::new(p);
list.in_expression = in_expression;
list.parse_list(p)?;
Ok(list)
}
}
impl<'a> SeparatedList<'a> for TSTypeArgumentList<'a> {
fn new(p: &ParserImpl<'a>) -> Self {
Self { params: p.ast.new_vec() }
Self { params: p.ast.new_vec(), in_expression: false }
}
fn open(&self) -> Kind {
@ -174,6 +184,36 @@ impl<'a> SeparatedList<'a> for TSTypeArgumentList<'a> {
self.params.push(ty);
Ok(())
}
fn parse_list(&mut self, p: &mut ParserImpl<'a>) -> Result<()> {
p.expect(self.open())?;
let mut first = true;
while !p.at(self.close()) && !p.at(Kind::Eof) {
if first {
first = false;
} else {
p.expect(self.separator())?;
if p.at(self.close()) {
break;
}
}
self.parse_element(p)?;
}
if self.in_expression {
// `a < b> = c`` is valid but `a < b >= c` is BinaryExpression
let kind = p.re_lex_right_angle();
if matches!(kind, Kind::GtEq) {
return Err(p.unexpected());
}
p.re_lex_ts_r_angle();
}
p.expect(self.close())?;
Ok(())
}
}
pub struct TSImportAttributeList<'a> {

View file

@ -514,7 +514,7 @@ impl<'a> ParserImpl<'a> {
return Ok(None);
}
let span = self.start_span();
let params = TSTypeArgumentList::parse(self)?.params;
let params = TSTypeArgumentList::parse(self, false)?.params;
Ok(Some(self.ast.ts_type_arguments(self.end_span(span), params)))
}
@ -529,7 +529,7 @@ impl<'a> ParserImpl<'a> {
self.try_parse(|p| {
p.re_lex_ts_l_angle();
let params = TSTypeArgumentList::parse(p)?.params;
let params = TSTypeArgumentList::parse(p, true)?.params;
let token = p.cur_token();
if token.is_on_new_line || token.kind.can_follow_type_arguments_in_expr() {
Ok(params)

View file

@ -1809,6 +1809,7 @@ impl<'a> Format<'a> for SimpleAssignmentTarget<'a> {
Self::TSSatisfiesExpression(expr) => expr.expression.format(p),
Self::TSNonNullExpression(expr) => expr.expression.format(p),
Self::TSTypeAssertion(expr) => expr.expression.format(p),
Self::TSInstantiationExpression(expr) => expr.expression.format(p),
}
}
}

View file

@ -590,6 +590,9 @@ impl<'a> Prettier<'a> {
AssignmentTarget::TSTypeAssertion(e) => {
Self::starts_with_no_lookahead_token(&e.expression, span)
}
AssignmentTarget::TSInstantiationExpression(e) => {
Self::starts_with_no_lookahead_token(&e.expression, span)
}
AssignmentTarget::ArrayAssignmentTarget(_)
| AssignmentTarget::ObjectAssignmentTarget(_) => false,
},
@ -636,6 +639,9 @@ impl<'a> Prettier<'a> {
SimpleAssignmentTarget::TSTypeAssertion(e) => {
Self::starts_with_no_lookahead_token(&e.expression, span)
}
SimpleAssignmentTarget::TSInstantiationExpression(e) => {
Self::starts_with_no_lookahead_token(&e.expression, span)
}
}
}
Expression::SequenceExpression(e) => e

View file

@ -915,6 +915,7 @@ pub(crate) unsafe fn walk_assignment_target<'a, Tr: Traverse<'a>>(
| AssignmentTarget::TSSatisfiesExpression(_)
| AssignmentTarget::TSNonNullExpression(_)
| AssignmentTarget::TSTypeAssertion(_)
| AssignmentTarget::TSInstantiationExpression(_)
| AssignmentTarget::ComputedMemberExpression(_)
| AssignmentTarget::StaticMemberExpression(_)
| AssignmentTarget::PrivateFieldExpression(_) => {
@ -950,6 +951,9 @@ pub(crate) unsafe fn walk_simple_assignment_target<'a, Tr: Traverse<'a>>(
SimpleAssignmentTarget::TSTypeAssertion(node) => {
walk_ts_type_assertion(traverser, (&mut **node) as *mut _, ctx)
}
SimpleAssignmentTarget::TSInstantiationExpression(node) => {
walk_ts_instantiation_expression(traverser, (&mut **node) as *mut _, ctx)
}
SimpleAssignmentTarget::ComputedMemberExpression(_)
| SimpleAssignmentTarget::StaticMemberExpression(_)
| SimpleAssignmentTarget::PrivateFieldExpression(_) => {
@ -1062,6 +1066,7 @@ pub(crate) unsafe fn walk_assignment_target_maybe_default<'a, Tr: Traverse<'a>>(
| AssignmentTargetMaybeDefault::TSSatisfiesExpression(_)
| AssignmentTargetMaybeDefault::TSNonNullExpression(_)
| AssignmentTargetMaybeDefault::TSTypeAssertion(_)
| AssignmentTargetMaybeDefault::TSInstantiationExpression(_)
| AssignmentTargetMaybeDefault::ArrayAssignmentTarget(_)
| AssignmentTargetMaybeDefault::ObjectAssignmentTarget(_)
| AssignmentTargetMaybeDefault::ComputedMemberExpression(_)
@ -1757,6 +1762,7 @@ pub(crate) unsafe fn walk_for_statement_left<'a, Tr: Traverse<'a>>(
| ForStatementLeft::TSSatisfiesExpression(_)
| ForStatementLeft::TSNonNullExpression(_)
| ForStatementLeft::TSTypeAssertion(_)
| ForStatementLeft::TSInstantiationExpression(_)
| ForStatementLeft::ArrayAssignmentTarget(_)
| ForStatementLeft::ObjectAssignmentTarget(_)
| ForStatementLeft::ComputedMemberExpression(_)

View file

@ -1,6 +1,6 @@
parser_babel Summary:
AST Parsed : 2091/2099 (99.62%)
Positive Passed: 2084/2099 (99.29%)
AST Parsed : 2093/2099 (99.71%)
Positive Passed: 2086/2099 (99.38%)
Negative Passed: 1363/1501 (90.81%)
Expect Syntax Error: "annex-b/disabled/1.1-html-comments-close/input.js"
Expect Syntax Error: "annex-b/disabled/3.1-sloppy-labeled-functions/input.js"
@ -163,24 +163,6 @@ Expect to Parse: "typescript/arrow-function/generic-tsx-babel-7/input.ts"
╭─[typescript/arrow-function/generic-tsx-babel-7/input.ts:3:1]
2 │ <T>(a: T): T => a;
╰────
Expect to Parse: "typescript/assign/TSTypeParameterInstantiation/input.ts"
× Unexpected token
╭─[typescript/assign/TSTypeParameterInstantiation/input.ts:15:31]
14 │
15 │ cls.myFunc<ConcreteClass> = (instance) => {
· ─
16 │ console.log(instance.myField);
╰────
Expect to Parse: "typescript/assign/TSTypeParameterInstantiation-babel-7/input.ts"
× Unexpected token
╭─[typescript/assign/TSTypeParameterInstantiation-babel-7/input.ts:15:31]
14 │
15 │ cls.myFunc<ConcreteClass> = (instance) => {
· ─
16 │ console.log(instance.myField);
╰────
Expect to Parse: "typescript/class/constructor-with-modifier-names/input.ts"
× Multiple constructor implementations are not allowed.

View file

@ -1,4 +1,4 @@
Passed: 295/362
Passed: 296/362
# All Passed:
* babel-plugin-transform-react-display-name
@ -23,7 +23,7 @@ Passed: 295/362
* opts/optimizeConstEnums/input.ts
* opts/rewriteImportExtensions/input.ts
# babel-plugin-transform-typescript (118/156)
# babel-plugin-transform-typescript (119/156)
* class/accessor-allowDeclareFields-false/input.ts
* class/accessor-allowDeclareFields-true/input.ts
* enum/mix-references/input.ts
@ -33,7 +33,6 @@ Passed: 295/362
* exports/export-type-star-from/input.ts
* imports/enum-value/input.ts
* imports/type-only-export-specifier-2/input.ts
* lvalues/TSTypeParameterInstantiation/input.ts
* namespace/ambient-module-nested/input.ts
* namespace/ambient-module-nested-exported/input.ts
* namespace/canonical/input.ts