feat(transformer): numeric separator plugin. (#2795)

[es2021 numeric
separator](https://babeljs.io/docs/babel-plugin-transform-numeric-separator)
This commit is contained in:
Ali Rezvani 2024-03-26 13:45:12 +03:30 committed by GitHub
parent 56493bd02b
commit 243131d7a4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 54 additions and 19 deletions

View file

@ -1167,11 +1167,7 @@ fn print_non_negative_float<const MINIFY: bool>(value: f64, _p: &Codegen<{ MINIF
impl<'a, const MINIFY: bool> Gen<MINIFY> for BigIntLiteral<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) {
p.add_source_mapping(self.span.start);
if self.raw.contains('_') {
p.print_str(self.raw.replace('_', "").as_bytes());
} else {
p.print_str(self.raw.as_bytes());
}
p.print_str(self.raw.as_bytes());
}
}

View file

@ -33,7 +33,7 @@ impl<'a> Literals<'a> {
if let [b'0', b'b' | b'B' | b'o' | b'O'] = lit.raw[0..2].as_bytes() {
// Set binary and octal raw values to empty, It would force the codegen,
// to generate them from their value.
// go generate them from their value.
lit.raw = "";
}
}

View file

@ -1,3 +1,5 @@
mod logical_assignment_operators;
mod numeric_separator;
pub use logical_assignment_operators::LogicalAssignmentOperators;
pub use numeric_separator::NumericSeparator;

View file

@ -0,0 +1,36 @@
use oxc_ast::ast::*;
use oxc_span::Atom;
use crate::{
context::TransformerCtx,
options::{TransformOptions, TransformTarget},
};
/// ES2021: Numeric Separator
///
/// References:
/// * <https://babeljs.io/docs/babel-plugin-transform-numeric-separator>
pub struct NumericSeparator<'a> {
ctx: TransformerCtx<'a>,
}
impl<'a> NumericSeparator<'a> {
#![allow(clippy::unused_self)]
pub fn new(ctx: TransformerCtx<'a>, options: &TransformOptions) -> Option<Self> {
(options.target < TransformTarget::ES2021 || options.numeric_separator)
.then_some(Self { ctx })
}
pub fn transform_number_literal(&mut self, lit: &mut NumericLiteral<'a>) {
if !lit.raw.is_empty() {
lit.raw = self.ctx.ast.new_str(lit.raw.replace('_', "").as_str());
}
}
pub fn transform_bigint_literal(&mut self, lit: &mut BigIntLiteral<'a>) {
if !lit.raw.is_empty() {
lit.raw = Atom::from(self.ctx.ast.new_str(lit.raw.replace('_', "").as_str()));
}
}
}

View file

@ -49,7 +49,7 @@ use crate::{
es2016::ExponentiationOperator,
es2019::{JsonStrings, OptionalCatchBinding},
es2020::NullishCoalescingOperator,
es2021::LogicalAssignmentOperators,
es2021::{LogicalAssignmentOperators, NumericSeparator},
es2022::ClassStaticBlock,
es3::PropertyLiteral,
react_jsx::ReactJsx,
@ -78,6 +78,7 @@ pub struct Transformer<'a> {
es2022_class_static_block: Option<ClassStaticBlock<'a>>,
// es2021
es2021_logical_assignment_operators: Option<LogicalAssignmentOperators<'a>>,
es2021_numeric_separator: Option<NumericSeparator<'a>>,
// es2020
es2020_nullish_coalescing_operators: Option<NullishCoalescingOperator<'a>>,
// es2019
@ -120,6 +121,7 @@ impl<'a> Transformer<'a> {
es2022_class_static_block: es2022::ClassStaticBlock::new(Rc::clone(&ast), &options),
// es2021
es2021_logical_assignment_operators: LogicalAssignmentOperators::new(Rc::clone(&ast), ctx.clone(), &options),
es2021_numeric_separator: NumericSeparator::new(ctx.clone(), &options),
// es2020
es2020_nullish_coalescing_operators: NullishCoalescingOperator::new(Rc::clone(&ast), ctx.clone(), &options),
// es2019
@ -247,21 +249,20 @@ impl<'a> VisitMut<'a> for Transformer<'a> {
}
fn visit_directive(&mut self, directive: &mut Directive<'a>) {
self.es2019_json_strings
.as_mut()
.map(|t: &mut JsonStrings| t.transform_directive(directive));
// TODO: we didn't walk this through, but maybe we should?
// walk_directive_mut(self, directive);
self.es2019_json_strings.as_mut().map(|t| t.transform_directive(directive));
}
fn visit_number_literal(&mut self, lit: &mut NumericLiteral<'a>) {
self.es2021_numeric_separator.as_mut().map(|t| t.transform_number_literal(lit));
self.es2015_literals.as_mut().map(|t| t.transform_number_literal(lit));
}
fn visit_bigint_literal(&mut self, lit: &mut BigIntLiteral<'a>) {
self.es2021_numeric_separator.as_mut().map(|t| t.transform_bigint_literal(lit));
}
fn visit_string_literal(&mut self, lit: &mut StringLiteral<'a>) {
self.es2019_json_strings
.as_mut()
.map(|t: &mut JsonStrings| t.transform_string_literal(lit));
self.es2019_json_strings.as_mut().map(|t| t.transform_string_literal(lit));
self.es2015_literals.as_mut().map(|t| t.transform_string_literal(lit));
}

View file

@ -18,6 +18,7 @@ pub struct TransformOptions {
pub class_static_block: bool,
// es2021
pub logical_assignment_operators: bool,
pub numeric_separator: bool,
// es2020
pub nullish_coalescing_operator: Option<NullishCoalescingOperatorOptions>,
// es2019

View file

@ -1,6 +1,7 @@
Passed: 319/1415
Passed: 320/1415
# All Passed:
* babel-plugin-transform-numeric-separator
* babel-plugin-transform-optional-catch-binding
* babel-plugin-transform-json-strings
* babel-plugin-transform-shorthand-properties
@ -519,9 +520,6 @@ Passed: 319/1415
# babel-plugin-transform-logical-assignment-operators (5/6)
* logical-assignment/null-coalescing/input.js
# babel-plugin-transform-numeric-separator (1/2)
* numeric-separator/used-with-transform-literals/input.js
# babel-plugin-transform-export-namespace-from (0/4)
* export-namespace/namespace-default/input.mjs
* export-namespace/namespace-es6/input.mjs

View file

@ -109,6 +109,7 @@ pub trait TestCase {
logical_assignment_operators: options
.get_plugin("transform-logical-assignment-operators")
.is_some(),
numeric_separator: options.get_plugin("transform-numeric-separator").is_some(),
nullish_coalescing_operator: options
.get_plugin("transform-nullish-coalescing-operator")
.map(get_options::<NullishCoalescingOperatorOptions>),