mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
refactor(ast)!: change 'raw' from &str to Option<Atom> (#7547)
Fix #7254 Changed all "raw" properties of literal types (if they have this property) to `Option<Atom>`. --------- Co-authored-by: overlookmotel <theoverlookmotel@gmail.com>
This commit is contained in:
parent
e5145b0083
commit
ebc80f6749
33 changed files with 125 additions and 128 deletions
|
|
@ -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,
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<'_> {
|
||||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
@ -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.
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
@ -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)))
|
||||
}
|
||||
|
||||
|
|
@ -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)))
|
||||
}
|
||||
|
||||
|
|
@ -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)))
|
||||
}
|
||||
|
||||
|
|
@ -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)))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ impl<'a> IsolatedDeclarations<'a> {
|
|||
self.ast.expression_numeric_literal(
|
||||
SPAN,
|
||||
value,
|
||||
value.to_string(),
|
||||
None,
|
||||
NumberBase::Decimal,
|
||||
)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
_ => ctx.source_range(key.span()),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -86,13 +86,14 @@ impl Rule for NumericSeparatorsStyle {
|
|||
fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) {
|
||||
match node.kind() {
|
||||
AstKind::NumericLiteral(number) => {
|
||||
if self.only_if_contains_separator && !number.raw.contains('_') {
|
||||
let raw = number.raw.as_ref().unwrap().as_str();
|
||||
if self.only_if_contains_separator && !raw.contains('_') {
|
||||
return;
|
||||
}
|
||||
|
||||
let formatted = self.format_number(number);
|
||||
|
||||
if formatted != number.raw {
|
||||
if formatted != raw {
|
||||
ctx.diagnostic_with_fix(
|
||||
numeric_separators_style_diagnostic(number.span),
|
||||
|fixer| fixer.replace(number.span, formatted),
|
||||
|
|
@ -151,11 +152,12 @@ impl NumericSeparatorsStyle {
|
|||
fn format_number(&self, number: &NumericLiteral) -> String {
|
||||
use oxc_syntax::number::NumberBase;
|
||||
|
||||
let raw = number.raw.as_ref().unwrap();
|
||||
match number.base {
|
||||
NumberBase::Binary => self.format_binary(number.raw),
|
||||
NumberBase::Decimal | NumberBase::Float => self.format_decimal(number.raw),
|
||||
NumberBase::Hex => self.format_hex(number.raw),
|
||||
NumberBase::Octal => self.format_octal(number.raw),
|
||||
NumberBase::Binary => self.format_binary(raw),
|
||||
NumberBase::Decimal | NumberBase::Float => self.format_decimal(raw),
|
||||
NumberBase::Hex => self.format_hex(raw),
|
||||
NumberBase::Octal => self.format_octal(raw),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ impl Rule for PreferArrayFlatMap {
|
|||
|
||||
if let Some(first_arg) = flat_call_expr.arguments.first() {
|
||||
if let Argument::NumericLiteral(number_lit) = first_arg {
|
||||
if number_lit.raw != "1" {
|
||||
if number_lit.raw.as_ref().unwrap() != "1" {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ impl Rule for PreferArraySome {
|
|||
return;
|
||||
};
|
||||
|
||||
if right_num_lit.raw == "0"
|
||||
if right_num_lit.raw.as_ref().unwrap().as_str() == "0"
|
||||
&& is_method_call(
|
||||
left_call_expr,
|
||||
None,
|
||||
|
|
@ -207,7 +207,7 @@ impl Rule for PreferArraySome {
|
|||
return;
|
||||
};
|
||||
|
||||
if right_num_lit.raw != "0" {
|
||||
if right_num_lit.raw.as_ref().unwrap() != "0" {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ impl Rule for PreferIncludes {
|
|||
return;
|
||||
};
|
||||
|
||||
if num_lit.raw != "0" {
|
||||
if num_lit.raw.as_ref().unwrap() != "0" {
|
||||
return;
|
||||
}
|
||||
ctx.diagnostic(prefer_includes_diagnostic(
|
||||
|
|
@ -108,7 +108,7 @@ fn is_negative_one(expr: &Expression) -> bool {
|
|||
return false;
|
||||
};
|
||||
|
||||
num_lit.raw == "1"
|
||||
num_lit.raw.as_ref().unwrap() == "1"
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -287,7 +287,7 @@ pub fn is_same_member_expression(
|
|||
// x[/regex/] === x['/regex/']
|
||||
(Expression::StringLiteral(string_lit), Expression::RegExpLiteral(regex_lit))
|
||||
| (Expression::RegExpLiteral(regex_lit), Expression::StringLiteral(string_lit)) => {
|
||||
if string_lit.value != regex_lit.raw {
|
||||
if string_lit.value != regex_lit.raw.as_ref().unwrap() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -296,7 +296,7 @@ pub fn is_same_member_expression(
|
|||
(Expression::TemplateLiteral(template_lit), Expression::RegExpLiteral(regex_lit))
|
||||
| (Expression::RegExpLiteral(regex_lit), Expression::TemplateLiteral(template_lit)) => {
|
||||
if !(template_lit.is_no_substitution_template()
|
||||
&& template_lit.quasi().unwrap() == regex_lit.raw)
|
||||
&& template_lit.quasi().unwrap() == regex_lit.raw.as_ref().unwrap())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use oxc_ecmascript::{
|
|||
};
|
||||
use oxc_span::{GetSpan, SPAN};
|
||||
use oxc_syntax::{
|
||||
number::{NumberBase, ToJsString},
|
||||
number::NumberBase,
|
||||
operator::{BinaryOperator, LogicalOperator},
|
||||
};
|
||||
use oxc_traverse::{traverse_mut_with_ctx, Ancestor, ReusableTraverseCtx, Traverse, TraverseCtx};
|
||||
|
|
@ -310,7 +310,7 @@ impl<'a, 'b> PeepholeFoldConstants {
|
|||
let number_literal_expr = ctx.ast.expression_numeric_literal(
|
||||
right_expr.span(),
|
||||
num,
|
||||
num.to_js_string(),
|
||||
None,
|
||||
if num.fract() == 0.0 { NumberBase::Decimal } else { NumberBase::Float },
|
||||
);
|
||||
|
||||
|
|
@ -333,7 +333,7 @@ impl<'a, 'b> PeepholeFoldConstants {
|
|||
let number_literal_expr = ctx.ast.expression_numeric_literal(
|
||||
left_expr.span(),
|
||||
num,
|
||||
num.to_js_string(),
|
||||
None,
|
||||
if num.fract() == 0.0 { NumberBase::Decimal } else { NumberBase::Float },
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -124,12 +124,7 @@ impl PeepholeReplaceKnownMethods {
|
|||
};
|
||||
|
||||
#[expect(clippy::cast_precision_loss)]
|
||||
Some(ctx.ast.expression_numeric_literal(
|
||||
span,
|
||||
result as f64,
|
||||
result.to_string(),
|
||||
NumberBase::Decimal,
|
||||
))
|
||||
Some(ctx.ast.expression_numeric_literal(span, result as f64, None, NumberBase::Decimal))
|
||||
}
|
||||
|
||||
fn try_fold_string_substring_or_slice<'a>(
|
||||
|
|
@ -219,12 +214,7 @@ impl PeepholeReplaceKnownMethods {
|
|||
let result = string_lit.value.as_str().char_code_at(Some(char_at_index))?;
|
||||
|
||||
#[expect(clippy::cast_lossless)]
|
||||
Some(ctx.ast.expression_numeric_literal(
|
||||
span,
|
||||
result as f64,
|
||||
result.to_string(),
|
||||
NumberBase::Decimal,
|
||||
))
|
||||
Some(ctx.ast.expression_numeric_literal(span, result as f64, None, NumberBase::Decimal))
|
||||
}
|
||||
fn try_fold_string_replace_or_string_replace_all<'a>(
|
||||
span: Span,
|
||||
|
|
|
|||
|
|
@ -230,7 +230,7 @@ impl<'a, 'b> PeepholeSubstituteAlternateSyntax {
|
|||
let num = ctx.ast.expression_numeric_literal(
|
||||
SPAN,
|
||||
if lit.value ^ no_unary { 0.0 } else { 1.0 },
|
||||
if lit.value ^ no_unary { "0" } else { "1" },
|
||||
None,
|
||||
NumberBase::Decimal,
|
||||
);
|
||||
*expr = if no_unary {
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ impl<'a> Ctx<'a, '_> {
|
|||
ConstantValue::Number(n) => {
|
||||
let number_base =
|
||||
if is_exact_int64(n) { NumberBase::Decimal } else { NumberBase::Float };
|
||||
self.ast.expression_numeric_literal(span, n, "", number_base)
|
||||
self.ast.expression_numeric_literal(span, n, None, number_base)
|
||||
}
|
||||
ConstantValue::BigInt(n) => {
|
||||
self.ast.expression_big_int_literal(span, n.to_string() + "n", BigintBase::Decimal)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ fn test() {
|
|||
elements.push(ArrayExpressionElement::NumericLiteral(ast.alloc(ast.numeric_literal(
|
||||
SPAN,
|
||||
42f64,
|
||||
"42",
|
||||
None,
|
||||
NumberBase::Decimal,
|
||||
))));
|
||||
elements.push(ArrayExpressionElement::StringLiteral(
|
||||
|
|
|
|||
|
|
@ -321,7 +321,7 @@ impl<'a> ParserImpl<'a> {
|
|||
_ => return Err(self.unexpected()),
|
||||
};
|
||||
self.bump_any();
|
||||
Ok(self.ast.numeric_literal(self.end_span(span), value, src, base))
|
||||
Ok(self.ast.numeric_literal(self.end_span(span), value, Some(Atom::from(src)), base))
|
||||
}
|
||||
|
||||
pub(crate) fn parse_literal_bigint(&mut self) -> Result<BigIntLiteral<'a>> {
|
||||
|
|
@ -364,7 +364,11 @@ impl<'a> ParserImpl<'a> {
|
|||
pat.map_or_else(|| RegExpPattern::Invalid(pattern_text), RegExpPattern::Pattern)
|
||||
},
|
||||
);
|
||||
Ok(self.ast.reg_exp_literal(self.end_span(span), RegExp { pattern, flags }, raw))
|
||||
Ok(self.ast.reg_exp_literal(
|
||||
self.end_span(span),
|
||||
RegExp { pattern, flags },
|
||||
Some(Atom::from(raw)),
|
||||
))
|
||||
}
|
||||
|
||||
fn parse_regex_pattern(
|
||||
|
|
|
|||
|
|
@ -2153,7 +2153,7 @@ impl<'a> Format<'a> for PropertyKey<'a> {
|
|||
if need_quote {
|
||||
dynamic_text!(
|
||||
p,
|
||||
string::print_string(p, literal.raw, p.options.single_quote)
|
||||
string::print_string(p, &literal.raw_str(), p.options.single_quote)
|
||||
)
|
||||
} else {
|
||||
literal.format(p)
|
||||
|
|
|
|||
|
|
@ -221,11 +221,13 @@ pub fn check_number_literal(lit: &NumericLiteral, ctx: &SemanticBuilder<'_>) {
|
|||
// NumericLiteral :: legacy_octalIntegerLiteral
|
||||
// DecimalIntegerLiteral :: NonOctalDecimalIntegerLiteral
|
||||
// * It is a Syntax Error if the source text matched by this production is strict mode code.
|
||||
fn leading_zero(s: &str) -> bool {
|
||||
let mut chars = s.bytes();
|
||||
if let Some(first) = chars.next() {
|
||||
if let Some(second) = chars.next() {
|
||||
return first == b'0' && second.is_ascii_digit();
|
||||
fn leading_zero(s: Option<&Atom>) -> bool {
|
||||
if let Some(s) = s {
|
||||
let mut chars = s.bytes();
|
||||
if let Some(first) = chars.next() {
|
||||
if let Some(second) = chars.next() {
|
||||
return first == b'0' && second.is_ascii_digit();
|
||||
}
|
||||
}
|
||||
}
|
||||
false
|
||||
|
|
@ -233,10 +235,10 @@ pub fn check_number_literal(lit: &NumericLiteral, ctx: &SemanticBuilder<'_>) {
|
|||
|
||||
if ctx.strict_mode() {
|
||||
match lit.base {
|
||||
NumberBase::Octal if leading_zero(lit.raw) => {
|
||||
NumberBase::Octal if leading_zero(lit.raw.as_ref()) => {
|
||||
ctx.error(legacy_octal(lit.span));
|
||||
}
|
||||
NumberBase::Decimal | NumberBase::Float if leading_zero(lit.raw) => {
|
||||
NumberBase::Decimal | NumberBase::Float if leading_zero(lit.raw.as_ref()) => {
|
||||
ctx.error(leading_zero_decimal(lit.span));
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
|||
|
|
@ -154,24 +154,16 @@ impl<'a, 'ctx> JsxSource<'a, 'ctx> {
|
|||
|
||||
let line_number = {
|
||||
let key = ctx.ast.property_key_identifier_name(SPAN, "lineNumber");
|
||||
let value = ctx.ast.expression_numeric_literal(
|
||||
SPAN,
|
||||
line as f64,
|
||||
line.to_string(),
|
||||
NumberBase::Decimal,
|
||||
);
|
||||
let value =
|
||||
ctx.ast.expression_numeric_literal(SPAN, line as f64, None, NumberBase::Decimal);
|
||||
ctx.ast
|
||||
.object_property_kind_object_property(SPAN, kind, key, value, false, false, false)
|
||||
};
|
||||
|
||||
let column_number = {
|
||||
let key = ctx.ast.property_key_identifier_name(SPAN, "columnNumber");
|
||||
let value = ctx.ast.expression_numeric_literal(
|
||||
SPAN,
|
||||
column as f64,
|
||||
column.to_string(),
|
||||
NumberBase::Decimal,
|
||||
);
|
||||
let value =
|
||||
ctx.ast.expression_numeric_literal(SPAN, column as f64, None, NumberBase::Decimal);
|
||||
ctx.ast
|
||||
.object_property_kind_object_property(SPAN, kind, key, value, false, false, false)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ impl<'a> TypeScriptEnum<'a> {
|
|||
}
|
||||
|
||||
fn get_number_literal_expression(value: f64, ctx: &TraverseCtx<'a>) -> Expression<'a> {
|
||||
ctx.ast.expression_numeric_literal(SPAN, value, value.to_string(), NumberBase::Decimal)
|
||||
ctx.ast.expression_numeric_literal(SPAN, value, None, NumberBase::Decimal)
|
||||
}
|
||||
|
||||
fn get_initializer_expr(value: f64, ctx: &TraverseCtx<'a>) -> Expression<'a> {
|
||||
|
|
|
|||
|
|
@ -466,7 +466,7 @@ impl<'a> GatherNodeParts<'a> for StringLiteral<'a> {
|
|||
|
||||
impl<'a> GatherNodeParts<'a> for NumericLiteral<'a> {
|
||||
fn gather<F: FnMut(&str)>(&self, f: &mut F) {
|
||||
f(self.raw);
|
||||
f(&self.raw_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
4
npm/oxc-types/types.d.ts
vendored
4
npm/oxc-types/types.d.ts
vendored
|
|
@ -16,7 +16,7 @@ export interface NullLiteral extends Span {
|
|||
export interface NumericLiteral extends Span {
|
||||
type: 'Literal';
|
||||
value: number;
|
||||
raw: string;
|
||||
raw: string | null;
|
||||
}
|
||||
|
||||
export interface StringLiteral extends Span {
|
||||
|
|
@ -34,7 +34,7 @@ export interface BigIntLiteral extends Span {
|
|||
|
||||
export interface RegExpLiteral extends Span {
|
||||
type: 'Literal';
|
||||
raw: string;
|
||||
raw: string | null;
|
||||
value: {} | null;
|
||||
regex: { pattern: string; flags: string };
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue