Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(ast)!: change 'raw' from &str to Option<Atom> #7547

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions crates/oxc_ast/src/ast/literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ pub struct NumericLiteral<'a> {
/// The value of the number, converted into base 10
pub value: f64,
/// The number as it appears in source code
pub raw: &'a str,
///
/// `None` when this ast node is not constructed from the parser.
pub raw: Option<Atom<'a>>,
/// The base representation used by the literal in source code
#[estree(skip)]
pub base: NumberBase,
Expand Down Expand Up @@ -114,7 +116,9 @@ pub struct RegExpLiteral<'a> {
#[estree(skip)]
pub regex: RegExp<'a>,
/// The regular expression as it appears in source code
pub raw: &'a str,
///
/// `None` when this ast node is not constructed from the parser.
pub raw: Option<Atom<'a>>,
}

/// A regular expression
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_ast/src/ast_builder_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ impl<'a> AstBuilder<'a> {
/// `0`
#[inline]
pub fn number_0(self) -> Expression<'a> {
self.expression_numeric_literal(Span::default(), 0.0, "0", NumberBase::Decimal)
self.expression_numeric_literal(Span::default(), 0.0, None, NumberBase::Decimal)
}

/// `void 0`
Expand Down
4 changes: 2 additions & 2 deletions crates/oxc_ast/src/ast_impl/js.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ impl<'a> Expression<'a> {

/// Determines whether the given numeral literal's raw value is exactly val
pub fn is_specific_raw_number_literal(&self, val: &str) -> bool {
matches!(self, Self::NumericLiteral(lit) if lit.raw == val)
matches!(self, Self::NumericLiteral(lit) if lit.raw.as_ref().is_some_and(|raw| raw == val))
}

/// Determines whether the given expr evaluate to `undefined`
Expand Down Expand Up @@ -502,7 +502,7 @@ impl<'a> ComputedMemberExpression<'a> {
{
Some(lit.quasis[0].value.raw.clone())
}
Expression::RegExpLiteral(lit) => Some(Atom::from(lit.raw)),
Expression::RegExpLiteral(lit) => lit.raw.clone(),
_ => None,
}
}
Expand Down
16 changes: 15 additions & 1 deletion crates/oxc_ast/src/ast_impl/literal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@ impl NumericLiteral<'_> {
int32bit as i32
}
}

/// Return raw source code for `NumericLiteral`.
/// If `raw` is `None` (node is generated, not parsed from source), fallback to formatting `value`.
pub fn raw_str(&self) -> Cow<str> {
match self.raw.as_ref() {
Some(raw) => Cow::Borrowed(raw),
None => Cow::Owned(format!("{}", self.value)),
}
}
}

impl ContentHash for NumericLiteral<'_> {
Expand All @@ -82,7 +91,12 @@ impl ContentHash for NumericLiteral<'_> {

impl fmt::Display for NumericLiteral<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.raw.fmt(f)
// We have 2 choices here:
// 1. Only use the `value` field. or
// 2. Use `raw` field if it's `Some`, otherwise fallback to using `value` field.
// For now, we take the 2nd approach, since `NumericLiteral::to_string` is only used in linter,
// where raw does matter.
self.raw_str().fmt(f)
}
}

