From e51ad704a6a9eb1e4bb42f9f43014a84911e2c66 Mon Sep 17 00:00:00 2001 From: Konstantin Burkalev Date: Fri, 14 Feb 2025 22:28:28 +0200 Subject: [PATCH] =?UTF-8?q?polish=20transpilers,=20add=20support=20for?= =?UTF-8?q?=C2=A0error=20reporter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/check_dup_prop_transpiler.rs | 146 +++----- .../src/cube_prop_ctx_transpiler.rs | 336 ++++++++--------- rust/cubetranspilers/src/error_reporter.rs | 45 +++ .../src/import_export_transpiler.rs | 350 +++++++----------- rust/cubetranspilers/src/lib.rs | 31 +- .../src/validation_transpiler.rs | 111 +++--- 6 files changed, 450 insertions(+), 569 deletions(-) create mode 100644 rust/cubetranspilers/src/error_reporter.rs diff --git a/rust/cubetranspilers/src/check_dup_prop_transpiler.rs b/rust/cubetranspilers/src/check_dup_prop_transpiler.rs index bb37530003b0c..e9efc7bafa3f1 100644 --- a/rust/cubetranspilers/src/check_dup_prop_transpiler.rs +++ b/rust/cubetranspilers/src/check_dup_prop_transpiler.rs @@ -1,32 +1,30 @@ use std::collections::HashSet; +use swc_core::common::errors::Handler; use swc_core::common::{BytePos, Span, DUMMY_SP}; use swc_core::ecma::visit::VisitMutWith; -use swc_core::plugin::errors::HANDLER; -use swc_core::plugin::proxies::TransformPluginProgramMetadata; use swc_core::{ - ecma::{ - ast::*, - visit::{visit_mut_pass, VisitMut}, - }, + ecma::{ast::*, visit::VisitMut}, plugin::proxies::PluginSourceMapProxy, }; -pub struct CheckDupPropTransformVisitor { +pub struct CheckDupPropTransformVisitor<'a> { pub(crate) source_map: Option, + handler: &'a Handler, } -impl CheckDupPropTransformVisitor { - pub fn new(source_map: Option) -> Self { - CheckDupPropTransformVisitor { source_map } +impl<'a> CheckDupPropTransformVisitor<'a> { + pub fn new(source_map: Option, handler: &'a Handler) -> Self { + CheckDupPropTransformVisitor { + source_map, + handler, + } } fn emit_error(&mut self, span: Span, message: &str) { - HANDLER.with(|handler| { - handler - .struct_span_err(span, &self.format_msg(span, message)) - .emit(); - }); + self.handler + .struct_span_err(span, &self.format_msg(span, message)) + .emit(); } fn format_msg(&self, span: Span, message: &str) -> String { @@ -87,7 +85,7 @@ impl CheckDupPropTransformVisitor { } } -impl VisitMut for CheckDupPropTransformVisitor { +impl VisitMut for CheckDupPropTransformVisitor<'_> { // Implement necessary visit_mut_* methods for actual custom transform. // A comprehensive list of possible visitor methods can be found here: // https://rustdoc.swc.rs/swc_ecma_visit/trait.VisitMut.html @@ -108,12 +106,6 @@ impl VisitMut for CheckDupPropTransformVisitor { } } -pub fn process_transform(program: Program, metadata: TransformPluginProgramMetadata) -> Program { - program.apply(&mut visit_mut_pass(CheckDupPropTransformVisitor { - source_map: Some(metadata.source_map), - })) -} - #[cfg(test)] mod tests { // Recommended strategy to test plugin's transform is verify @@ -128,7 +120,7 @@ mod tests { common::{ errors::{DiagnosticBuilder, Emitter, Handler, HandlerFlags}, sync::Lrc, - FileName, Globals, SourceMap, + FileName, SourceMap, }, ecma::visit::VisitMutWith, }; @@ -147,7 +139,6 @@ mod tests { #[test] fn test_errors_for_duplicates_first_level() { - let globals = Globals::new(); let cm: Lrc = Default::default(); let diagnostics = Arc::new(Mutex::new(Vec::new())); let emitter = Box::new(TestEmitter { @@ -210,26 +201,21 @@ mod tests { }); "#; - swc_core::common::GLOBALS.set(&globals, || { - HANDLER.set(&handler, || { - let fm = cm.new_source_file( - Arc::new(FileName::Custom("input.js".into())), - js_code.into(), - ); - let lexer = Lexer::new( - Syntax::Es(Default::default()), - EsVersion::Es2020, - StringInput::from(&*fm), - None, - ); - let mut parser = Parser::new_from(lexer); - let mut program: Program = - parser.parse_program().expect("Failed to parse the JS code"); - - let mut visitor = CheckDupPropTransformVisitor { source_map: None }; - program.visit_mut_with(&mut visitor); - }); - }); + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = CheckDupPropTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); let diags = diagnostics.lock().unwrap(); let msgs: Vec<_> = diags @@ -241,7 +227,6 @@ mod tests { #[test] fn test_errors_for_duplicates_deep_level() { - let globals = Globals::new(); let cm: Lrc = Default::default(); let diagnostics = Arc::new(Mutex::new(Vec::new())); let emitter = Box::new(TestEmitter { @@ -304,26 +289,21 @@ mod tests { }); "#; - swc_core::common::GLOBALS.set(&globals, || { - HANDLER.set(&handler, || { - let fm = cm.new_source_file( - Arc::new(FileName::Custom("input.js".into())), - js_code.into(), - ); - let lexer = Lexer::new( - Syntax::Es(Default::default()), - EsVersion::Es2020, - StringInput::from(&*fm), - None, - ); - let mut parser = Parser::new_from(lexer); - let mut program: Program = - parser.parse_program().expect("Failed to parse the JS code"); - - let mut visitor = CheckDupPropTransformVisitor { source_map: None }; - program.visit_mut_with(&mut visitor); - }); - }); + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = CheckDupPropTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); let diags = diagnostics.lock().unwrap(); let msgs: Vec<_> = diags @@ -335,7 +315,6 @@ mod tests { #[test] fn test_no_errors() { - let globals = Globals::new(); let cm: Lrc = Default::default(); let diagnostics = Arc::new(Mutex::new(Vec::new())); let emitter = Box::new(TestEmitter { @@ -391,26 +370,21 @@ mod tests { }); "#; - swc_core::common::GLOBALS.set(&globals, || { - HANDLER.set(&handler, || { - let fm = cm.new_source_file( - Arc::new(FileName::Custom("input.js".into())), - js_code.into(), - ); - let lexer = Lexer::new( - Syntax::Es(Default::default()), - EsVersion::Es2020, - StringInput::from(&*fm), - None, - ); - let mut parser = Parser::new_from(lexer); - let mut program: Program = - parser.parse_program().expect("Failed to parse the JS code"); - - let mut visitor = CheckDupPropTransformVisitor { source_map: None }; - program.visit_mut_with(&mut visitor); - }); - }); + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = CheckDupPropTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); let diags = diagnostics.lock().unwrap(); assert!(diags.is_empty(), "Should not emit errors",); diff --git a/rust/cubetranspilers/src/cube_prop_ctx_transpiler.rs b/rust/cubetranspilers/src/cube_prop_ctx_transpiler.rs index 9828da93828ef..913da41b1f79a 100644 --- a/rust/cubetranspilers/src/cube_prop_ctx_transpiler.rs +++ b/rust/cubetranspilers/src/cube_prop_ctx_transpiler.rs @@ -3,17 +3,12 @@ use regex::Regex; use std::collections::{HashMap, HashSet}; use std::sync::LazyLock; use swc_core::atoms::Atom; +use swc_core::common::errors::Handler; use swc_core::common::{BytePos, Span, SyntaxContext, DUMMY_SP}; use swc_core::ecma::visit::{Visit, VisitMutWith, VisitWith}; -use swc_core::plugin::errors::HANDLER; -use crate::TransformConfig; -use swc_core::plugin::proxies::TransformPluginProgramMetadata; use swc_core::{ - ecma::{ - ast::*, - visit::{visit_mut_pass, VisitMut}, - }, + ecma::{ast::*, visit::VisitMut}, plugin::proxies::PluginSourceMapProxy, }; @@ -65,34 +60,35 @@ static TRANSPILLED_FIELDS: LazyLock> = LazyLock::new(|| { set }); -pub struct CubePropTransformVisitor { +pub struct CubePropTransformVisitor<'a> { pub(crate) cube_names: HashSet, pub(crate) cube_symbols: HashMap>, pub(crate) context_symbols: HashMap, pub(crate) source_map: Option, + handler: &'a Handler, } -impl CubePropTransformVisitor { +impl<'a> CubePropTransformVisitor<'a> { pub fn new( cube_names: HashSet, cube_symbols: HashMap>, context_symbols: HashMap, source_map: Option, + handler: &'a Handler, ) -> Self { CubePropTransformVisitor { source_map, cube_names, cube_symbols, context_symbols, + handler, } } fn emit_error(&self, span: Span, message: &str) { - HANDLER.with(|handler| { - handler - .struct_span_err(span, &self.format_msg(span, message)) - .emit(); - }); + self.handler + .struct_span_err(span, &self.format_msg(span, message)) + .emit(); } fn format_msg(&self, span: Span, message: &str) -> String { @@ -151,10 +147,13 @@ impl CubePropTransformVisitor { } } - fn sql_and_references_field_visitor( - &mut self, + fn sql_and_references_field_visitor<'b>( + &'b mut self, cube_name: Option, - ) -> SqlAndReferencesFieldVisitor { + ) -> SqlAndReferencesFieldVisitor<'b, 'a> + where + 'a: 'b, + { SqlAndReferencesFieldVisitor { cube_name, parent: self, @@ -162,9 +161,15 @@ impl CubePropTransformVisitor { } } - fn known_identifiers_inject_visitor(&mut self, field: &str) -> KnownIdentifiersInjectVisitor { + fn known_identifiers_inject_visitor<'b>( + &'b mut self, + field: String, + ) -> KnownIdentifiersInjectVisitor<'b, 'a> + where + 'a: 'b, + { KnownIdentifiersInjectVisitor { - field: field.to_string(), + field, parent: self, } } @@ -219,7 +224,7 @@ impl CubePropTransformVisitor { } } -impl VisitMut for CubePropTransformVisitor { +impl VisitMut for CubePropTransformVisitor<'_> { // Implement necessary visit_mut_* methods for actual custom transform. // A comprehensive list of possible visitor methods can be found here: // https://rustdoc.swc.rs/swc_ecma_visit/trait.VisitMut.html @@ -263,13 +268,17 @@ impl VisitMut for CubePropTransformVisitor { } { let mut known_visitor = - self.known_identifiers_inject_visitor("extends"); + self.known_identifiers_inject_visitor("extends".to_string()); last_arg.visit_mut_with(&mut known_visitor); } } } else if callee_name == "context" { if let Some(last_arg) = call_expr.args.last_mut() { - let mut sql_visitor = self.sql_and_references_field_visitor(None); + let mut sql_visitor = { + let self_ref = &mut *self; + self_ref.sql_and_references_field_visitor(None) + }; + last_arg.expr.visit_mut_with(&mut sql_visitor); } } @@ -280,19 +289,19 @@ impl VisitMut for CubePropTransformVisitor { } } -pub struct SqlAndReferencesFieldVisitor<'a> { +pub struct SqlAndReferencesFieldVisitor<'b, 'a: 'b> { pub cube_name: Option, - pub parent: &'a mut CubePropTransformVisitor, + pub parent: &'b mut CubePropTransformVisitor<'a>, pub path_stack: Vec, } -impl SqlAndReferencesFieldVisitor<'_> { +impl SqlAndReferencesFieldVisitor<'_, '_> { fn current_path(&self) -> String { self.path_stack.join(".") } } -impl VisitMut for SqlAndReferencesFieldVisitor<'_> { +impl VisitMut for SqlAndReferencesFieldVisitor<'_, '_> { fn visit_mut_prop(&mut self, prop: &mut Prop) { let mut added = false; if let Prop::KeyValue(ref kv) = prop { @@ -338,12 +347,12 @@ impl VisitMut for SqlAndReferencesFieldVisitor<'_> { } } -pub struct KnownIdentifiersInjectVisitor<'a> { +pub struct KnownIdentifiersInjectVisitor<'b, 'a: 'b> { pub field: String, - pub parent: &'a mut CubePropTransformVisitor, + pub parent: &'b mut CubePropTransformVisitor<'a>, } -impl VisitMut for KnownIdentifiersInjectVisitor<'_> { +impl VisitMut for KnownIdentifiersInjectVisitor<'_, '_> { fn visit_mut_prop(&mut self, prop: &mut Prop) { let ident_name = match &prop { Prop::Shorthand(ident) => ident.sym.clone().to_string(), @@ -387,22 +396,6 @@ impl Visit for CollectIdentifiersVisitor<'_> { } } -pub fn process_transform(program: Program, metadata: TransformPluginProgramMetadata) -> Program { - let config_str = metadata.get_transform_plugin_config().unwrap_or_default(); - - let ts_config: TransformConfig = - serde_json::from_str(&config_str).expect("Incorrect plugin configuration"); - - let visitor = CubePropTransformVisitor { - cube_names: ts_config.cube_names, - cube_symbols: ts_config.cube_symbols, - context_symbols: ts_config.context_symbols, - source_map: Some(metadata.source_map), - }; - - program.apply(&mut visit_mut_pass(visitor)) -} - #[cfg(test)] mod tests { // Recommended strategy to test plugin's transform is verify @@ -417,7 +410,7 @@ mod tests { common::{ errors::{DiagnosticBuilder, Emitter, Handler, HandlerFlags}, sync::Lrc, - FileName, Globals, SourceMap, + FileName, SourceMap, }, ecma::visit::VisitMutWith, }; @@ -470,7 +463,6 @@ mod tests { #[test] fn test_incorrect_args_to_cube() { - let globals = Globals::new(); let cm: Lrc = Default::default(); let diagnostics = Arc::new(Mutex::new(Vec::new())); let emitter = Box::new(TestEmitter { @@ -488,37 +480,29 @@ mod tests { cube(`cube1`, { sql: `xxx` }, 25); "#; - let mut transformed_program: Option = None; - - swc_core::common::GLOBALS.set(&globals, || { - HANDLER.set(&handler, || { - let fm = cm.new_source_file( - Arc::new(FileName::Custom("input.js".into())), - js_code.into(), - ); - let lexer = Lexer::new( - Syntax::Es(Default::default()), - EsVersion::Es2020, - StringInput::from(&*fm), - None, - ); - let mut parser = Parser::new_from(lexer); - let mut program: Program = - parser.parse_program().expect("Failed to parse the JS code"); - - let mut visitor = CubePropTransformVisitor { - source_map: None, - cube_names: HashSet::new(), - cube_symbols: HashMap::new(), - context_symbols: HashMap::new(), - }; - program.visit_mut_with(&mut visitor); - transformed_program = Some(program); - }); - }); + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = CubePropTransformVisitor::new( + HashSet::new(), + HashMap::new(), + HashMap::new(), + None, + &handler, + ); + program.visit_mut_with(&mut visitor); - let transformed_program = transformed_program.expect("Transformation failed"); - let _output_code = generate_code(&transformed_program, &cm); + let _output_code = generate_code(&program, &cm); let diags = diagnostics.lock().unwrap(); let msgs: Vec<_> = diags .iter() @@ -529,7 +513,6 @@ mod tests { #[test] fn test_simple_transform() { - let globals = Globals::new(); let cm: Lrc = Default::default(); let diagnostics = Arc::new(Mutex::new(Vec::new())); let emitter = Box::new(TestEmitter { @@ -623,37 +606,29 @@ mod tests { // } // }); - let mut transformed_program: Option = None; - - swc_core::common::GLOBALS.set(&globals, || { - HANDLER.set(&handler, || { - let fm = cm.new_source_file( - Arc::new(FileName::Custom("input.js".into())), - js_code.into(), - ); - let lexer = Lexer::new( - Syntax::Es(Default::default()), - EsVersion::Es2020, - StringInput::from(&*fm), - None, - ); - let mut parser = Parser::new_from(lexer); - let mut program: Program = - parser.parse_program().expect("Failed to parse the JS code"); - - let mut visitor = CubePropTransformVisitor { - source_map: None, - cube_names: HashSet::new(), - cube_symbols: HashMap::new(), - context_symbols: HashMap::new(), - }; - program.visit_mut_with(&mut visitor); - transformed_program = Some(program); - }); - }); + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = CubePropTransformVisitor::new( + HashSet::new(), + HashMap::new(), + HashMap::new(), + None, + &handler, + ); + program.visit_mut_with(&mut visitor); - let transformed_program = transformed_program.expect("Transformation failed"); - let output_code = generate_code(&transformed_program, &cm); + let output_code = generate_code(&program, &cm); assert!( output_code.contains("sql: ()=>`"), @@ -670,7 +645,6 @@ mod tests { #[test] fn test_complicated_transform_1st_stage() { - let globals = Globals::new(); let cm: Lrc = Default::default(); let diagnostics = Arc::new(Mutex::new(Vec::new())); let emitter = Box::new(TestEmitter { @@ -937,37 +911,30 @@ mod tests { // }] // }); - let mut transformed_program: Option = None; - - swc_core::common::GLOBALS.set(&globals, || { - HANDLER.set(&handler, || { - let fm = cm.new_source_file( - Arc::new(FileName::Custom("input.js".into())), - js_code.into(), - ); - let lexer = Lexer::new( - Syntax::Es(Default::default()), - EsVersion::Es2020, - StringInput::from(&*fm), - None, - ); - let mut parser = Parser::new_from(lexer); - let mut program: Program = - parser.parse_program().expect("Failed to parse the JS code"); - - let mut visitor = CubePropTransformVisitor { - source_map: None, - cube_names: HashSet::new(), - cube_symbols: HashMap::new(), - context_symbols: CONTEXT_SYMBOLS.clone(), - }; - program.visit_mut_with(&mut visitor); - transformed_program = Some(program); - }); - }); + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = CubePropTransformVisitor::new( + HashSet::new(), + HashMap::new(), + CONTEXT_SYMBOLS.clone(), + None, + &handler, + ); - let transformed_program = transformed_program.expect("Transformation failed"); - let output_code = generate_code(&transformed_program, &cm); + program.visit_mut_with(&mut visitor); + + let output_code = generate_code(&program, &cm); assert!( output_code.contains("sql: ()=>`"), @@ -1034,7 +1001,6 @@ mod tests { #[test] fn test_complicated_transform_2nd_stage() { - let globals = Globals::new(); let cm: Lrc = Default::default(); let diagnostics = Arc::new(Mutex::new(Vec::new())); let emitter = Box::new(TestEmitter { @@ -1292,56 +1258,48 @@ mod tests { // }] // }); - let mut transformed_program: Option = None; - - swc_core::common::GLOBALS.set(&globals, || { - HANDLER.set(&handler, || { - let fm = cm.new_source_file( - Arc::new(FileName::Custom("input.js".into())), - js_code.into(), - ); - let lexer = Lexer::new( - Syntax::Es(Default::default()), - EsVersion::Es2020, - StringInput::from(&*fm), - None, - ); - let mut parser = Parser::new_from(lexer); - let mut program: Program = - parser.parse_program().expect("Failed to parse the JS code"); - let mut cube_names = HashSet::new(); - cube_names.insert("Orders".to_string()); - let mut cube_symbols = HashMap::>::new(); - let mut orders_cube_symbols = HashMap::new(); - orders_cube_symbols.insert("division_error_test".to_string(), true); - orders_cube_symbols.insert("zero_sum".to_string(), true); - orders_cube_symbols.insert("rolling_count_month".to_string(), true); - orders_cube_symbols.insert("count".to_string(), true); - orders_cube_symbols.insert("countShipped".to_string(), true); - orders_cube_symbols.insert("id".to_string(), true); - orders_cube_symbols.insert("status".to_string(), true); - orders_cube_symbols.insert("createdAt".to_string(), true); - orders_cube_symbols.insert("completedAt".to_string(), true); - orders_cube_symbols.insert("test_boolean".to_string(), true); - orders_cube_symbols.insert("localTime".to_string(), true); - orders_cube_symbols.insert("localYear".to_string(), true); - orders_cube_symbols.insert("status_completed".to_string(), true); - orders_cube_symbols.insert("main_test_range".to_string(), true); - cube_symbols.insert("Orders".to_string(), orders_cube_symbols); - - let mut visitor = CubePropTransformVisitor { - source_map: None, - cube_names, - cube_symbols, - context_symbols: CONTEXT_SYMBOLS.clone(), - }; - program.visit_mut_with(&mut visitor); - transformed_program = Some(program); - }); - }); + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + let mut cube_names = HashSet::new(); + cube_names.insert("Orders".to_string()); + let mut cube_symbols = HashMap::>::new(); + let mut orders_cube_symbols = HashMap::new(); + orders_cube_symbols.insert("division_error_test".to_string(), true); + orders_cube_symbols.insert("zero_sum".to_string(), true); + orders_cube_symbols.insert("rolling_count_month".to_string(), true); + orders_cube_symbols.insert("count".to_string(), true); + orders_cube_symbols.insert("countShipped".to_string(), true); + orders_cube_symbols.insert("id".to_string(), true); + orders_cube_symbols.insert("status".to_string(), true); + orders_cube_symbols.insert("createdAt".to_string(), true); + orders_cube_symbols.insert("completedAt".to_string(), true); + orders_cube_symbols.insert("test_boolean".to_string(), true); + orders_cube_symbols.insert("localTime".to_string(), true); + orders_cube_symbols.insert("localYear".to_string(), true); + orders_cube_symbols.insert("status_completed".to_string(), true); + orders_cube_symbols.insert("main_test_range".to_string(), true); + cube_symbols.insert("Orders".to_string(), orders_cube_symbols); + + let mut visitor = CubePropTransformVisitor::new( + cube_names, + cube_symbols, + CONTEXT_SYMBOLS.clone(), + None, + &handler, + ); + program.visit_mut_with(&mut visitor); - let transformed_program = transformed_program.expect("Transformation failed"); - let output_code = generate_code(&transformed_program, &cm); + let output_code = generate_code(&program, &cm); assert!( output_code.contains("sql: ()=>`"), diff --git a/rust/cubetranspilers/src/error_reporter.rs b/rust/cubetranspilers/src/error_reporter.rs new file mode 100644 index 0000000000000..eef3581c9cfc0 --- /dev/null +++ b/rust/cubetranspilers/src/error_reporter.rs @@ -0,0 +1,45 @@ +use std::sync::{Arc, Mutex}; + +use swc_core::common::errors::{DiagnosticBuilder, Emitter}; + +pub struct ErrorReporter { + pub errors: Arc>>, + pub warnings: Arc>>, +} + +impl ErrorReporter { + pub fn new(errors: Arc>>, warnings: Arc>>) -> Self { + ErrorReporter { errors, warnings } + } +} + +impl Default for ErrorReporter { + fn default() -> Self { + ErrorReporter { + errors: Arc::new(Mutex::new(Vec::new())), + warnings: Arc::new(Mutex::new(Vec::new())), + } + } +} + +impl Emitter for ErrorReporter { + fn emit(&mut self, diagnostic: &DiagnosticBuilder) { + match diagnostic.diagnostic.level { + swc_core::common::errors::Level::Bug + | swc_core::common::errors::Level::Fatal + | swc_core::common::errors::Level::PhaseFatal + | swc_core::common::errors::Level::Error => { + let mut errors = self.errors.lock().unwrap(); + errors.push(diagnostic.message()); + } + swc_core::common::errors::Level::Warning + | swc_core::common::errors::Level::Note + | swc_core::common::errors::Level::Help + | swc_core::common::errors::Level::Cancelled + | swc_core::common::errors::Level::FailureNote => { + let mut warnings = self.warnings.lock().unwrap(); + warnings.push(diagnostic.message()); + } + } + } +} diff --git a/rust/cubetranspilers/src/import_export_transpiler.rs b/rust/cubetranspilers/src/import_export_transpiler.rs index fcf66a2c3a65d..036fce503d786 100644 --- a/rust/cubetranspilers/src/import_export_transpiler.rs +++ b/rust/cubetranspilers/src/import_export_transpiler.rs @@ -1,30 +1,29 @@ -use swc_core::common::{errors::HANDLER, BytePos}; +use swc_core::common::errors::Handler; +use swc_core::common::BytePos; use swc_core::common::{Span, SyntaxContext, DUMMY_SP}; use swc_core::ecma::visit::{noop_visit_mut_type, VisitMutWith}; -use swc_core::plugin::{plugin_transform, proxies::TransformPluginProgramMetadata}; use swc_core::{ - ecma::{ - ast::*, - visit::{visit_mut_pass, VisitMut}, - }, + ecma::{ast::*, visit::VisitMut}, plugin::proxies::PluginSourceMapProxy, }; -pub struct ImportExportTransformVisitor { +pub struct ImportExportTransformVisitor<'a> { pub(crate) source_map: Option, + handler: &'a Handler, } -impl ImportExportTransformVisitor { - pub fn new(source_map: Option) -> Self { - ImportExportTransformVisitor { source_map } +impl<'a> ImportExportTransformVisitor<'a> { + pub fn new(source_map: Option, handler: &'a Handler) -> Self { + ImportExportTransformVisitor { + source_map, + handler, + } } fn emit_error(&self, span: Span, message: &str) { - HANDLER.with(|handler| { - handler - .struct_span_err(span, &self.format_msg(span, message)) - .emit(); - }); + self.handler + .struct_span_err(span, &self.format_msg(span, message)) + .emit(); } fn format_msg(&self, span: Span, message: &str) -> String { @@ -48,7 +47,7 @@ impl ImportExportTransformVisitor { } } -impl VisitMut for ImportExportTransformVisitor { +impl VisitMut for ImportExportTransformVisitor<'_> { // Implement necessary visit_mut_* methods for actual custom transform. // A comprehensive list of possible visitor methods can be found here: // https://rustdoc.swc.rs/swc_ecma_visit/trait.VisitMut.html @@ -356,28 +355,6 @@ impl VisitMut for ImportExportTransformVisitor { } } -/// An example plugin function with macro support. -/// `plugin_transform` macro interop pointers into deserialized structs, as well -/// as returning ptr back to host. -/// -/// It is possible to opt out from macro by writing transform fn manually -/// if plugin need to handle low-level ptr directly via -/// `__transform_plugin_process_impl( -/// ast_ptr: *const u8, ast_ptr_len: i32, -/// unresolved_mark: u32, should_enable_comments_proxy: i32) -> -/// i32 /* 0 for success, fail otherwise. -/// Note this is only for internal pointer interop result, -/// not actual transform result */` -/// -/// This requires manual handling of serialization / deserialization from ptrs. -/// Refer swc_plugin_macro to see how does it work internally. -#[plugin_transform] -pub fn process_transform(program: Program, metadata: TransformPluginProgramMetadata) -> Program { - program.apply(&mut visit_mut_pass(ImportExportTransformVisitor { - source_map: Some(metadata.source_map), - })) -} - #[cfg(test)] mod tests { // Recommended strategy to test plugin's transform is verify @@ -392,7 +369,7 @@ mod tests { common::{ errors::{DiagnosticBuilder, Emitter, Handler, HandlerFlags}, sync::Lrc, - FileName, Globals, SourceMap, + FileName, SourceMap, }, ecma::visit::VisitMutWith, }; @@ -428,7 +405,6 @@ mod tests { #[test] fn test_export_default_declaration() { - let globals = Globals::new(); let cm: Lrc = Default::default(); let diagnostics = Arc::new(Mutex::new(Vec::new())); let emitter = Box::new(TestEmitter { @@ -446,32 +422,23 @@ mod tests { export default function exp() { console.log('exported function'); }; "#; - let mut transformed_program: Option = None; - - swc_core::common::GLOBALS.set(&globals, || { - HANDLER.set(&handler, || { - let fm = cm.new_source_file( - Arc::new(FileName::Custom("input.js".into())), - js_code.into(), - ); - let lexer = Lexer::new( - Syntax::Es(Default::default()), - EsVersion::Es2020, - StringInput::from(&*fm), - None, - ); - let mut parser = Parser::new_from(lexer); - let mut program: Program = - parser.parse_program().expect("Failed to parse the JS code"); - - let mut visitor = ImportExportTransformVisitor { source_map: None }; - program.visit_mut_with(&mut visitor); - transformed_program = Some(program); - }); - }); + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); - let transformed_program = transformed_program.expect("Transformation failed"); - let output_code = generate_code(&transformed_program, &cm); + let mut visitor = ImportExportTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); + + let output_code = generate_code(&program, &cm); assert!( output_code.contains("setExport(function()"), @@ -493,7 +460,6 @@ mod tests { #[test] fn test_export_default_expression() { - let globals = Globals::new(); let cm: Lrc = Default::default(); let diagnostics = Arc::new(Mutex::new(Vec::new())); let emitter = Box::new(TestEmitter { @@ -512,32 +478,23 @@ mod tests { export default myVar; "#; - let mut transformed_program: Option = None; - - swc_core::common::GLOBALS.set(&globals, || { - HANDLER.set(&handler, || { - let fm = cm.new_source_file( - Arc::new(FileName::Custom("input.js".into())), - js_code.into(), - ); - let lexer = Lexer::new( - Syntax::Es(Default::default()), - EsVersion::Es2020, - StringInput::from(&*fm), - None, - ); - let mut parser = Parser::new_from(lexer); - let mut program: Program = - parser.parse_program().expect("Failed to parse the JS code"); - - let mut visitor = ImportExportTransformVisitor { source_map: None }; - program.visit_mut_with(&mut visitor); - transformed_program = Some(program); - }); - }); + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = ImportExportTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); - let transformed_program = transformed_program.expect("Transformation failed"); - let output_code = generate_code(&transformed_program, &cm); + let output_code = generate_code(&program, &cm); assert!( output_code.contains("setExport(myVar)"), @@ -554,7 +511,6 @@ mod tests { #[test] fn test_export_const_expression() { - let globals = Globals::new(); let cm: Lrc = Default::default(); let diagnostics = Arc::new(Mutex::new(Vec::new())); let emitter = Box::new(TestEmitter { @@ -573,32 +529,23 @@ mod tests { export const a1 = 5, a2 = ()=>111, a3 = (inputA3)=>inputA3+"Done"; "#; - let mut transformed_program: Option = None; - - swc_core::common::GLOBALS.set(&globals, || { - HANDLER.set(&handler, || { - let fm = cm.new_source_file( - Arc::new(FileName::Custom("input.js".into())), - js_code.into(), - ); - let lexer = Lexer::new( - Syntax::Es(Default::default()), - EsVersion::Es2020, - StringInput::from(&*fm), - None, - ); - let mut parser = Parser::new_from(lexer); - let mut program: Program = - parser.parse_program().expect("Failed to parse the JS code"); - - let mut visitor = ImportExportTransformVisitor { source_map: None }; - program.visit_mut_with(&mut visitor); - transformed_program = Some(program); - }); - }); + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = ImportExportTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); - let transformed_program = transformed_program.expect("Transformation failed"); - let output_code = generate_code(&transformed_program, &cm); + let output_code = generate_code(&program, &cm); assert!( output_code.contains("const sql = (input)=>intput + 5;"), @@ -631,7 +578,6 @@ mod tests { #[test] fn test_import_named_default() { - let globals = Globals::new(); let cm: Lrc = Default::default(); let diagnostics = Arc::new(Mutex::new(Vec::new())); let emitter = Box::new(TestEmitter { @@ -652,33 +598,23 @@ mod tests { // const def = require("module"), foo = require("module").foo, baz = require("module").bar; // - let mut transformed_program: Option = None; - swc_core::common::GLOBALS.set(&globals, || { - HANDLER.set(&handler, || { - let fm = cm.new_source_file( - Arc::new(FileName::Custom("import.js".into())), - js_code.into(), - ); - let lexer = Lexer::new( - Syntax::Es(Default::default()), - EsVersion::Es2020, - StringInput::from(&*fm), - None, - ); - let mut parser = Parser::new_from(lexer); - let mut program: Program = - parser.parse_program().expect("Failed to parse the JS code"); - - { - let mut visitor = super::ImportExportTransformVisitor { source_map: None }; - program.visit_mut_with(&mut visitor); - } - transformed_program = Some(program); - }); - }); + let fm = cm.new_source_file( + Arc::new(FileName::Custom("import.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = ImportExportTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); - let transformed_program = transformed_program.expect("Transformation failed"); - let output_code = generate_code(&transformed_program, &cm); + let output_code = generate_code(&program, &cm); assert!( output_code.contains("const"), "Output code should contain a const declaration, got:\n{}", @@ -709,7 +645,6 @@ mod tests { #[test] fn test_namespace_import() { - let globals = Globals::new(); let cm: Lrc = Default::default(); let diagnostics = Arc::new(Mutex::new(Vec::new())); let emitter = Box::new(TestEmitter { @@ -727,30 +662,21 @@ mod tests { import * as ns from "module"; "#; - let mut transformed_program: Option = None; - swc_core::common::GLOBALS.set(&globals, || { - HANDLER.set(&handler, || { - let fm = cm.new_source_file( - Arc::new(FileName::Custom("ns_import.js".into())), - js_code.into(), - ); - let lexer = Lexer::new( - Syntax::Es(Default::default()), - EsVersion::Es2020, - StringInput::from(&*fm), - None, - ); - let mut parser = Parser::new_from(lexer); - let mut program: Program = - parser.parse_program().expect("Failed to parse the JS code"); - - { - let mut visitor = super::ImportExportTransformVisitor { source_map: None }; - program.visit_mut_with(&mut visitor); - } - transformed_program = Some(program); - }); - }); + let fm = cm.new_source_file( + Arc::new(FileName::Custom("ns_import.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = ImportExportTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); let diags = diagnostics.lock().unwrap(); let errors: Vec<_> = diags @@ -766,7 +692,6 @@ mod tests { #[test] fn test_export_named() { - let globals = Globals::new(); let cm: Lrc = Default::default(); let diagnostics = Arc::new(Mutex::new(Vec::new())); let emitter = Box::new(TestEmitter { @@ -789,33 +714,23 @@ mod tests { // baz: bar // }); - let mut transformed_program: Option = None; - swc_core::common::GLOBALS.set(&globals, || { - HANDLER.set(&handler, || { - let fm = cm.new_source_file( - Arc::new(FileName::Custom("export_named.js".into())), - js_code.into(), - ); - let lexer = Lexer::new( - Syntax::Es(Default::default()), - EsVersion::Es2020, - StringInput::from(&*fm), - None, - ); - let mut parser = Parser::new_from(lexer); - let mut program: Program = - parser.parse_program().expect("Failed to parse the JS code"); - - { - let mut visitor = super::ImportExportTransformVisitor { source_map: None }; - program.visit_mut_with(&mut visitor); - } - transformed_program = Some(program); - }); - }); + let fm = cm.new_source_file( + Arc::new(FileName::Custom("export_named.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); - let transformed_program = transformed_program.expect("Transformation failed"); - let output_code = generate_code(&transformed_program, &cm); + let mut visitor = ImportExportTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); + + let output_code = generate_code(&program, &cm); assert!( output_code.contains("addExport"), "Output code should contain addExport call, got:\n{}", @@ -841,7 +756,6 @@ mod tests { #[test] fn test_export_default_ts_interface() { - let globals = Globals::new(); let cm: Lrc = Default::default(); let diagnostics = Arc::new(Mutex::new(Vec::new())); let emitter = Box::new(TestEmitter { @@ -859,33 +773,23 @@ mod tests { export default interface Foo {} "#; - let mut transformed_program: Option = None; - swc_core::common::GLOBALS.set(&globals, || { - HANDLER.set(&handler, || { - let fm = cm.new_source_file( - Arc::new(FileName::Custom("export_default_ts_interface.ts".into())), - js_code.into(), - ); - let lexer = Lexer::new( - Syntax::Typescript(Default::default()), - EsVersion::Es2020, - StringInput::from(&*fm), - None, - ); - let mut parser = Parser::new_from(lexer); - let mut program: Program = - parser.parse_program().expect("Failed to parse the TS code"); - - { - let mut visitor = super::ImportExportTransformVisitor { source_map: None }; - program.visit_mut_with(&mut visitor); - } - transformed_program = Some(program); - }); - }); + let fm = cm.new_source_file( + Arc::new(FileName::Custom("export_default_ts_interface.ts".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Typescript(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the TS code"); + + let mut visitor = ImportExportTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); - let transformed_program = transformed_program.expect("Transformation failed"); - let output_code = generate_code(&transformed_program, &cm); + let output_code = generate_code(&program, &cm); // When exporting a TS interface, setExport is called with null as a fallback. assert!( output_code.contains("setExport"), diff --git a/rust/cubetranspilers/src/lib.rs b/rust/cubetranspilers/src/lib.rs index 83d39f7212fc6..e45f3b65f2ee6 100644 --- a/rust/cubetranspilers/src/lib.rs +++ b/rust/cubetranspilers/src/lib.rs @@ -3,9 +3,11 @@ use crate::cube_prop_ctx_transpiler::CubePropTransformVisitor; use crate::import_export_transpiler::ImportExportTransformVisitor; use crate::validation_transpiler::ValidationTransformVisitor; use anyhow::{anyhow, Result}; +use error_reporter::ErrorReporter; use serde::{Deserialize, Serialize}; use std::collections::{HashMap, HashSet}; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; +use swc_core::common::errors::{Handler, HandlerFlags}; use swc_core::common::input::StringInput; use swc_core::common::sync::{Lrc, OnceCell}; use swc_core::common::{FileName, SourceMap}; @@ -19,6 +21,7 @@ use swc_ecma_parser::{Parser, Syntax}; pub mod check_dup_prop_transpiler; pub mod cube_prop_ctx_transpiler; +pub mod error_reporter; pub mod import_export_transpiler; pub mod validation_transpiler; @@ -80,13 +83,25 @@ pub fn run_transpilers( source_file: sm_cell, }; + let errors = Arc::new(Mutex::new(Vec::new())); + let warnings = Arc::new(Mutex::new(Vec::new())); + + let reporter = Box::new(ErrorReporter::new(errors.clone(), warnings.clone())); + let handler = Handler::with_emitter_and_flags( + reporter, + HandlerFlags { + can_emit_warnings: true, + ..Default::default() + }, + ); + transform_config .transpilers .into_iter() .for_each(|transpiler| match transpiler { Transpilers::CubeCheckDuplicatePropTranspiler => { let mut visitor = - CheckDupPropTransformVisitor::new(Some(plugin_source_map.clone())); + CheckDupPropTransformVisitor::new(Some(plugin_source_map.clone()), &handler); program.visit_mut_with(&mut visitor); } Transpilers::CubePropContextTranspiler => { @@ -95,26 +110,30 @@ pub fn run_transpilers( transform_config.cube_symbols.clone(), transform_config.context_symbols.clone(), Some(plugin_source_map.clone()), + &handler, ); program.visit_mut_with(&mut visitor); } Transpilers::ImportExportTranspiler => { let mut visitor = - ImportExportTransformVisitor::new(Some(plugin_source_map.clone())); + ImportExportTransformVisitor::new(Some(plugin_source_map.clone()), &handler); program.visit_mut_with(&mut visitor); } Transpilers::ValidationTranspiler => { - let mut visitor = ValidationTransformVisitor::new(Some(plugin_source_map.clone())); + let mut visitor = + ValidationTransformVisitor::new(Some(plugin_source_map.clone()), &handler); program.visit_mut_with(&mut visitor); } }); let output_code = generate_code(&program, &sm)?; + let errors = errors.lock().unwrap().clone(); + let warnings = warnings.lock().unwrap().clone(); Ok(TransformResult { code: output_code, - errors: vec![], - warnings: vec![], + errors, + warnings, }) } diff --git a/rust/cubetranspilers/src/validation_transpiler.rs b/rust/cubetranspilers/src/validation_transpiler.rs index 8145eef63c440..a3cfee6567daa 100644 --- a/rust/cubetranspilers/src/validation_transpiler.rs +++ b/rust/cubetranspilers/src/validation_transpiler.rs @@ -1,31 +1,30 @@ +use swc_core::common::errors::Handler; +use swc_core::common::BytePos; use swc_core::common::Span; -use swc_core::common::{errors::HANDLER, BytePos}; use swc_core::ecma::visit::noop_visit_mut_type; use swc_core::plugin::proxies::PluginSourceMapProxy; -use swc_core::plugin::proxies::TransformPluginProgramMetadata; use swc_core::{ atoms::JsWord, - ecma::{ - ast::*, - visit::{visit_mut_pass, VisitMut}, - }, + ecma::{ast::*, visit::VisitMut}, }; -pub struct ValidationTransformVisitor { +pub struct ValidationTransformVisitor<'a> { pub(crate) source_map: Option, + handler: &'a Handler, } -impl ValidationTransformVisitor { - pub fn new(source_map: Option) -> Self { - ValidationTransformVisitor { source_map } +impl<'a> ValidationTransformVisitor<'a> { + pub fn new(source_map: Option, handler: &'a Handler) -> Self { + ValidationTransformVisitor { + source_map, + handler, + } } fn emit_warn(&self, span: Span, message: &str) { - HANDLER.with(|handler| { - handler - .struct_span_warn(span, &self.format_msg(span, message)) - .emit(); - }); + self.handler + .struct_span_warn(span, &self.format_msg(span, message)) + .emit(); } fn format_msg(&self, span: Span, message: &str) -> String { @@ -49,7 +48,7 @@ impl ValidationTransformVisitor { } } -impl VisitMut for ValidationTransformVisitor { +impl VisitMut for ValidationTransformVisitor<'_> { // Implement necessary visit_mut_* methods for actual custom transform. // A comprehensive list of possible visitor methods can be found here: // https://rustdoc.swc.rs/swc_ecma_visit/trait.VisitMut.html @@ -70,12 +69,6 @@ impl VisitMut for ValidationTransformVisitor { } } -pub fn process_transform(program: Program, metadata: TransformPluginProgramMetadata) -> Program { - program.apply(&mut visit_mut_pass(ValidationTransformVisitor { - source_map: Some(metadata.source_map), - })) -} - #[cfg(test)] mod tests { // Recommended strategy to test plugin's transform is verify @@ -90,7 +83,7 @@ mod tests { common::{ errors::{DiagnosticBuilder, Emitter, Handler, HandlerFlags}, sync::Lrc, - FileName, Globals, SourceMap, + FileName, SourceMap, }, ecma::visit::VisitMutWith, }; @@ -109,7 +102,6 @@ mod tests { #[test] fn test_warning_for_user_context() { - let globals = Globals::new(); let cm: Lrc = Default::default(); let diagnostics = Arc::new(Mutex::new(Vec::new())); let emitter = Box::new(TestEmitter { @@ -125,26 +117,21 @@ mod tests { let js_code = "USER_CONTEXT.something;"; - swc_core::common::GLOBALS.set(&globals, || { - HANDLER.set(&handler, || { - let fm = cm.new_source_file( - Arc::new(FileName::Custom("input.js".into())), - js_code.into(), - ); - let lexer = Lexer::new( - Syntax::Es(Default::default()), - EsVersion::Es2020, - StringInput::from(&*fm), - None, - ); - let mut parser = Parser::new_from(lexer); - let mut program: Program = - parser.parse_program().expect("Failed to parse the JS code"); - - let mut visitor = ValidationTransformVisitor { source_map: None }; - program.visit_mut_with(&mut visitor); - }); - }); + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = ValidationTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); let diags = diagnostics.lock().unwrap(); assert!( @@ -157,7 +144,6 @@ mod tests { #[test] fn test_no_warnings() { - let globals = Globals::new(); let cm: Lrc = Default::default(); let diagnostics = Arc::new(Mutex::new(Vec::new())); let emitter = Box::new(TestEmitter { @@ -173,26 +159,21 @@ mod tests { let js_code = "SECURITY_CONTEXT.something; let someOtherVar = 5;"; - swc_core::common::GLOBALS.set(&globals, || { - HANDLER.set(&handler, || { - let fm = cm.new_source_file( - Arc::new(FileName::Custom("input.js".into())), - js_code.into(), - ); - let lexer = Lexer::new( - Syntax::Es(Default::default()), - EsVersion::Es2020, - StringInput::from(&*fm), - None, - ); - let mut parser = Parser::new_from(lexer); - let mut program: Program = - parser.parse_program().expect("Failed to parse the JS code"); - - let mut visitor = ValidationTransformVisitor { source_map: None }; - program.visit_mut_with(&mut visitor); - }); - }); + let fm = cm.new_source_file( + Arc::new(FileName::Custom("input.js".into())), + js_code.into(), + ); + let lexer = Lexer::new( + Syntax::Es(Default::default()), + EsVersion::Es2020, + StringInput::from(&*fm), + None, + ); + let mut parser = Parser::new_from(lexer); + let mut program: Program = parser.parse_program().expect("Failed to parse the JS code"); + + let mut visitor = ValidationTransformVisitor::new(None, &handler); + program.visit_mut_with(&mut visitor); let diags = diagnostics.lock().unwrap(); assert!(diags.is_empty(), "Should not emit warning",);