feat(napi/transform): allow setting sourceType to transform (#4113)

closes #4071

Co-authored-by: Boshen <1430279+Boshen@users.noreply.github.com>
This commit is contained in:
Boshen 2024-07-08 19:09:45 +08:00 committed by GitHub
parent 2687ebc1c5
commit 720983a965
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 66 additions and 56 deletions

View file

@ -56,7 +56,7 @@ fn parse<'a>(
let source_type = options
.source_filename
.as_ref()
.map(|name| SourceType::from_path(name).unwrap())
.and_then(|name| SourceType::from_path(name).ok())
.unwrap_or_default();
let source_type = match options.source_type.as_deref() {
Some("script") => source_type.with_script(true),

View file

@ -0,0 +1,42 @@
use std::sync::Arc;
use napi_derive::napi;
use oxc_allocator::Allocator;
use oxc_codegen::CodeGenerator;
use oxc_diagnostics::{Error, NamedSource};
use oxc_isolated_declarations::IsolatedDeclarations;
use oxc_parser::Parser;
use oxc_span::SourceType;
#[napi(object)]
pub struct IsolatedDeclarationsResult {
pub source_text: String,
pub errors: Vec<String>,
}
/// TypeScript Isolated Declarations for Standalone DTS Emit
#[allow(clippy::needless_pass_by_value)]
#[napi]
pub fn isolated_declaration(filename: String, source_text: String) -> IsolatedDeclarationsResult {
let source_type = SourceType::from_path(&filename).unwrap_or_default().with_typescript(true);
let allocator = Allocator::default();
let parser_ret = Parser::new(&allocator, &source_text, source_type).parse();
let transformed_ret = IsolatedDeclarations::new(&allocator).build(&parser_ret.program);
let printed = CodeGenerator::new().build(&transformed_ret.program).source_text;
let mut errors = vec![];
if !parser_ret.errors.is_empty() || !transformed_ret.errors.is_empty() {
let source = Arc::new(NamedSource::new(filename, source_text.to_string()));
errors.extend(
parser_ret
.errors
.into_iter()
.chain(transformed_ret.errors)
.map(|diagnostic| Error::from(diagnostic).with_source_code(Arc::clone(&source)))
.map(|error| format!("{error:?}")),
);
}
IsolatedDeclarationsResult { source_text: printed, errors }
}

View file

@ -1,44 +1,4 @@
pub mod transformer;
mod isolated_declaration;
mod transformer;
use std::sync::Arc;
use napi_derive::napi;
use oxc_allocator::Allocator;
use oxc_codegen::CodeGenerator;
use oxc_diagnostics::{Error, NamedSource};
use oxc_isolated_declarations::IsolatedDeclarations;
use oxc_parser::Parser;
use oxc_span::SourceType;
#[napi(object)]
pub struct IsolatedDeclarationsResult {
pub source_text: String,
pub errors: Vec<String>,
}
/// TypeScript Isolated Declarations for Standalone DTS Emit
#[allow(clippy::needless_pass_by_value)]
#[napi]
pub fn isolated_declaration(filename: String, source_text: String) -> IsolatedDeclarationsResult {
let source_type = SourceType::from_path(&filename).unwrap_or_default().with_typescript(true);
let allocator = Allocator::default();
let parser_ret = Parser::new(&allocator, &source_text, source_type).parse();
let transformed_ret = IsolatedDeclarations::new(&allocator).build(&parser_ret.program);
let printed = CodeGenerator::new().build(&transformed_ret.program).source_text;
let mut errors = vec![];
if !parser_ret.errors.is_empty() || !transformed_ret.errors.is_empty() {
let source = Arc::new(NamedSource::new(filename, source_text.to_string()));
errors.extend(
parser_ret
.errors
.into_iter()
.chain(transformed_ret.errors)
.map(|diagnostic| Error::from(diagnostic).with_source_code(Arc::clone(&source)))
.map(|error| format!("{error:?}")),
);
}
IsolatedDeclarationsResult { source_text: printed, errors }
}
pub use crate::{isolated_declaration::*, transformer::*};

View file

@ -1,13 +1,14 @@
use std::path::Path;
use napi_derive::napi;
use oxc_allocator::Allocator;
use oxc_codegen::CodeGenerator;
use oxc_parser::Parser;
use oxc_span::SourceType;
use oxc_transformer::{
ArrowFunctionsOptions, ES2015Options, ReactJsxRuntime, ReactOptions, TransformOptions,
Transformer, TypeScriptOptions,
ArrowFunctionsOptions, ES2015Options, ReactJsxRuntime, ReactOptions, Transformer,
TypeScriptOptions,
};
#[napi(object)]
@ -92,7 +93,9 @@ impl From<ES2015BindingOptions> for ES2015Options {
}
#[napi(object)]
pub struct TransformBindingOptions {
pub struct TransformOptions {
#[napi(ts_type = "'script' | 'module' | 'unambiguous' | undefined")]
pub source_type: Option<String>,
pub typescript: Option<TypeScriptBindingOptions>,
pub react: Option<ReactBindingOptions>,
pub es2015: Option<ES2015BindingOptions>,
@ -104,13 +107,13 @@ pub struct TransformBindingOptions {
pub sourcemap: Option<bool>,
}
impl From<TransformBindingOptions> for TransformOptions {
fn from(options: TransformBindingOptions) -> Self {
TransformOptions {
impl From<TransformOptions> for oxc_transformer::TransformOptions {
fn from(options: TransformOptions) -> Self {
Self {
typescript: options.typescript.map(Into::into).unwrap_or_default(),
react: options.react.map(Into::into).unwrap_or_default(),
es2015: options.es2015.map(Into::into).unwrap_or_default(),
..TransformOptions::default()
..Self::default()
}
}
}
@ -137,13 +140,18 @@ pub struct TransformResult {
pub fn transform(
filename: String,
source_text: String,
options: Option<TransformBindingOptions>,
options: Option<TransformOptions>,
) -> TransformResult {
let sourcemap = options.as_ref().is_some_and(|x| x.sourcemap.unwrap_or_default());
let mut errors = vec![];
let source_path = Path::new(&filename);
let source_type = SourceType::from_path(source_path).unwrap_or_default();
let source_type = SourceType::from_path(&filename).unwrap_or_default();
let source_type = match options.as_ref().and_then(|options| options.source_type.as_deref()) {
Some("script") => source_type.with_script(true),
Some("module") => source_type.with_module(true),
_ => source_type,
};
let allocator = Allocator::default();
let parser_ret = Parser::new(&allocator, &source_text, source_type).parse();
if !parser_ret.errors.is_empty() {
@ -154,7 +162,7 @@ pub fn transform(
let transform_options = options.map(Into::into).unwrap_or_default();
let ret = Transformer::new(
&allocator,
source_path,
Path::new(&filename),
source_type,
&source_text,
parser_ret.trivias.clone(),
@ -168,7 +176,7 @@ pub fn transform(
let mut codegen = CodeGenerator::new();
if sourcemap {
codegen = codegen.enable_source_map(source_path.to_string_lossy().as_ref(), &source_text);
codegen = codegen.enable_source_map(&filename, &source_text);
}
let ret = codegen.build(&program);