diff --git a/napi/transform/src/context.rs b/napi/transform/src/context.rs deleted file mode 100644 index 22b045e16b5ff..0000000000000 --- a/napi/transform/src/context.rs +++ /dev/null @@ -1,124 +0,0 @@ -use std::{ - cell::{Ref, RefCell}, - sync::Arc, -}; - -use oxc::{ - allocator::Allocator, - ast::{ast::Program, Trivias}, - codegen::Codegen, - diagnostics::{Error, NamedSource, OxcDiagnostic}, - parser::{Parser, ParserReturn}, - span::SourceType, -}; - -#[must_use] -pub(crate) struct TransformContext<'a> { - pub allocator: &'a Allocator, - program: RefCell>, - pub trivias: Trivias, - - /// Generate source maps? - source_map: bool, - - /// Path to the file being transformed. - filename: &'a str, - - /// Source text of the file being transformed. - source_text: &'a str, - source_type: SourceType, - - /// Errors that occurred during transformation. - errors: RefCell>, -} - -impl<'a> TransformContext<'a> { - pub fn new( - allocator: &'a Allocator, - filename: &'a str, - source_text: &'a str, - source_type: SourceType, - source_map: Option, - ) -> Self { - let ParserReturn { errors, program, trivias, .. } = - Parser::new(allocator, source_text, source_type).parse(); - let source_map = source_map.unwrap_or_default(); - Self { - allocator, - program: RefCell::new(program), - trivias, - - source_map, - - filename, - source_text, - source_type, - errors: RefCell::new(errors), - } - } - - #[inline] - pub fn file_name(&self) -> &'a str { - self.filename - } - - #[inline] - pub fn source_text(&self) -> &'a str { - self.source_text - } - - #[inline] - pub fn program(&self) -> Ref<'_, Program<'a>> { - self.program.borrow() - } - - pub fn codegen(&self) -> Codegen<'a> { - let codegen = Codegen::new(); - if self.source_map { - codegen.enable_source_map(self.file_name(), self.source_text()) - } else { - codegen - } - } - - pub fn add_diagnostics(&self, diagnostics: Vec) { - if diagnostics.is_empty() { - return; - } - self.errors.borrow_mut().extend(diagnostics); - } - - pub fn take_and_render_reports(&self) -> Vec { - let diagnostics = std::mem::take(&mut *self.errors.borrow_mut()); - // TODO: make pretty-printed errors configurable - self.wrap_diagnostics(diagnostics).map(|error| format!("{error:?}")).collect() - } - - fn wrap_diagnostics>( - &self, - diagnostics: D, - ) -> impl Iterator { - let source = { - let lang = match (self.source_type.is_javascript(), self.source_type.is_jsx()) { - (true, false) => "JavaScript", - (true, true) => "JSX", - (false, true) => "TypeScript React", - (false, false) => { - if self.source_type.is_typescript_definition() { - "TypeScript Declaration" - } else { - "TypeScript" - } - } - }; - - let ns = NamedSource::new(self.file_name(), self.source_text().to_string()) - .with_language(lang); - Arc::new(ns) - }; - - diagnostics - .into_iter() - .map(move |diagnostic| Error::from(diagnostic).with_source_code(Arc::clone(&source))) - } -} diff --git a/napi/transform/src/errors.rs b/napi/transform/src/errors.rs new file mode 100644 index 0000000000000..339184c439297 --- /dev/null +++ b/napi/transform/src/errors.rs @@ -0,0 +1,40 @@ +use std::sync::Arc; + +use oxc::{ + diagnostics::{Error, NamedSource, OxcDiagnostic}, + span::SourceType, +}; + +pub fn wrap_diagnostics( + filename: &str, + source_type: SourceType, + source_text: &str, + errors: Vec, +) -> Vec { + if errors.is_empty() { + return vec![]; + } + let source = { + let lang = match (source_type.is_javascript(), source_type.is_jsx()) { + (true, false) => "JavaScript", + (true, true) => "JSX", + (false, true) => "TypeScript React", + (false, false) => { + if source_type.is_typescript_definition() { + "TypeScript Declaration" + } else { + "TypeScript" + } + } + }; + + let ns = NamedSource::new(filename, source_text.to_string()).with_language(lang); + Arc::new(ns) + }; + + errors + .into_iter() + .map(move |diagnostic| Error::from(diagnostic).with_source_code(Arc::clone(&source))) + .map(|error| format!("{error:?}")) + .collect() +} diff --git a/napi/transform/src/isolated_declaration.rs b/napi/transform/src/isolated_declaration.rs index 957309339dbfb..e8b531d24d013 100644 --- a/napi/transform/src/isolated_declaration.rs +++ b/napi/transform/src/isolated_declaration.rs @@ -1,13 +1,18 @@ use napi_derive::napi; + use oxc::{ allocator::Allocator, - codegen::{CodegenReturn, CommentOptions}, + codegen::{CodeGenerator, CommentOptions}, isolated_declarations::IsolatedDeclarations, - napi::isolated_declarations::{IsolatedDeclarationsOptions, IsolatedDeclarationsResult}, + napi::{ + isolated_declarations::{IsolatedDeclarationsOptions, IsolatedDeclarationsResult}, + source_map::SourceMap, + }, + parser::Parser, span::SourceType, }; -use crate::context::TransformContext; +use crate::errors::wrap_diagnostics; /// TypeScript Isolated Declarations for Standalone DTS Emit #[allow(clippy::needless_pass_by_value)] @@ -20,36 +25,35 @@ pub fn isolated_declaration( let source_type = SourceType::from_path(&filename).unwrap_or_default().with_typescript(true); let allocator = Allocator::default(); let options = options.unwrap_or_default(); - let ctx = - TransformContext::new(&allocator, &filename, &source_text, source_type, options.sourcemap); - let transformed_ret = build_declarations(&ctx, options); - IsolatedDeclarationsResult { - code: transformed_ret.source_text, - map: options.sourcemap.and_then(|_| transformed_ret.source_map.map(Into::into)), - errors: ctx.take_and_render_reports(), - } -} + let ret = Parser::new(&allocator, &source_text, source_type).parse(); -pub(crate) fn build_declarations( - ctx: &TransformContext<'_>, - options: IsolatedDeclarationsOptions, -) -> CodegenReturn { let transformed_ret = IsolatedDeclarations::new( - ctx.allocator, - ctx.source_text(), - &ctx.trivias, + &allocator, + &source_text, + &ret.trivias, oxc::isolated_declarations::IsolatedDeclarationsOptions { strip_internal: options.strip_internal.unwrap_or(false), }, ) - .build(&ctx.program()); - ctx.add_diagnostics(transformed_ret.errors); - ctx.codegen() - .enable_comment( - ctx.source_text(), - ctx.trivias.clone(), - CommentOptions { preserve_annotate_comments: false }, - ) - .build(&transformed_ret.program) + .build(&ret.program); + + let mut codegen = CodeGenerator::new().enable_comment( + &source_text, + ret.trivias.clone(), + CommentOptions { preserve_annotate_comments: false }, + ); + if options.sourcemap == Some(true) { + codegen = codegen.enable_source_map(&filename, &source_text); + } + let codegen_ret = codegen.build(&transformed_ret.program); + + let errors = ret.errors.into_iter().chain(transformed_ret.errors).collect(); + let errors = wrap_diagnostics(&filename, source_type, &source_text, errors); + + IsolatedDeclarationsResult { + code: codegen_ret.source_text, + map: codegen_ret.source_map.map(SourceMap::from), + errors, + } } diff --git a/napi/transform/src/lib.rs b/napi/transform/src/lib.rs index bcab5391a0575..ad8e001a33cb3 100644 --- a/napi/transform/src/lib.rs +++ b/napi/transform/src/lib.rs @@ -1,4 +1,4 @@ -mod context; +mod errors; pub use oxc::napi::{isolated_declarations, transform}; diff --git a/napi/transform/src/transformer.rs b/napi/transform/src/transformer.rs index 544511c2e5338..2fe315d5d6be4 100644 --- a/napi/transform/src/transformer.rs +++ b/napi/transform/src/transformer.rs @@ -1,11 +1,11 @@ -use std::{path::Path, sync::Arc}; +use std::path::Path; use napi::Either; use napi_derive::napi; use oxc::{ codegen::CodegenReturn, - diagnostics::{Error, NamedSource, OxcDiagnostic}, + diagnostics::OxcDiagnostic, napi::{ source_map::SourceMap, transform::{TransformOptions, TransformResult}, @@ -15,6 +15,8 @@ use oxc::{ CompilerInterface, }; +use crate::errors::wrap_diagnostics; + #[derive(Default)] struct Compiler { transform_options: oxc::transformer::TransformOptions, @@ -168,37 +170,3 @@ pub fn transform( errors: wrap_diagnostics(&filename, source_type, &source_text, compiler.errors), } } - -fn wrap_diagnostics( - filename: &str, - source_type: SourceType, - source_text: &str, - errors: Vec, -) -> Vec { - if errors.is_empty() { - return vec![]; - } - let source = { - let lang = match (source_type.is_javascript(), source_type.is_jsx()) { - (true, false) => "JavaScript", - (true, true) => "JSX", - (false, true) => "TypeScript React", - (false, false) => { - if source_type.is_typescript_definition() { - "TypeScript Declaration" - } else { - "TypeScript" - } - } - }; - - let ns = NamedSource::new(filename, source_text.to_string()).with_language(lang); - Arc::new(ns) - }; - - errors - .into_iter() - .map(move |diagnostic| Error::from(diagnostic).with_source_code(Arc::clone(&source))) - .map(|error| format!("{error:?}")) - .collect() -}