feat(semantic): check non-simple lhs expression of assignment expression (#994)

This commit is contained in:
Boshen 2023-10-14 23:40:10 +08:00 committed by GitHub
parent dc08a21207
commit 1661385c1a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 38 additions and 21 deletions

View file

@ -807,6 +807,10 @@ pub enum AssignmentTarget<'a> {
}
impl<'a> AssignmentTarget<'a> {
pub fn is_simple(&self) -> bool {
matches!(self, Self::SimpleAssignmentTarget(_))
}
pub fn is_destructuring_pattern(&self) -> bool {
matches!(self, Self::AssignmentTargetPattern(_))
}

View file

@ -11,7 +11,7 @@ use oxc_diagnostics::{
use oxc_span::{Atom, GetSpan, ModuleKind, Span};
use oxc_syntax::{
module_record::ExportLocalName,
operator::{BinaryOperator, LogicalOperator, UnaryOperator},
operator::{AssignmentOperator, BinaryOperator, LogicalOperator, UnaryOperator},
NumberBase,
};
use phf::{phf_set, Set};
@ -65,12 +65,14 @@ impl EarlyErrorJavaScript {
AstKind::FormalParameters(params) => check_formal_parameters(params, node, ctx),
AstKind::ArrayPattern(pat) => check_array_pattern(pat, ctx),
AstKind::ObjectExpression(expr) => check_object_expression(expr, ctx),
AstKind::AssignmentExpression(expr) => check_assignment_expression(expr, ctx),
AstKind::AwaitExpression(expr) => check_await_expression(expr, node, ctx),
AstKind::BinaryExpression(expr) => check_binary_expression(expr, ctx),
AstKind::LogicalExpression(expr) => check_logical_expression(expr, ctx),
AstKind::MemberExpression(expr) => check_member_expression(expr, ctx),
AstKind::ObjectExpression(expr) => check_object_expression(expr, ctx),
AstKind::UnaryExpression(expr) => check_unary_expression(expr, node, ctx),
AstKind::AwaitExpression(expr) => check_await_expression(expr, node, ctx),
AstKind::YieldExpression(expr) => check_yield_expression(expr, node, ctx),
_ => {}
}
@ -989,6 +991,22 @@ fn check_array_pattern(pattern: &ArrayPattern, ctx: &SemanticBuilder<'_>) {
}
}
fn check_assignment_expression(assign_expr: &AssignmentExpression, ctx: &SemanticBuilder<'_>) {
#[derive(Debug, Error, Diagnostic)]
#[error("Invalid left-hand side in assignment")]
#[diagnostic()]
struct AssignmentIsNotSimple(#[label] Span);
// AssignmentExpression :
// LeftHandSideExpression AssignmentOperator AssignmentExpression
// LeftHandSideExpression &&= AssignmentExpression
// LeftHandSideExpression ||= AssignmentExpression
// LeftHandSideExpression ??= AssignmentExpression
// It is a Syntax Error if AssignmentTargetType of LeftHandSideExpression is not SIMPLE.
if assign_expr.operator != AssignmentOperator::Assign && !assign_expr.left.is_simple() {
ctx.error(AssignmentIsNotSimple(assign_expr.left.span()));
}
}
fn check_object_expression(obj_expr: &ObjectExpression, ctx: &SemanticBuilder<'_>) {
// ObjectLiteral : { PropertyDefinitionList }
// It is a Syntax Error if PropertyNameList of PropertyDefinitionList contains any duplicate entries for "__proto__"

View file

@ -43,27 +43,17 @@ impl AssignmentOperator {
matches!(self, Self::LogicalAnd | Self::LogicalOr | Self::LogicalNullish)
}
#[rustfmt::skip]
pub fn is_arithmetic(self) -> bool {
matches!(
self,
Self::Addition
| Self::Subtraction
| Self::Multiplication
| Self::Division
| Self::Remainder
| Self::Exponential
matches!(self, Self::Addition | Self::Subtraction | Self::Multiplication
| Self::Division | Self::Remainder | Self::Exponential
)
}
#[rustfmt::skip]
pub fn is_bitwise(self) -> bool {
matches!(
self,
Self::BitwiseOR
| Self::BitwiseXOR
| Self::BitwiseAnd
| Self::ShiftLeft
| Self::ShiftRight
| Self::ShiftRightZeroFill
matches!(self, Self::BitwiseOR | Self::BitwiseXOR | Self::BitwiseAnd
| Self::ShiftLeft | Self::ShiftRight | Self::ShiftRightZeroFill
)
}

View file

@ -1,7 +1,7 @@
parser_babel Summary:
AST Parsed : 2072/2078 (99.71%)
Positive Passed: 2069/2078 (99.57%)
Negative Passed: 1342/1507 (89.05%)
Negative Passed: 1343/1507 (89.12%)
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"
Expect Syntax Error: "annex-b/disabled/3.1-sloppy-labeled-functions-if-body/input.js"
@ -24,7 +24,6 @@ Expect Syntax Error: "es2015/object/disallow-duplicate-method-params/input.js"
Expect Syntax Error: "es2015/uncategorised/.191/input.js"
Expect Syntax Error: "es2015/uncategorised/.335/input.js"
Expect Syntax Error: "es2015/uncategorised/.343/input.js"
Expect Syntax Error: "es2015/uncategorised/220/input.js"
Expect Syntax Error: "es2015/uncategorised/297/input.js"
Expect Syntax Error: "es2017/async-functions/await-binding-inside-arrow-params-inside-async-arrow-params/input.js"
Expect Syntax Error: "es2017/trailing-function-commas/7/input.js"
@ -3559,6 +3558,12 @@ Expect to Parse: "typescript/types/const-type-parameters-babel-7/input.ts"
· ─────
╰────
× Invalid left-hand side in assignment
╭─[es2015/uncategorised/220/input.js:1:1]
1 │ [v] += ary
· ───
╰────
× Cannot assign to this expression
╭─[es2015/uncategorised/221/input.js:1:1]
1 │ [2] = 42