Skip to content

Commit

Permalink
feat(napi/transform): allow setting sourceType to transform (#4113)
Browse files Browse the repository at this point in the history
closes #4071

Co-authored-by: Boshen <[email protected]>
  • Loading branch information
Boshen and Boshen authored Jul 8, 2024
1 parent 2687ebc commit 720983a
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 56 deletions.
2 changes: 1 addition & 1 deletion napi/parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
42 changes: 42 additions & 0 deletions napi/transform/src/isolated_declaration.rs
Original file line number Diff line number Diff line change
@@ -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 }
}
46 changes: 3 additions & 43 deletions napi/transform/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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::*};
32 changes: 20 additions & 12 deletions napi/transform/src/transformer.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand Down Expand Up @@ -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>,
Expand All @@ -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()
}
}
}
Expand All @@ -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() {
Expand All @@ -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(),
Expand All @@ -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);

Expand Down

0 comments on commit 720983a

Please sign in to comment.