Skip to content

Commit

Permalink
refactor(biome_js_parser/syntax): use enumflags2 for `ExpressionConte…
Browse files Browse the repository at this point in the history
…xtFlag` (#3799)
  • Loading branch information
Javimtib92 authored Sep 5, 2024
1 parent 689d205 commit 31d43b7
Showing 1 changed file with 62 additions and 22 deletions.
84 changes: 62 additions & 22 deletions crates/biome_js_parser/src/syntax/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
//!
//! See the [ECMAScript spec](https://www.ecma-international.org/ecma-262/5.1/#sec-11).
use std::ops::{BitOr, BitOrAssign, Sub};

use super::metavariable::{is_at_metavariable, parse_metavariable};
use super::typescript::*;
use crate::lexer::{JsLexContext, JsReLexContext};
Expand Down Expand Up @@ -35,35 +37,73 @@ use biome_js_syntax::{JsSyntaxKind::*, *};
use biome_parser::diagnostic::expected_token;
use biome_parser::parse_lists::ParseSeparatedList;
use biome_parser::ParserProgress;
use bitflags::bitflags;
use enumflags2::{bitflags, make_bitflags, BitFlags};

pub const EXPR_RECOVERY_SET: TokenSet<JsSyntaxKind> =
token_set![VAR_KW, R_PAREN, L_PAREN, L_BRACK, R_BRACK];

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub(crate) struct ExpressionContext(ExpressionContextFlags);

bitflags! {
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
struct ExpressionContextFlags: u8 {
/// Whether `in` should be counted in a binary expression.
/// This is for `for...in` statements to prevent ambiguity.
/// Corresponds to `[+In]` in the EcmaScript spec if true
const INCLUDE_IN = 1 << 0;
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[bitflags]
#[repr(u8)]
enum ExpressionContextFlag {
IncludeIn = 1 << 0,
AllowObjectExpression = 1 << 1,
InDecorator = 1 << 2,
AllowTSTypeAssertion = 1 << 3,
}

#[derive(Debug, Clone, Copy, Eq, PartialEq)]
struct ExpressionContextFlags(BitFlags<ExpressionContextFlag>);

impl ExpressionContextFlags {
/// Whether `in` should be counted in a binary expression.
/// This is for `for...in` statements to prevent ambiguity.
/// Corresponds to `[+In]` in the EcmaScript spec if true
const INCLUDE_IN: Self = Self(make_bitflags!(ExpressionContextFlag::{IncludeIn}));

/// If false, object expressions are not allowed to be parsed
/// inside an expression.
///
/// Also applies for object patterns
const ALLOW_OBJECT_EXPRESSION = 1 << 1;
/// If false, object expressions are not allowed to be parsed
/// inside an expression.
///
/// Also applies for object patterns
const ALLOW_OBJECT_EXPRESSION: Self =
Self(make_bitflags!(ExpressionContextFlag::{AllowObjectExpression}));

/// If `true` then, don't parse computed member expressions because they can as well indicate
/// the start of a computed class member.
const IN_DECORATOR: Self = Self(make_bitflags!(ExpressionContextFlag::{InDecorator}));

/// If `true` allows a typescript type assertion.
/// Currently disabled on "new" expressions.
const ALLOW_TS_TYPE_ASSERTION: Self =
Self(make_bitflags!(ExpressionContextFlag::{AllowTSTypeAssertion}));

pub fn contains(&self, other: impl Into<ExpressionContextFlags>) -> bool {
self.0.contains(other.into().0)
}
}

impl BitOr for ExpressionContextFlags {
type Output = Self;

fn bitor(self, rhs: Self) -> Self::Output {
ExpressionContextFlags(self.0 | rhs.0)
}
}

impl BitOrAssign for ExpressionContextFlags {
fn bitor_assign(&mut self, rhs: Self) {
self.0 |= rhs.0;
}
}

/// If `true` then, don't parse computed member expressions because they can as well indicate
/// the start of a computed class member.
const IN_DECORATOR = 1 << 2;
impl Sub for ExpressionContextFlags {
type Output = Self;

/// If `true` allows a typescript type assertion.
/// Currently disabled on "new" expressions.
const ALLOW_TS_TYPE_ASSERTION = 1 << 3;
fn sub(self, rhs: Self) -> Self::Output {
Self(self.0 & !rhs.0)
}
}

Expand All @@ -85,18 +125,18 @@ impl ExpressionContext {
}

/// Returns true if object expressions or object patterns are valid in this context
pub(crate) const fn is_object_expression_allowed(&self) -> bool {
pub(crate) fn is_object_expression_allowed(&self) -> bool {
self.0
.contains(ExpressionContextFlags::ALLOW_OBJECT_EXPRESSION)
}

/// Returns `true` if the expression parsing includes binary in expressions.
pub(crate) const fn is_in_included(&self) -> bool {
pub(crate) fn is_in_included(&self) -> bool {
self.0.contains(ExpressionContextFlags::INCLUDE_IN)
}

/// Returns `true` if currently parsing a decorator expression `@<expr>`.
pub(crate) const fn is_in_decorator(&self) -> bool {
pub(crate) fn is_in_decorator(&self) -> bool {
self.0.contains(ExpressionContextFlags::IN_DECORATOR)
}

Expand Down

0 comments on commit 31d43b7

Please sign in to comment.