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:
Song Gao 2024-12-05 08:34:45 +08:00 committed by GitHub
parent e5145b0083
commit ebc80f6749
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 125 additions and 128 deletions

View file

@ -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

View file

@ -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`

View file

@ -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,
}
}

View file

@ -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)
}
}

View file

@ -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)))
}

View file

@ -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,

View file

@ -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");

View file

@ -66,7 +66,7 @@ impl<'a> IsolatedDeclarations<'a> {
self.ast.expression_numeric_literal(
SPAN,
value,
value.to_string(),
None,
NumberBase::Decimal,
)
};

View file

@ -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()),
}
}

View file

@ -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;
};

View file

@ -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(),
}
}
}

View file

@ -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),

View file

@ -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));

View file

@ -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";
}
}
}

View file

@ -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;
};

View file

@ -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)

View file

@ -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),
}
}

View file

@ -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 {

View file

@ -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;
}

View file

@ -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]

View file

@ -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;
}

View file

@ -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 },
);

View file

@ -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,

View file

@ -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 {

View file

@ -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)

View file

@ -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(

View file

@ -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(

View file

@ -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)

View file

@ -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));
}
_ => {}

View file

@ -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)
};

View file

@ -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> {

View file

@ -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());
}
}

View file

@ -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 };
}