Expand Down
77 changes: 29 additions & 48 deletions crates/oxc_ast/src/generated/ast_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,17 +80,14 @@ impl<'a> AstBuilder<'a> {
/// - raw: The number as it appears in source code
/// - base: The base representation used by the literal in source code
#[inline]
pub fn numeric_literal<S>(
pub fn numeric_literal(
self,
span: Span,
value: f64,
raw: S,
raw: Option<Atom<'a>>,
base: NumberBase,
) -> NumericLiteral<'a>
where
S: IntoIn<'a, &'a str>,
{
NumericLiteral { span, value, raw: raw.into_in(self.allocator), base }
) -> NumericLiteral<'a> {
NumericLiteral { span, value, raw, base }
}

/// Build a [`NumericLiteral`], and store it in the memory arena.
Expand All @@ -103,16 +100,13 @@ impl<'a> AstBuilder<'a> {
/// - raw: The number as it appears in source code
/// - base: The base representation used by the literal in source code
#[inline]
pub fn alloc_numeric_literal<S>(
pub fn alloc_numeric_literal(
self,
span: Span,
value: f64,
raw: S,
raw: Option<Atom<'a>>,
base: NumberBase,
) -> Box<'a, NumericLiteral<'a>>
where
S: IntoIn<'a, &'a str>,
{
) -> Box<'a, NumericLiteral<'a>> {
Box::new_in(self.numeric_literal(span, value, raw, base), self.allocator)
}

Expand Down Expand Up @@ -199,11 +193,13 @@ impl<'a> AstBuilder<'a> {
/// - regex: The parsed regular expression. See [`oxc_regular_expression`] for more
/// - raw: The regular expression as it appears in source code
#[inline]
pub fn reg_exp_literal<S>(self, span: Span, regex: RegExp<'a>, raw: S) -> RegExpLiteral<'a>
where
S: IntoIn<'a, &'a str>,
{
RegExpLiteral { span, regex, raw: raw.into_in(self.allocator) }
pub fn reg_exp_literal(
self,
span: Span,
regex: RegExp<'a>,
raw: Option<Atom<'a>>,
) -> RegExpLiteral<'a> {
RegExpLiteral { span, regex, raw }
}

/// Build a [`RegExpLiteral`], and store it in the memory arena.
Expand All @@ -215,15 +211,12 @@ impl<'a> AstBuilder<'a> {
/// - regex: The parsed regular expression. See [`oxc_regular_expression`] for more
/// - raw: The regular expression as it appears in source code
#[inline]
pub fn alloc_reg_exp_literal<S>(
pub fn alloc_reg_exp_literal(
self,
span: Span,
regex: RegExp<'a>,
raw: S,
) -> Box<'a, RegExpLiteral<'a>>
where
S: IntoIn<'a, &'a str>,
{
raw: Option<Atom<'a>>,
) -> Box<'a, RegExpLiteral<'a>> {
Box::new_in(self.reg_exp_literal(span, regex, raw), self.allocator)
}

Expand Down Expand Up @@ -413,16 +406,13 @@ impl<'a> AstBuilder<'a> {
/// - raw: The number as it appears in source code
/// - base: The base representation used by the literal in source code
#[inline]
pub fn expression_numeric_literal<S>(
pub fn expression_numeric_literal(
self,
span: Span,
value: f64,
raw: S,
raw: Option<Atom<'a>>,
base: NumberBase,
) -> Expression<'a>
where
S: IntoIn<'a, &'a str>,
{
) -> Expression<'a> {
Expression::NumericLiteral(self.alloc(self.numeric_literal(span, value, raw, base)))
}

Expand Down Expand Up @@ -456,15 +446,12 @@ impl<'a> AstBuilder<'a> {
/// - regex: The parsed regular expression. See [`oxc_regular_expression`] for more
/// - raw: The regular expression as it appears in source code
#[inline]
pub fn expression_reg_exp_literal<S>(
pub fn expression_reg_exp_literal(
self,
span: Span,
regex: RegExp<'a>,
raw: S,
) -> Expression<'a>
where
S: IntoIn<'a, &'a str>,
{
raw: Option<Atom<'a>>,
) -> Expression<'a> {
Expression::RegExpLiteral(self.alloc(self.reg_exp_literal(span, regex, raw)))
}

Expand Down Expand Up @@ -7911,16 +7898,13 @@ impl<'a> AstBuilder<'a> {
/// - raw: The number as it appears in source code
/// - base: The base representation used by the literal in source code
#[inline]
pub fn ts_literal_numeric_literal<S>(
pub fn ts_literal_numeric_literal(
self,
span: Span,
value: f64,
raw: S,
raw: Option<Atom<'a>>,
base: NumberBase,
) -> TSLiteral<'a>
where
S: IntoIn<'a, &'a str>,
{
) -> TSLiteral<'a> {
TSLiteral::NumericLiteral(self.alloc(self.numeric_literal(span, value, raw, base)))
}

Expand Down Expand Up @@ -7954,15 +7938,12 @@ impl<'a> AstBuilder<'a> {
/// - regex: The parsed regular expression. See [`oxc_regular_expression`] for more
/// - raw: The regular expression as it appears in source code
#[inline]
pub fn ts_literal_reg_exp_literal<S>(
pub fn ts_literal_reg_exp_literal(
self,
span: Span,
regex: RegExp<'a>,
raw: S,
) -> TSLiteral<'a>
where
S: IntoIn<'a, &'a str>,
{
raw: Option<Atom<'a>>,
) -> TSLiteral<'a> {
TSLiteral::RegExpLiteral(self.alloc(self.reg_exp_literal(span, regex, raw)))
}

Expand Down
12 changes: 9 additions & 3 deletions crates/oxc_ast/src/serialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl<'a> From<&'a NumericLiteral<'a>> for ESTreeLiteral<'a, f64> {
Self {
span: value.span,
value: value.value,
raw: Some(value.raw),
raw: value.raw.as_ref().map(oxc_span::Atom::as_str),
bigint: None,
regex: None,
}
Expand All @@ -61,7 +61,13 @@ impl<'a> From<&'a NumericLiteral<'a>> for ESTreeLiteral<'a, f64> {

impl<'a> From<&'a StringLiteral<'a>> for ESTreeLiteral<'a, &'a str> {
fn from(value: &'a StringLiteral) -> Self {
Self { span: value.span, value: &value.value, raw: None, bigint: None, regex: None }
Self {
span: value.span,
value: &value.value,
raw: value.raw.as_ref().map(oxc_span::Atom::as_str),
bigint: None,
regex: None,
}
}
}

Expand Down Expand Up @@ -107,7 +113,7 @@ impl<'a> From<&'a RegExpLiteral<'a>> for ESTreeLiteral<'a, Option<EmptyObject>>
fn from(value: &'a RegExpLiteral) -> Self {
Self {
span: value.span,
raw: Some(value.raw),
raw: value.raw.as_ref().map(oxc_span::Atom::as_str),
value: match &value.regex.pattern {
RegExpPattern::Pattern(_) => Some(EmptyObject {}),
_ => None,
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_codegen/src/gen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1155,7 +1155,7 @@ impl GenExpr for NumericLiteral<'_> {
p.add_source_mapping(self.span);
let value = self.value;
if ctx.contains(Context::TYPESCRIPT) {
p.print_str(self.raw);
p.print_str(&self.raw_str());
} else if value.is_nan() {
p.print_space_before_identifier();
p.print_str("NaN");
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_isolated_declarations/src/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ impl<'a> IsolatedDeclarations<'a> {
self.ast.expression_numeric_literal(
SPAN,
value,
value.to_string(),
None,
NumberBase::Decimal,
)
};
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/eslint/no_dupe_keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ fn prop_key_name<'a>(key: &PropertyKey<'a>, ctx: &LintContext<'a>) -> &'a str {
PropertyKey::StaticIdentifier(ident) => ident.name.as_str(),
PropertyKey::PrivateIdentifier(ident) => ident.name.as_str(),
PropertyKey::StringLiteral(lit) => lit.value.as_str(),
PropertyKey::NumericLiteral(lit) => lit.raw,
PropertyKey::NumericLiteral(lit) => lit.raw.as_ref().unwrap().as_str(),
ShuiRuTian marked this conversation as resolved.
Show resolved Hide resolved
_ => ctx.source_range(key.span()),
}
}
Expand Down
4 changes: 2 additions & 2 deletions crates/oxc_linter/src/rules/eslint/no_loss_of_precision.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ impl<'a> RawNum<'a> {

impl NoLossOfPrecision {
fn not_base_ten_loses_precision(node: &'_ NumericLiteral) -> bool {
let raw = node.raw.cow_replace('_', "");
let raw = node.raw.as_ref().unwrap().as_str().cow_replace('_', "");
let raw = raw.cow_to_uppercase();
#[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
// AST always store number as f64, need a cast to format in bin/oct/hex
Expand All @@ -200,7 +200,7 @@ impl NoLossOfPrecision {
}

fn base_ten_loses_precision(node: &'_ NumericLiteral) -> bool {
let raw = node.raw.cow_replace('_', "");
let raw = node.raw.as_ref().unwrap().as_str().cow_replace('_', "");
let Some(raw) = Self::normalize(&raw) else {
return true;
};
Expand Down
4 changes: 2 additions & 2 deletions crates/oxc_linter/src/rules/eslint/no_magic_numbers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,13 +247,13 @@ impl InternConfig<'_> {
InternConfig {
node: parent_node,
value: NoMagicNumbersNumber::Float(0.0 - numeric.value),
raw: format!("-{}", numeric.raw),
raw: format!("-{}", numeric.raw.as_ref().unwrap()),
}
} else {
InternConfig {
node: if is_unary { parent_node } else { node },
value: NoMagicNumbersNumber::Float(numeric.value),
raw: numeric.raw.into(),
raw: numeric.raw.as_ref().unwrap().as_str().into(),
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions crates/oxc_linter/src/rules/eslint/prefer_numeric_literals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,12 @@ fn check_arguments<'a>(call_expr: &CallExpression<'a>, ctx: &LintContext<'a>) {
return;
};

if let Some(name_prefix_set) = RADIX_MAP.get(numeric_lit.raw) {
let raw = numeric_lit.raw.as_ref().unwrap().as_str();
if let Some(name_prefix_set) = RADIX_MAP.get(raw) {
let name = name_prefix_set.index(0).unwrap();
let prefix = name_prefix_set.index(1).unwrap();

match is_fixable(call_expr, numeric_lit.raw) {
match is_fixable(call_expr, raw) {
Ok(argument) => {
ctx.diagnostic_with_fix(
prefer_numeric_literals_diagnostic(call_expr.span, name),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ impl Rule for NoDuplicateEnumValues {
ctx.diagnostic(no_duplicate_enum_values_diagnostic(
*old_span,
enum_member,
num.raw,
num.raw.as_ref().unwrap().as_str(),
));
} else {
seen_number_values.push((num.value, num.span));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ fn is_negative_one(expression: &Expression) -> bool {
if let Expression::NumericLiteral(value) =
&unary_expression.argument.get_inner_expression()
{
return value.raw == "1";
return value.raw.as_ref().unwrap() == "1";
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions crates/oxc_linter/src/rules/unicorn/no_zero_fractions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,11 @@ impl Rule for NoZeroFractions {
return;
};

let Some((fmt, is_dangling_dot)) = format_raw(number_literal.raw) else {
let raw = number_literal.raw.as_ref().unwrap().as_str();
let Some((fmt, is_dangling_dot)) = format_raw(raw) else {
return;
};
if fmt == number_literal.raw {
if fmt == raw {
return;
};

Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_linter/src/rules/unicorn/number_literal_case.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ declare_oxc_lint!(
impl Rule for NumberLiteralCase {
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
let (raw_literal, raw_span) = match node.kind() {
AstKind::NumericLiteral(number) => (number.raw, number.span),
AstKind::NumericLiteral(number) => (number.raw.as_ref().unwrap().as_str(), number.span),
AstKind::BigIntLiteral(number) => {
let span = number.span;
(span.source_text(ctx.source_text()), span)
Expand Down
Loading
Loading