Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions crates/oxc_transformer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,18 @@ impl<'a> Transformer<'a> {
}

pub fn build_with_symbols_and_scopes(
self,
mut self,
symbols: SymbolTable,
scopes: ScopeTree,
program: &mut Program<'a>,
) -> TransformerReturn {
let allocator = self.allocator;
let ast_builder = AstBuilder::new(allocator);

react::update_options_with_comments(&mut self.options, &self.ctx);

let mut transformer = TransformerImpl {
x0_typescript: TypeScript::new(self.options.typescript, &self.ctx),
x0_typescript: TypeScript::new(&self.options.typescript, &self.ctx),
x1_react: React::new(self.options.react, ast_builder, &self.ctx),
x2_es2021: ES2021::new(self.options.es2021, &self.ctx),
x2_es2020: ES2020::new(self.options.es2020, &self.ctx),
Expand Down
30 changes: 23 additions & 7 deletions crates/oxc_transformer/src/react/comments.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use std::borrow::Cow;

use oxc_ast::{Comment, CommentKind};
use oxc_syntax::identifier::is_irregular_whitespace;

use crate::{JsxOptions, JsxRuntime, TransformCtx};
use crate::{JsxRuntime, TransformCtx, TransformOptions};

/// Scan through all comments and find the following pragmas:
///
Expand All @@ -14,35 +16,49 @@ use crate::{JsxOptions, JsxRuntime, TransformCtx};
/// otherwise `JSDoc` could be used instead.
///
/// This behavior is aligned with Babel.
pub(crate) fn update_options_with_comments(options: &mut JsxOptions, ctx: &TransformCtx) {
pub(crate) fn update_options_with_comments(options: &mut TransformOptions, ctx: &TransformCtx) {
for comment in ctx.trivias.comments() {
update_options_with_comment(options, comment, ctx.source_text);
}
}

fn update_options_with_comment(options: &mut JsxOptions, comment: &Comment, source_text: &str) {
fn update_options_with_comment(
options: &mut TransformOptions,
comment: &Comment,
source_text: &str,
) {
let Some((keyword, remainder)) = find_jsx_pragma(comment, source_text) else { return };

match keyword {
// @jsx
"" => {
options.pragma = Some(remainder.to_string());
// Don't set React option unless React transform is enabled
// otherwise can cause error in `ReactJsx::new`
if options.react.jsx_plugin || options.react.development {
options.react.pragma = Some(remainder.to_string());
}
options.typescript.jsx_pragma = Cow::from(remainder.to_string());
}
// @jsxRuntime
"Runtime" => {
options.runtime = match remainder {
options.react.runtime = match remainder {
"classic" => JsxRuntime::Classic,
"automatic" => JsxRuntime::Automatic,
_ => return,
};
}
// @jsxImportSource
"ImportSource" => {
options.import_source = Some(remainder.to_string());
options.react.import_source = Some(remainder.to_string());
}
// @jsxFrag
"Frag" => {
options.pragma_frag = Some(remainder.to_string());
// Don't set React option unless React transform is enabled
// otherwise can cause error in `ReactJsx::new`
if options.react.jsx_plugin || options.react.development {
options.react.pragma_frag = Some(remainder.to_string());
}
options.typescript.jsx_pragma_frag = Cow::from(remainder.to_string());
}
_ => {}
}
Expand Down
3 changes: 1 addition & 2 deletions crates/oxc_transformer/src/react/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub use self::{
};
use crate::TransformCtx;

use comments::update_options_with_comments;
pub(crate) use comments::update_options_with_comments;

/// [Preset React](https://babel.dev/docs/babel-preset-react)
///
Expand All @@ -45,7 +45,6 @@ pub struct React<'a, 'ctx> {
impl<'a, 'ctx> React<'a, 'ctx> {
pub fn new(mut options: JsxOptions, ast: AstBuilder<'a>, ctx: &'ctx TransformCtx<'a>) -> Self {
if options.jsx_plugin || options.development {
update_options_with_comments(&mut options, ctx);
options.conform();
}
let JsxOptions {
Expand Down
9 changes: 4 additions & 5 deletions crates/oxc_transformer/src/typescript/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,14 @@ pub struct TypeScript<'a, 'ctx> {
}

impl<'a, 'ctx> TypeScript<'a, 'ctx> {
pub fn new(mut options: TypeScriptOptions, ctx: &'ctx TransformCtx<'a>) -> Self {
options.update_with_comments(ctx);
pub fn new(options: &TypeScriptOptions, ctx: &'ctx TransformCtx<'a>) -> Self {
Self {
ctx,
annotations: TypeScriptAnnotations::new(&options, ctx),
annotations: TypeScriptAnnotations::new(options, ctx),
r#enum: TypeScriptEnum::new(),
namespace: TypeScriptNamespace::new(&options, ctx),
namespace: TypeScriptNamespace::new(options, ctx),
module: TypeScriptModule::new(ctx),
rewrite_extensions: TypeScriptRewriteExtensions::new(&options),
rewrite_extensions: TypeScriptRewriteExtensions::new(options),
}
}
}
Expand Down
37 changes: 0 additions & 37 deletions crates/oxc_transformer/src/typescript/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ use serde::{
Deserialize, Deserializer,
};

use crate::context::TransformCtx;

fn default_for_jsx_pragma() -> Cow<'static, str> {
Cow::Borrowed("React.createElement")
}
Expand Down Expand Up @@ -60,41 +58,6 @@ pub struct TypeScriptOptions {
pub rewrite_import_extensions: Option<RewriteExtensionsMode>,
}

impl TypeScriptOptions {
/// Scan through all comments and find the following pragmas
///
/// * @jsx React.createElement
/// * @jsxFrag React.Fragment
///
/// The comment does not need to be a jsdoc,
/// otherwise `JSDoc` could be used instead.
///
/// This behavior is aligned with babel.
pub(crate) fn update_with_comments(&mut self, ctx: &TransformCtx) {
for comment in ctx.trivias.comments() {
let mut comment = comment.span.source_text(ctx.source_text).trim_start();
// strip leading jsdoc comment `*` and then whitespaces
while let Some(cur_comment) = comment.strip_prefix('*') {
comment = cur_comment.trim_start();
}
// strip leading `@`
let Some(comment) = comment.strip_prefix('@') else { continue };

// read jsxFrag
if let Some(pragma_frag) = comment.strip_prefix("jsxFrag").map(str::trim) {
self.jsx_pragma_frag = Cow::from(pragma_frag.to_string());
continue;
}

// Put this condition at the end to avoid breaking @jsxXX
// read jsx
if let Some(pragma) = comment.strip_prefix("jsx").map(str::trim) {
self.jsx_pragma = Cow::from(pragma.to_string());
}
}
}
}

impl Default for TypeScriptOptions {
fn default() -> Self {
Self {
Expand Down