mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 20:32:10 +00:00
refactor(ast): fix the lifetime annotations around Vist and VisitMut (#973)
This commit is contained in:
parent
c38a00b453
commit
903854dac0
10 changed files with 528 additions and 535 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -1820,6 +1820,7 @@ dependencies = [
|
||||||
"oxc_ast",
|
"oxc_ast",
|
||||||
"oxc_formatter",
|
"oxc_formatter",
|
||||||
"oxc_parser",
|
"oxc_parser",
|
||||||
|
"oxc_semantic",
|
||||||
"oxc_span",
|
"oxc_span",
|
||||||
"oxc_syntax",
|
"oxc_syntax",
|
||||||
]
|
]
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -84,7 +84,7 @@ impl<'a> Compressor<'a> {
|
||||||
Self { ast: AstBuilder::new(allocator), options, prepass: Prepass::new(allocator) }
|
Self { ast: AstBuilder::new(allocator), options, prepass: Prepass::new(allocator) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build<'b>(mut self, program: &'b mut Program<'a>) {
|
pub fn build(mut self, program: &mut Program<'a>) {
|
||||||
self.prepass.visit_program(program);
|
self.prepass.visit_program(program);
|
||||||
self.visit_program(program);
|
self.visit_program(program);
|
||||||
}
|
}
|
||||||
|
|
@ -113,7 +113,7 @@ impl<'a> Compressor<'a> {
|
||||||
/// Remove block from single line blocks
|
/// Remove block from single line blocks
|
||||||
/// `{ block } -> block`
|
/// `{ block } -> block`
|
||||||
#[allow(clippy::only_used_in_recursion)] // `&self` is only used in recursion
|
#[allow(clippy::only_used_in_recursion)] // `&self` is only used in recursion
|
||||||
fn compress_block<'b>(&self, stmt: &'b mut Statement<'a>) {
|
fn compress_block(&self, stmt: &mut Statement<'a>) {
|
||||||
if let Statement::BlockStatement(block) = stmt {
|
if let Statement::BlockStatement(block) = stmt {
|
||||||
// Avoid compressing `if (x) { var x = 1 }` to `if (x) var x = 1` due to different
|
// Avoid compressing `if (x) { var x = 1 }` to `if (x) var x = 1` due to different
|
||||||
// semantics according to AnnexB, which lead to different semantics.
|
// semantics according to AnnexB, which lead to different semantics.
|
||||||
|
|
@ -126,18 +126,18 @@ impl<'a> Compressor<'a> {
|
||||||
|
|
||||||
/// Drop `drop_debugger` statement.
|
/// Drop `drop_debugger` statement.
|
||||||
/// Enabled by `compress.drop_debugger`
|
/// Enabled by `compress.drop_debugger`
|
||||||
fn drop_debugger<'b>(&mut self, stmt: &'b Statement<'a>) -> bool {
|
fn drop_debugger(&mut self, stmt: &Statement<'a>) -> bool {
|
||||||
matches!(stmt, Statement::DebuggerStatement(_)) && self.options.drop_debugger
|
matches!(stmt, Statement::DebuggerStatement(_)) && self.options.drop_debugger
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Drop `console.*` expressions.
|
/// Drop `console.*` expressions.
|
||||||
/// Enabled by `compress.drop_console
|
/// Enabled by `compress.drop_console
|
||||||
fn drop_console<'b>(&mut self, stmt: &'b Statement<'a>) -> bool {
|
fn drop_console(&mut self, stmt: &Statement<'a>) -> bool {
|
||||||
self.options.drop_console
|
self.options.drop_console
|
||||||
&& matches!(stmt, Statement::ExpressionStatement(expr) if util::is_console(&expr.expression))
|
&& matches!(stmt, Statement::ExpressionStatement(expr) if util::is_console(&expr.expression))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compress_console<'b>(&mut self, expr: &'b mut Expression<'a>) -> bool {
|
fn compress_console(&mut self, expr: &mut Expression<'a>) -> bool {
|
||||||
if self.options.drop_console && util::is_console(expr) {
|
if self.options.drop_console && util::is_console(expr) {
|
||||||
*expr = self.create_void_0();
|
*expr = self.create_void_0();
|
||||||
true
|
true
|
||||||
|
|
@ -147,7 +147,7 @@ impl<'a> Compressor<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Join consecutive var statements
|
/// Join consecutive var statements
|
||||||
fn join_vars<'b>(&mut self, stmts: &'b mut Vec<'a, Statement<'a>>) {
|
fn join_vars(&mut self, stmts: &mut Vec<'a, Statement<'a>>) {
|
||||||
// Collect all the consecutive ranges that contain joinable vars.
|
// Collect all the consecutive ranges that contain joinable vars.
|
||||||
// This is required because Rust prevents in-place vec mutation.
|
// This is required because Rust prevents in-place vec mutation.
|
||||||
let mut ranges = vec![];
|
let mut ranges = vec![];
|
||||||
|
|
@ -201,7 +201,7 @@ impl<'a> Compressor<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transforms `while(expr)` to `for(;expr;)`
|
/// Transforms `while(expr)` to `for(;expr;)`
|
||||||
fn compress_while<'b>(&mut self, stmt: &'b mut Statement<'a>) {
|
fn compress_while(&mut self, stmt: &mut Statement<'a>) {
|
||||||
let Statement::WhileStatement(while_stmt) = stmt else { return };
|
let Statement::WhileStatement(while_stmt) = stmt else { return };
|
||||||
if self.options.loops {
|
if self.options.loops {
|
||||||
let dummy_test = self.ast.this_expression(SPAN);
|
let dummy_test = self.ast.this_expression(SPAN);
|
||||||
|
|
@ -214,7 +214,7 @@ impl<'a> Compressor<'a> {
|
||||||
/* Expressions */
|
/* Expressions */
|
||||||
|
|
||||||
/// Transforms `undefined` => `void 0`
|
/// Transforms `undefined` => `void 0`
|
||||||
fn compress_undefined<'b>(&mut self, expr: &'b mut Expression<'a>) -> bool {
|
fn compress_undefined(&mut self, expr: &mut Expression<'a>) -> bool {
|
||||||
let Expression::Identifier(ident) = expr else { return false };
|
let Expression::Identifier(ident) = expr else { return false };
|
||||||
if ident.name == "undefined" {
|
if ident.name == "undefined" {
|
||||||
// if let Some(reference_id) = ident.reference_id.clone().into_inner() {
|
// if let Some(reference_id) = ident.reference_id.clone().into_inner() {
|
||||||
|
|
@ -228,7 +228,7 @@ impl<'a> Compressor<'a> {
|
||||||
|
|
||||||
/// Transforms `Infinity` => `1/0`
|
/// Transforms `Infinity` => `1/0`
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
fn compress_infinity<'b>(&mut self, expr: &'b mut Expression<'a>) -> bool {
|
fn compress_infinity(&mut self, expr: &mut Expression<'a>) -> bool {
|
||||||
let Expression::Identifier(ident) = expr else { return false };
|
let Expression::Identifier(ident) = expr else { return false };
|
||||||
if ident.name == "Infinity" {
|
if ident.name == "Infinity" {
|
||||||
// if let Some(reference_id) = ident.reference_id.clone().into_inner() {
|
// if let Some(reference_id) = ident.reference_id.clone().into_inner() {
|
||||||
|
|
@ -242,7 +242,7 @@ impl<'a> Compressor<'a> {
|
||||||
|
|
||||||
/// Transforms boolean expression `true` => `!0` `false` => `!1`
|
/// Transforms boolean expression `true` => `!0` `false` => `!1`
|
||||||
/// Enabled by `compress.booleans`
|
/// Enabled by `compress.booleans`
|
||||||
fn compress_boolean<'b>(&mut self, expr: &'b mut Expression<'a>) -> bool {
|
fn compress_boolean(&mut self, expr: &mut Expression<'a>) -> bool {
|
||||||
let Expression::BooleanLiteral(lit) = expr else { return false };
|
let Expression::BooleanLiteral(lit) = expr else { return false };
|
||||||
if self.options.booleans {
|
if self.options.booleans {
|
||||||
let num = self.ast.number_literal(
|
let num = self.ast.number_literal(
|
||||||
|
|
@ -260,7 +260,7 @@ impl<'a> Compressor<'a> {
|
||||||
|
|
||||||
/// Transforms `typeof foo == "undefined"` into `foo === void 0`
|
/// Transforms `typeof foo == "undefined"` into `foo === void 0`
|
||||||
/// Enabled by `compress.typeofs`
|
/// Enabled by `compress.typeofs`
|
||||||
fn compress_typeof_undefined<'b>(&mut self, expr: &'b mut BinaryExpression<'a>) {
|
fn compress_typeof_undefined(&mut self, expr: &mut BinaryExpression<'a>) {
|
||||||
if expr.operator.is_equality() && self.options.typeofs {
|
if expr.operator.is_equality() && self.options.typeofs {
|
||||||
if let Expression::UnaryExpression(unary_expr) = &expr.left {
|
if let Expression::UnaryExpression(unary_expr) = &expr.left {
|
||||||
if unary_expr.operator == UnaryOperator::Typeof {
|
if unary_expr.operator == UnaryOperator::Typeof {
|
||||||
|
|
@ -281,13 +281,13 @@ impl<'a> Compressor<'a> {
|
||||||
///
|
///
|
||||||
/// `return undefined` -> `return`
|
/// `return undefined` -> `return`
|
||||||
/// `return void 0` -> `return`
|
/// `return void 0` -> `return`
|
||||||
fn compress_return_statement<'b>(&mut self, stmt: &'b mut ReturnStatement<'a>) {
|
fn compress_return_statement(&mut self, stmt: &mut ReturnStatement<'a>) {
|
||||||
if stmt.argument.as_ref().is_some_and(|expr| expr.is_undefined() || expr.is_void_0()) {
|
if stmt.argument.as_ref().is_some_and(|expr| expr.is_undefined() || expr.is_void_0()) {
|
||||||
stmt.argument = None;
|
stmt.argument = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compress_variable_declarator<'b>(&mut self, decl: &'b mut VariableDeclarator<'a>) {
|
fn compress_variable_declarator(&mut self, decl: &mut VariableDeclarator<'a>) {
|
||||||
if decl.kind.is_const() {
|
if decl.kind.is_const() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -303,7 +303,7 @@ impl<'a> Compressor<'a> {
|
||||||
/// After reordering, expressions like 0 === x and 0 === y may have higher
|
/// After reordering, expressions like 0 === x and 0 === y may have higher
|
||||||
/// compression together than their original counterparts.
|
/// compression together than their original counterparts.
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
fn reorder_constant_expression<'b>(&self, expr: &'b mut BinaryExpression<'a>) {
|
fn reorder_constant_expression(&self, expr: &mut BinaryExpression<'a>) {
|
||||||
let operator = expr.operator;
|
let operator = expr.operator;
|
||||||
if operator.is_equality()
|
if operator.is_equality()
|
||||||
|| operator.is_compare()
|
|| operator.is_compare()
|
||||||
|
|
@ -322,8 +322,8 @@ impl<'a> Compressor<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> VisitMut<'a, 'b> for Compressor<'a> {
|
impl<'a> VisitMut<'a> for Compressor<'a> {
|
||||||
fn visit_statements(&mut self, stmts: &'b mut Vec<'a, Statement<'a>>) {
|
fn visit_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>) {
|
||||||
stmts.retain(|stmt| {
|
stmts.retain(|stmt| {
|
||||||
if self.drop_debugger(stmt) {
|
if self.drop_debugger(stmt) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -341,14 +341,14 @@ impl<'a, 'b> VisitMut<'a, 'b> for Compressor<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_statement(&mut self, stmt: &'b mut Statement<'a>) {
|
fn visit_statement(&mut self, stmt: &mut Statement<'a>) {
|
||||||
self.compress_block(stmt);
|
self.compress_block(stmt);
|
||||||
self.compress_while(stmt);
|
self.compress_while(stmt);
|
||||||
self.fold_condition(stmt);
|
self.fold_condition(stmt);
|
||||||
self.visit_statement_match(stmt);
|
self.visit_statement_match(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_return_statement(&mut self, stmt: &'b mut ReturnStatement<'a>) {
|
fn visit_return_statement(&mut self, stmt: &mut ReturnStatement<'a>) {
|
||||||
if let Some(arg) = &mut stmt.argument {
|
if let Some(arg) = &mut stmt.argument {
|
||||||
self.visit_expression(arg);
|
self.visit_expression(arg);
|
||||||
}
|
}
|
||||||
|
|
@ -356,14 +356,14 @@ impl<'a, 'b> VisitMut<'a, 'b> for Compressor<'a> {
|
||||||
self.compress_return_statement(stmt);
|
self.compress_return_statement(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_variable_declaration(&mut self, decl: &'b mut VariableDeclaration<'a>) {
|
fn visit_variable_declaration(&mut self, decl: &mut VariableDeclaration<'a>) {
|
||||||
for declarator in decl.declarations.iter_mut() {
|
for declarator in decl.declarations.iter_mut() {
|
||||||
self.visit_variable_declarator(declarator);
|
self.visit_variable_declarator(declarator);
|
||||||
self.compress_variable_declarator(declarator);
|
self.compress_variable_declarator(declarator);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expression(&mut self, expr: &'b mut Expression<'a>) {
|
fn visit_expression(&mut self, expr: &mut Expression<'a>) {
|
||||||
self.visit_expression_match(expr);
|
self.visit_expression_match(expr);
|
||||||
self.compress_console(expr);
|
self.compress_console(expr);
|
||||||
self.fold_expression(expr);
|
self.fold_expression(expr);
|
||||||
|
|
@ -372,7 +372,7 @@ impl<'a, 'b> VisitMut<'a, 'b> for Compressor<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_binary_expression(&mut self, expr: &'b mut BinaryExpression<'a>) {
|
fn visit_binary_expression(&mut self, expr: &mut BinaryExpression<'a>) {
|
||||||
self.visit_expression(&mut expr.left);
|
self.visit_expression(&mut expr.left);
|
||||||
self.visit_expression(&mut expr.right);
|
self.visit_expression(&mut expr.right);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ impl<'a> Prepass<'a> {
|
||||||
Self { ast: AstBuilder::new(allocator) }
|
Self { ast: AstBuilder::new(allocator) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn strip_parenthesized_expression<'b>(&self, expr: &'b mut Expression<'a>) {
|
fn strip_parenthesized_expression(&self, expr: &mut Expression<'a>) {
|
||||||
if let Expression::ParenthesizedExpression(paren_expr) = expr {
|
if let Expression::ParenthesizedExpression(paren_expr) = expr {
|
||||||
*expr = self.ast.move_expression(&mut paren_expr.expression);
|
*expr = self.ast.move_expression(&mut paren_expr.expression);
|
||||||
self.strip_parenthesized_expression(expr);
|
self.strip_parenthesized_expression(expr);
|
||||||
|
|
@ -20,15 +20,15 @@ impl<'a> Prepass<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> VisitMut<'a, 'b> for Prepass<'a> {
|
impl<'a> VisitMut<'a> for Prepass<'a> {
|
||||||
fn visit_statements(&mut self, stmts: &'b mut Vec<'a, Statement<'a>>) {
|
fn visit_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>) {
|
||||||
stmts.retain(|stmt| !matches!(stmt, Statement::EmptyStatement(_)));
|
stmts.retain(|stmt| !matches!(stmt, Statement::EmptyStatement(_)));
|
||||||
for stmt in stmts.iter_mut() {
|
for stmt in stmts.iter_mut() {
|
||||||
self.visit_statement(stmt);
|
self.visit_statement(stmt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expression(&mut self, expr: &'b mut Expression<'a>) {
|
fn visit_expression(&mut self, expr: &mut Expression<'a>) {
|
||||||
self.strip_parenthesized_expression(expr);
|
self.strip_parenthesized_expression(expr);
|
||||||
self.visit_expression_match(expr);
|
self.visit_expression_match(expr);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,7 @@ impl<'a> SemanticBuilder<'a> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build(mut self, program: &'a Program<'a>) -> SemanticBuilderReturn<'a> {
|
pub fn build(mut self, program: &Program<'a>) -> SemanticBuilderReturn<'a> {
|
||||||
if !self.source_type.is_typescript_definition() {
|
if !self.source_type.is_typescript_definition() {
|
||||||
self.visit_program(program);
|
self.visit_program(program);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ oxc_ast = { workspace = true }
|
||||||
oxc_span = { workspace = true }
|
oxc_span = { workspace = true }
|
||||||
oxc_allocator = { workspace = true }
|
oxc_allocator = { workspace = true }
|
||||||
oxc_syntax = { workspace = true }
|
oxc_syntax = { workspace = true }
|
||||||
|
oxc_semantic = { workspace = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
oxc_parser = { workspace = true }
|
oxc_parser = { workspace = true }
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ use std::{env, path::Path};
|
||||||
use oxc_allocator::Allocator;
|
use oxc_allocator::Allocator;
|
||||||
use oxc_formatter::{Formatter, FormatterOptions};
|
use oxc_formatter::{Formatter, FormatterOptions};
|
||||||
use oxc_parser::Parser;
|
use oxc_parser::Parser;
|
||||||
|
use oxc_semantic::SemanticBuilder;
|
||||||
use oxc_span::SourceType;
|
use oxc_span::SourceType;
|
||||||
use oxc_transformer::{TransformOptions, TransformReactOptions, TransformTarget, Transformer};
|
use oxc_transformer::{TransformOptions, TransformReactOptions, TransformTarget, Transformer};
|
||||||
|
|
||||||
|
|
@ -28,11 +29,12 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
let formatter_options = FormatterOptions::default();
|
let formatter_options = FormatterOptions::default();
|
||||||
let program = allocator.alloc(ret.program);
|
let printed = Formatter::new(source_text.len(), formatter_options.clone()).build(&ret.program);
|
||||||
let printed = Formatter::new(source_text.len(), formatter_options.clone()).build(program);
|
|
||||||
println!("Original:\n");
|
println!("Original:\n");
|
||||||
println!("{printed}");
|
println!("{printed}");
|
||||||
|
|
||||||
|
let program = allocator.alloc(ret.program);
|
||||||
|
let _ = SemanticBuilder::new(&source_text, source_type).build(program);
|
||||||
let transform_options = TransformOptions {
|
let transform_options = TransformOptions {
|
||||||
target: TransformTarget::ES2015,
|
target: TransformTarget::ES2015,
|
||||||
react: Some(TransformReactOptions::default()),
|
react: Some(TransformReactOptions::default()),
|
||||||
|
|
|
||||||
|
|
@ -84,13 +84,13 @@ impl<'a> Transformer<'a> {
|
||||||
t
|
t
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build<'b>(mut self, program: &'b mut Program<'a>) {
|
pub fn build(mut self, program: &mut Program<'a>) {
|
||||||
self.visit_program(program);
|
self.visit_program(program);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b> VisitMut<'a, 'b> for Transformer<'a> {
|
impl<'a> VisitMut<'a> for Transformer<'a> {
|
||||||
fn visit_expression(&mut self, expr: &'b mut Expression<'a>) {
|
fn visit_expression(&mut self, expr: &mut Expression<'a>) {
|
||||||
// self.typescript.as_mut().map(|t| t.transform_expression(expr));
|
// self.typescript.as_mut().map(|t| t.transform_expression(expr));
|
||||||
// self.react_jsx.as_mut().map(|t| t.transform_expression(expr));
|
// self.react_jsx.as_mut().map(|t| t.transform_expression(expr));
|
||||||
self.es2021_logical_assignment_operators.as_mut().map(|t| t.transform_expression(expr));
|
self.es2021_logical_assignment_operators.as_mut().map(|t| t.transform_expression(expr));
|
||||||
|
|
@ -100,7 +100,7 @@ impl<'a, 'b> VisitMut<'a, 'b> for Transformer<'a> {
|
||||||
self.visit_expression_match(expr);
|
self.visit_expression_match(expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_catch_clause(&mut self, clause: &'b mut CatchClause<'a>) {
|
fn visit_catch_clause(&mut self, clause: &mut CatchClause<'a>) {
|
||||||
self.es2019_optional_catch_binding.as_mut().map(|t| t.transform_catch_clause(clause));
|
self.es2019_optional_catch_binding.as_mut().map(|t| t.transform_catch_clause(clause));
|
||||||
|
|
||||||
if let Some(param) = &mut clause.param {
|
if let Some(param) = &mut clause.param {
|
||||||
|
|
@ -109,7 +109,7 @@ impl<'a, 'b> VisitMut<'a, 'b> for Transformer<'a> {
|
||||||
self.visit_statements(&mut clause.body.body);
|
self.visit_statements(&mut clause.body.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_object_property(&mut self, prop: &'b mut ObjectProperty<'a>) {
|
fn visit_object_property(&mut self, prop: &mut ObjectProperty<'a>) {
|
||||||
self.es2015_shorthand_properties.as_mut().map(|t| t.transform_object_property(prop));
|
self.es2015_shorthand_properties.as_mut().map(|t| t.transform_object_property(prop));
|
||||||
|
|
||||||
self.visit_property_key(&mut prop.key);
|
self.visit_property_key(&mut prop.key);
|
||||||
|
|
@ -119,7 +119,7 @@ impl<'a, 'b> VisitMut<'a, 'b> for Transformer<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_class_body(&mut self, class_body: &'b mut ClassBody<'a>) {
|
fn visit_class_body(&mut self, class_body: &mut ClassBody<'a>) {
|
||||||
self.es2022_class_static_block.as_mut().map(|t| t.transform_class_body(class_body));
|
self.es2022_class_static_block.as_mut().map(|t| t.transform_class_body(class_body));
|
||||||
|
|
||||||
class_body.body.iter_mut().for_each(|class_element| {
|
class_body.body.iter_mut().for_each(|class_element| {
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ const UNICORN_TEST_PATH: &str =
|
||||||
|
|
||||||
struct TestCase<'a> {
|
struct TestCase<'a> {
|
||||||
source_text: &'a str,
|
source_text: &'a str,
|
||||||
code: Option<Cow<'a, str>>,
|
code: Option<String>,
|
||||||
test_code: Option<Cow<'a, str>>,
|
test_code: Option<Cow<'a, str>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,7 +74,7 @@ impl<'a> TestCase<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Visit<'a> for TestCase<'a> {
|
impl<'a> Visit<'a> for TestCase<'a> {
|
||||||
fn visit_expression(&mut self, expr: &'a Expression<'a>) {
|
fn visit_expression(&mut self, expr: &Expression<'a>) {
|
||||||
match expr {
|
match expr {
|
||||||
Expression::StringLiteral(lit) => self.visit_string_literal(lit),
|
Expression::StringLiteral(lit) => self.visit_string_literal(lit),
|
||||||
Expression::TemplateLiteral(lit) => self.visit_template_literal(lit),
|
Expression::TemplateLiteral(lit) => self.visit_template_literal(lit),
|
||||||
|
|
@ -87,7 +87,7 @@ impl<'a> Visit<'a> for TestCase<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_call_expression(&mut self, expr: &'a CallExpression<'a>) {
|
fn visit_call_expression(&mut self, expr: &CallExpression<'a>) {
|
||||||
if let Expression::MemberExpression(member_expr) = &expr.callee {
|
if let Expression::MemberExpression(member_expr) = &expr.callee {
|
||||||
if let Expression::ArrayExpression(array_expr) = member_expr.object() {
|
if let Expression::ArrayExpression(array_expr) = member_expr.object() {
|
||||||
// ['class A {', '}'].join('\n')
|
// ['class A {', '}'].join('\n')
|
||||||
|
|
@ -100,19 +100,19 @@ impl<'a> Visit<'a> for TestCase<'a> {
|
||||||
code.push_str(lit.value.as_str());
|
code.push_str(lit.value.as_str());
|
||||||
code.push('\n');
|
code.push('\n');
|
||||||
}
|
}
|
||||||
self.code = Some(Cow::Owned(code));
|
self.code = Some(code);
|
||||||
self.test_code = None;
|
self.test_code = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_object_expression(&mut self, expr: &'a ObjectExpression<'a>) {
|
fn visit_object_expression(&mut self, expr: &ObjectExpression<'a>) {
|
||||||
for obj_prop in &expr.properties {
|
for obj_prop in &expr.properties {
|
||||||
match obj_prop {
|
match obj_prop {
|
||||||
ObjectPropertyKind::ObjectProperty(prop) => match &prop.key {
|
ObjectPropertyKind::ObjectProperty(prop) => match &prop.key {
|
||||||
PropertyKey::Identifier(ident) if ident.name == "code" => {
|
PropertyKey::Identifier(ident) if ident.name == "code" => {
|
||||||
self.code = match &prop.value {
|
self.code = match &prop.value {
|
||||||
Expression::StringLiteral(s) => Some(Cow::Borrowed(s.value.as_str())),
|
Expression::StringLiteral(s) => Some(s.value.to_string()),
|
||||||
// eslint-plugin-jest use dedent to strips indentation from multi-line strings
|
// eslint-plugin-jest use dedent to strips indentation from multi-line strings
|
||||||
Expression::TaggedTemplateExpression(tag_expr) => {
|
Expression::TaggedTemplateExpression(tag_expr) => {
|
||||||
let Expression::Identifier(ident) = &tag_expr.tag else {
|
let Expression::Identifier(ident) = &tag_expr.tag else {
|
||||||
|
|
@ -121,10 +121,10 @@ impl<'a> Visit<'a> for TestCase<'a> {
|
||||||
if ident.name != "dedent" {
|
if ident.name != "dedent" {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
tag_expr.quasi.quasi().map(|s| Cow::Borrowed(s.as_str()))
|
tag_expr.quasi.quasi().map(ToString::to_string)
|
||||||
}
|
}
|
||||||
Expression::TemplateLiteral(tag_expr) => {
|
Expression::TemplateLiteral(tag_expr) => {
|
||||||
tag_expr.quasi().map(|s| Cow::Borrowed(s.as_str()))
|
tag_expr.quasi().map(ToString::to_string)
|
||||||
}
|
}
|
||||||
// handle code like ["{", "a: 1", "}"].join("\n")
|
// handle code like ["{", "a: 1", "}"].join("\n")
|
||||||
Expression::CallExpression(call_expr) => {
|
Expression::CallExpression(call_expr) => {
|
||||||
|
|
@ -146,7 +146,7 @@ impl<'a> Visit<'a> for TestCase<'a> {
|
||||||
let Expression::ArrayExpression(array_expr) = &member.object else {
|
let Expression::ArrayExpression(array_expr) = &member.object else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
Some(Cow::Owned(
|
Some(
|
||||||
array_expr
|
array_expr
|
||||||
.elements
|
.elements
|
||||||
.iter()
|
.iter()
|
||||||
|
|
@ -158,7 +158,7 @@ impl<'a> Visit<'a> for TestCase<'a> {
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("\n"),
|
.join("\n"),
|
||||||
))
|
)
|
||||||
}
|
}
|
||||||
_ => continue,
|
_ => continue,
|
||||||
}
|
}
|
||||||
|
|
@ -176,24 +176,24 @@ impl<'a> Visit<'a> for TestCase<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_template_literal(&mut self, lit: &'a TemplateLiteral<'a>) {
|
fn visit_template_literal(&mut self, lit: &TemplateLiteral<'a>) {
|
||||||
self.code = Some(Cow::Borrowed(lit.quasi().unwrap().as_str()));
|
self.code = Some(lit.quasi().unwrap().to_string());
|
||||||
self.test_code = None;
|
self.test_code = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_string_literal(&mut self, lit: &'a StringLiteral) {
|
fn visit_string_literal(&mut self, lit: &StringLiteral) {
|
||||||
self.code = Some(Cow::Borrowed(lit.value.as_str()));
|
self.code = Some(lit.value.to_string());
|
||||||
self.test_code = None;
|
self.test_code = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_tagged_template_expression(&mut self, expr: &'a TaggedTemplateExpression<'a>) {
|
fn visit_tagged_template_expression(&mut self, expr: &TaggedTemplateExpression<'a>) {
|
||||||
let Expression::Identifier(ident) = &expr.tag else {
|
let Expression::Identifier(ident) = &expr.tag else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
if ident.name != "dedent" {
|
if ident.name != "dedent" {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self.code = expr.quasi.quasi().map(|s| Cow::Borrowed(s.as_str()));
|
self.code = expr.quasi.quasi().map(std::string::ToString::to_string);
|
||||||
self.test_code = None;
|
self.test_code = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -246,23 +246,23 @@ impl<'a> State<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Visit<'a> for State<'a> {
|
impl<'a> Visit<'a> for State<'a> {
|
||||||
fn visit_program(&mut self, program: &'a Program<'a>) {
|
fn visit_program(&mut self, program: &Program<'a>) {
|
||||||
for stmt in &program.body {
|
for stmt in &program.body {
|
||||||
self.visit_statement(stmt);
|
self.visit_statement(stmt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_statement(&mut self, stmt: &'a Statement<'a>) {
|
fn visit_statement(&mut self, stmt: &Statement<'a>) {
|
||||||
if let Statement::ExpressionStatement(expr_stmt) = stmt {
|
if let Statement::ExpressionStatement(expr_stmt) = stmt {
|
||||||
self.visit_expression_statement(expr_stmt);
|
self.visit_expression_statement(expr_stmt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expression_statement(&mut self, stmt: &'a ExpressionStatement<'a>) {
|
fn visit_expression_statement(&mut self, stmt: &ExpressionStatement<'a>) {
|
||||||
self.visit_expression(&stmt.expression);
|
self.visit_expression(&stmt.expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expression(&mut self, expr: &'a Expression<'a>) {
|
fn visit_expression(&mut self, expr: &Expression<'a>) {
|
||||||
if let Expression::CallExpression(call_expr) = expr {
|
if let Expression::CallExpression(call_expr) = expr {
|
||||||
for arg in &call_expr.arguments {
|
for arg in &call_expr.arguments {
|
||||||
self.visit_argument(arg);
|
self.visit_argument(arg);
|
||||||
|
|
@ -270,7 +270,7 @@ impl<'a> Visit<'a> for State<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_argument(&mut self, arg: &'a Argument<'a>) {
|
fn visit_argument(&mut self, arg: &Argument<'a>) {
|
||||||
if let Argument::Expression(Expression::ObjectExpression(obj_expr)) = arg {
|
if let Argument::Expression(Expression::ObjectExpression(obj_expr)) = arg {
|
||||||
for obj_prop in &obj_expr.properties {
|
for obj_prop in &obj_expr.properties {
|
||||||
let ObjectPropertyKind::ObjectProperty(prop) = obj_prop else { return };
|
let ObjectPropertyKind::ObjectProperty(prop) = obj_prop else { return };
|
||||||
|
|
@ -279,17 +279,17 @@ impl<'a> Visit<'a> for State<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_object_property(&mut self, prop: &'a ObjectProperty<'a>) {
|
fn visit_object_property(&mut self, prop: &ObjectProperty<'a>) {
|
||||||
let PropertyKey::Identifier(ident) = &prop.key else { return };
|
let PropertyKey::Identifier(ident) = &prop.key else { return };
|
||||||
match ident.name.as_str() {
|
match ident.name.as_str() {
|
||||||
"valid" => {
|
"valid" => {
|
||||||
if let Expression::ArrayExpression(array_expr) = &prop.value {
|
if let Expression::ArrayExpression(array_expr) = &prop.value {
|
||||||
self.valid_tests.push(array_expr);
|
self.valid_tests.push(self.alloc(array_expr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"invalid" => {
|
"invalid" => {
|
||||||
if let Expression::ArrayExpression(array_expr) = &prop.value {
|
if let Expression::ArrayExpression(array_expr) = &prop.value {
|
||||||
self.invalid_tests.push(array_expr);
|
self.invalid_tests.push(self.alloc(array_expr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue