mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 12:19:15 +00:00
feat(parser): fix incorrect AST for x?.f<T>() (#7387)
This commit is contained in:
parent
885e37f8eb
commit
e6922df3bb
5 changed files with 45 additions and 16 deletions
|
|
@ -261,6 +261,10 @@ fn test() {
|
|||
"disallowArithmeticOperators": false
|
||||
}])),
|
||||
),
|
||||
("x?.f<T>();", None),
|
||||
("x?.f?.<T>();", None),
|
||||
("f?.<Q>();", None),
|
||||
("a?.c?.b<c>", None),
|
||||
];
|
||||
|
||||
let fail = vec![
|
||||
|
|
|
|||
|
|
@ -101,6 +101,9 @@ fn test() {
|
|||
("a?.c?.b<c>", None),
|
||||
("foo?.bar!", None),
|
||||
("foo?.[bar]!", None),
|
||||
("x?.f<T>();", None),
|
||||
("x?.f?.<T>();", None),
|
||||
("f?.<Q>();", None),
|
||||
(
|
||||
"var x = a?.b",
|
||||
Some(serde_json::json!([{
|
||||
|
|
|
|||
|
|
@ -74,6 +74,24 @@ snapshot_kind: text
|
|||
· ───────────
|
||||
╰────
|
||||
|
||||
⚠ oxc(no-optional-chaining): Optional chaining is not allowed.
|
||||
╭─[no_optional_chaining.tsx:1:1]
|
||||
1 │ x?.f<T>();
|
||||
· ─────────
|
||||
╰────
|
||||
|
||||
⚠ oxc(no-optional-chaining): Optional chaining is not allowed.
|
||||
╭─[no_optional_chaining.tsx:1:1]
|
||||
1 │ x?.f?.<T>();
|
||||
· ───────────
|
||||
╰────
|
||||
|
||||
⚠ oxc(no-optional-chaining): Optional chaining is not allowed.
|
||||
╭─[no_optional_chaining.tsx:1:1]
|
||||
1 │ f?.<Q>();
|
||||
· ────────
|
||||
╰────
|
||||
|
||||
⚠ oxc(no-optional-chaining): Optional chaining is not allowed.
|
||||
╭─[no_optional_chaining.tsx:1:9]
|
||||
1 │ var x = a?.b
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use oxc_allocator::Box;
|
|||
use oxc_ast::ast::*;
|
||||
use oxc_diagnostics::Result;
|
||||
use oxc_regular_expression::ast::Pattern;
|
||||
use oxc_span::{Atom, Span};
|
||||
use oxc_span::{Atom, GetSpan, Span};
|
||||
use oxc_syntax::{
|
||||
number::{BigintBase, NumberBase},
|
||||
operator::BinaryOperator,
|
||||
|
|
@ -576,25 +576,33 @@ impl<'a> ParserImpl<'a> {
|
|||
let mut in_optional_chain = false;
|
||||
let lhs = self.parse_member_expression_or_higher(&mut in_optional_chain)?;
|
||||
let lhs = self.parse_call_expression_rest(span, lhs, &mut in_optional_chain)?;
|
||||
if in_optional_chain {
|
||||
if !in_optional_chain {
|
||||
return Ok(lhs);
|
||||
}
|
||||
// Add `ChainExpression` to `a?.c?.b<c>`;
|
||||
if let Expression::TSInstantiationExpression(mut expr) = lhs {
|
||||
expr.expression = self.map_to_chain_expression(
|
||||
expr.expression.span(),
|
||||
self.ast.move_expression(&mut expr.expression),
|
||||
);
|
||||
Ok(Expression::TSInstantiationExpression(expr))
|
||||
} else {
|
||||
let span = self.end_span(span);
|
||||
Ok(self.map_to_chain_expression(span, lhs))
|
||||
} else {
|
||||
Ok(lhs)
|
||||
}
|
||||
}
|
||||
|
||||
fn map_to_chain_expression(&mut self, span: Span, expr: Expression<'a>) -> Expression<'a> {
|
||||
fn map_to_chain_expression(&self, span: Span, expr: Expression<'a>) -> Expression<'a> {
|
||||
match expr {
|
||||
match_member_expression!(Expression) => {
|
||||
let member_expr = expr.into_member_expression();
|
||||
self.ast.expression_chain(span, ChainElement::from(member_expr))
|
||||
}
|
||||
Expression::CallExpression(result) => {
|
||||
self.ast.expression_chain(span, ChainElement::CallExpression(result))
|
||||
Expression::CallExpression(e) => {
|
||||
self.ast.expression_chain(span, ChainElement::CallExpression(e))
|
||||
}
|
||||
Expression::TSNonNullExpression(result) => {
|
||||
self.ast.expression_chain(span, ChainElement::TSNonNullExpression(result))
|
||||
Expression::TSNonNullExpression(e) => {
|
||||
self.ast.expression_chain(span, ChainElement::TSNonNullExpression(e))
|
||||
}
|
||||
expr => expr,
|
||||
}
|
||||
|
|
@ -677,15 +685,9 @@ impl<'a> ParserImpl<'a> {
|
|||
self.parse_tagged_template(lhs_span, expr, *in_optional_chain, type_parameters)?
|
||||
}
|
||||
Kind::LAngle | Kind::ShiftLeft => {
|
||||
let optional_chain_span = (*in_optional_chain).then(|| self.end_span(lhs_span));
|
||||
if let Some(Some(arguments)) =
|
||||
self.try_parse(Self::parse_type_arguments_in_expression)
|
||||
{
|
||||
// `a?.c?.b<c>`
|
||||
if let Some(optional_chain_span) = optional_chain_span {
|
||||
*in_optional_chain = false;
|
||||
lhs = self.map_to_chain_expression(optional_chain_span, lhs);
|
||||
}
|
||||
lhs = self.ast.expression_ts_instantiation(
|
||||
self.end_span(lhs_span),
|
||||
lhs,
|
||||
|
|
|
|||
|
|
@ -1987,7 +1987,9 @@ after transform: ["C", "T"]
|
|||
rebuilt : ["C"]
|
||||
|
||||
* type-arguments/optional-call/input.ts
|
||||
x Output mismatch
|
||||
Unresolved references mismatch:
|
||||
after transform: ["Q", "T", "f", "x"]
|
||||
rebuilt : ["f", "x"]
|
||||
|
||||
* type-arguments/tagged-template/input.ts
|
||||
Unresolved references mismatch:
|
||||
|
|
|
|||
Loading…
Reference in a new issue