feat(transformer): add transform context to all plugins (#2931)

This commit is contained in:
Boshen 2024-04-10 14:49:00 +08:00 committed by GitHub
parent 0a77d621e2
commit 255c74ccc5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 140 additions and 107 deletions

View file

@ -0,0 +1,37 @@
use std::{cell::RefCell, mem, rc::Rc};
use oxc_allocator::Allocator;
use oxc_ast::AstBuilder;
use oxc_diagnostics::Error;
use oxc_semantic::Semantic;
use oxc_span::SourceType;
pub type Ctx<'a> = Rc<TransformCtx<'a>>;
pub struct TransformCtx<'a> {
pub ast: AstBuilder<'a>,
pub source_type: SourceType,
pub semantic: Semantic<'a>,
errors: RefCell<Vec<Error>>,
}
impl<'a> TransformCtx<'a> {
pub fn new(allocator: &'a Allocator, source_type: SourceType, semantic: Semantic<'a>) -> Self {
Self {
ast: AstBuilder::new(allocator),
source_type,
semantic,
errors: RefCell::new(vec![]),
}
}
pub fn take_errors(&self) -> Vec<Error> {
mem::take(&mut self.errors.borrow_mut())
}
/// Add an Error
#[allow(unused)]
pub fn error<T: Into<Error>>(&self, error: T) {
self.errors.borrow_mut().push(error.into());
}
}

View file

@ -1,26 +1,30 @@
use std::rc::Rc;
use serde::Deserialize; use serde::Deserialize;
use oxc_ast::ast::*; use oxc_ast::ast::*;
use crate::context::Ctx;
/// Only `"2023-11"` will be implemented because Babel 8 will only support "2023-11" and "legacy". /// Only `"2023-11"` will be implemented because Babel 8 will only support "2023-11" and "legacy".
#[derive(Debug, Default, Clone, Deserialize)] #[derive(Debug, Default, Clone, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct DecoratorsOptions; pub struct DecoratorsOptions;
/// [proposal-decorators](https://babeljs.io/docs/babel-plugin-proposal-decorators) /// [proposal-decorators](https://babeljs.io/docs/babel-plugin-proposal-decorators)
#[derive(Debug, Default)] #[allow(unused)]
pub struct Decorators { pub struct Decorators<'a> {
#[allow(unused)]
options: DecoratorsOptions, options: DecoratorsOptions,
ctx: Ctx<'a>,
} }
impl Decorators { impl<'a> Decorators<'a> {
pub fn new(options: DecoratorsOptions) -> Self { pub fn new(options: DecoratorsOptions, ctx: &Ctx<'a>) -> Self {
Self { options } Self { options, ctx: Rc::clone(ctx) }
} }
} }
// Transformers // Transformers
impl Decorators { impl<'a> Decorators<'a> {
pub fn transform_statement(&mut self, _stmt: &mut Statement<'_>) {} pub fn transform_statement(&mut self, _stmt: &mut Statement<'_>) {}
} }

View file

@ -9,11 +9,14 @@
// Core // Core
mod compiler_assumptions; mod compiler_assumptions;
// Plugins: <https://babeljs.io/docs/plugins-list> mod context;
// Presets: <https://babel.dev/docs/presets>
mod decorators; mod decorators;
mod react; mod react;
mod typescript; mod typescript;
use std::rc::Rc;
use oxc_allocator::Allocator; use oxc_allocator::Allocator;
use oxc_ast::{ use oxc_ast::{
ast::*, ast::*,
@ -26,13 +29,12 @@ use oxc_span::SourceType;
pub use crate::{ pub use crate::{
compiler_assumptions::CompilerAssumptions, compiler_assumptions::CompilerAssumptions,
decorators::{Decorators, DecoratorsOptions}, decorators::{Decorators, DecoratorsOptions},
react::{ react::{React, ReactDisplayName, ReactJsx, ReactJsxSelf, ReactJsxSource, ReactOptions},
React, ReactDisplayName, ReactDisplayNameOptions, ReactJsx, ReactJsxSelf, ReactJsxSource,
ReactJsxSourceOptions, ReactOptions,
},
typescript::{TypeScript, TypeScriptOptions}, typescript::{TypeScript, TypeScriptOptions},
}; };
use crate::context::{Ctx, TransformCtx};
#[allow(unused)] #[allow(unused)]
#[derive(Debug, Default, Clone)] #[derive(Debug, Default, Clone)]
pub struct TransformOptions { pub struct TransformOptions {
@ -54,15 +56,11 @@ pub struct TransformOptions {
#[allow(unused)] #[allow(unused)]
pub struct Transformer<'a> { pub struct Transformer<'a> {
allocator: &'a Allocator, ctx: Ctx<'a>,
source_type: SourceType,
semantic: Semantic<'a>,
options: TransformOptions,
// NOTE: all callbacks must run in order. // NOTE: all callbacks must run in order.
x0_typescript: TypeScript, x0_typescript: TypeScript<'a>,
x1_react: React, x1_react: React<'a>,
x2_decorators: Decorators, x2_decorators: Decorators<'a>,
} }
impl<'a> Transformer<'a> { impl<'a> Transformer<'a> {
@ -72,14 +70,12 @@ impl<'a> Transformer<'a> {
semantic: Semantic<'a>, semantic: Semantic<'a>,
options: TransformOptions, options: TransformOptions,
) -> Self { ) -> Self {
let ctx = Rc::new(TransformCtx::new(allocator, source_type, semantic));
Self { Self {
allocator, ctx: Rc::clone(&ctx),
source_type, x0_typescript: TypeScript::new(options.typescript, &ctx),
semantic, x1_react: React::new(options.react, &ctx),
options, x2_decorators: Decorators::new(options.decorators, &ctx),
x0_typescript: TypeScript::default(),
x1_react: React::default(),
x2_decorators: Decorators::default(),
} }
} }
@ -88,7 +84,12 @@ impl<'a> Transformer<'a> {
/// Returns `Vec<Error>` if any errors were collected during the transformation. /// Returns `Vec<Error>` if any errors were collected during the transformation.
pub fn build(mut self, program: &mut Program<'a>) -> Result<(), Vec<Error>> { pub fn build(mut self, program: &mut Program<'a>) -> Result<(), Vec<Error>> {
self.visit_program(program); self.visit_program(program);
Ok(()) let errors = self.ctx.take_errors();
if errors.is_empty() {
Ok(())
} else {
Err(errors)
}
} }
} }

View file

@ -1,8 +1,6 @@
use serde::Deserialize; use std::rc::Rc;
#[derive(Debug, Default, Clone, Deserialize)] use crate::context::Ctx;
#[serde(rename_all = "camelCase")]
pub struct ReactDisplayNameOptions;
/// [plugin-transform-react-display-name](https://babeljs.io/docs/babel-plugin-transform-react-display-name) /// [plugin-transform-react-display-name](https://babeljs.io/docs/babel-plugin-transform-react-display-name)
/// ///
@ -12,14 +10,13 @@ pub struct ReactDisplayNameOptions;
/// ///
/// In: `var bar = createReactClass({});` /// In: `var bar = createReactClass({});`
/// Out: `var bar = createReactClass({ displayName: "bar" });` /// Out: `var bar = createReactClass({ displayName: "bar" });`
#[derive(Debug, Default)] #[allow(unused)]
pub struct ReactDisplayName { pub struct ReactDisplayName<'a> {
#[allow(unused)] ctx: Ctx<'a>,
options: ReactDisplayNameOptions,
} }
impl ReactDisplayName { impl<'a> ReactDisplayName<'a> {
pub fn new(options: ReactDisplayNameOptions) -> Self { pub fn new(ctx: &Ctx<'a>) -> Self {
Self { options } Self { ctx: Rc::clone(ctx) }
} }
} }

View file

@ -1,3 +1,7 @@
use std::rc::Rc;
use crate::context::Ctx;
pub use super::options::ReactOptions; pub use super::options::ReactOptions;
/// [plugin-transform-react-jsx](https://babeljs.io/docs/babel-plugin-transform-react-jsx) /// [plugin-transform-react-jsx](https://babeljs.io/docs/babel-plugin-transform-react-jsx)
@ -13,14 +17,14 @@ pub use super::options::ReactOptions;
/// ///
/// * <https://babeljs.io/docs/babel-plugin-transform-react-jsx> /// * <https://babeljs.io/docs/babel-plugin-transform-react-jsx>
/// * <https://github.com/babel/babel/tree/main/packages/babel-helper-builder-react-jsx> /// * <https://github.com/babel/babel/tree/main/packages/babel-helper-builder-react-jsx>
#[derive(Debug, Default)] #[allow(unused)]
pub struct ReactJsx { pub struct ReactJsx<'a> {
#[allow(unused)]
options: ReactOptions, options: ReactOptions,
ctx: Ctx<'a>,
} }
impl ReactJsx { impl<'a> ReactJsx<'a> {
pub fn new(options: ReactOptions) -> Self { pub fn new(options: ReactOptions, ctx: &Ctx<'a>) -> Self {
Self { options } Self { options, ctx: Rc::clone(ctx) }
} }
} }

View file

@ -1,8 +1,6 @@
use serde::Deserialize; use std::rc::Rc;
#[derive(Debug, Default, Clone, Deserialize)] use crate::context::Ctx;
#[serde(rename_all = "camelCase")]
pub struct ReactJsxSelfOptions;
/// [plugin-transform-react-jsx-self](https://babeljs.io/docs/babel-plugin-transform-react-jsx-self) /// [plugin-transform-react-jsx-self](https://babeljs.io/docs/babel-plugin-transform-react-jsx-self)
/// ///
@ -12,14 +10,13 @@ pub struct ReactJsxSelfOptions;
/// ///
/// In: `<sometag />` /// In: `<sometag />`
/// Out: `<sometag __self={this} />` /// Out: `<sometag __self={this} />`
#[derive(Debug, Default)] #[allow(unused)]
pub struct ReactJsxSelf { pub struct ReactJsxSelf<'a> {
#[allow(unused)] ctx: Ctx<'a>,
options: ReactJsxSelfOptions,
} }
impl ReactJsxSelf { impl<'a> ReactJsxSelf<'a> {
pub fn new(options: ReactJsxSelfOptions) -> Self { pub fn new(ctx: &Ctx<'a>) -> Self {
Self { options } Self { ctx: Rc::clone(ctx) }
} }
} }

View file

@ -1,18 +1,15 @@
use serde::Deserialize; use std::rc::Rc;
#[derive(Debug, Default, Clone, Deserialize)] use crate::context::Ctx;
#[serde(rename_all = "camelCase")]
pub struct ReactJsxSourceOptions;
/// [plugin-transform-react-jsx-source](https://babeljs.io/docs/babel-plugin-transform-react-jsx-source) /// [plugin-transform-react-jsx-source](https://babeljs.io/docs/babel-plugin-transform-react-jsx-source)
#[derive(Debug, Default)] #[allow(unused)]
pub struct ReactJsxSource { pub struct ReactJsxSource<'a> {
#[allow(unused)] ctx: Ctx<'a>,
options: ReactJsxSourceOptions,
} }
impl ReactJsxSource { impl<'a> ReactJsxSource<'a> {
pub fn new(options: ReactJsxSourceOptions) -> Self { pub fn new(ctx: &Ctx<'a>) -> Self {
Self { options } Self { ctx: Rc::clone(ctx) }
} }
} }

View file

@ -4,14 +4,15 @@ mod jsx_self;
mod jsx_source; mod jsx_source;
mod options; mod options;
use std::rc::Rc;
use oxc_ast::ast::*; use oxc_ast::ast::*;
use crate::context::Ctx;
pub use self::{ pub use self::{
display_name::{ReactDisplayName, ReactDisplayNameOptions}, display_name::ReactDisplayName, jsx::ReactJsx, jsx_self::ReactJsxSelf,
jsx::ReactJsx, jsx_source::ReactJsxSource, options::ReactOptions,
jsx_self::{ReactJsxSelf, ReactJsxSelfOptions},
jsx_source::{ReactJsxSource, ReactJsxSourceOptions},
options::ReactOptions,
}; };
/// [Preset React](https://babel.dev/docs/babel-preset-react) /// [Preset React](https://babel.dev/docs/babel-preset-react)
@ -22,40 +23,31 @@ pub use self::{
/// * [plugin-transform-react-jsx-self](https://babeljs.io/docs/babel-plugin-transform-react-jsx-self) /// * [plugin-transform-react-jsx-self](https://babeljs.io/docs/babel-plugin-transform-react-jsx-self)
/// * [plugin-transform-react-jsx](https://babeljs.io/docs/babel-plugin-transform-react-jsx) /// * [plugin-transform-react-jsx](https://babeljs.io/docs/babel-plugin-transform-react-jsx)
/// * [plugin-transform-react-display-name](https://babeljs.io/docs/babel-plugin-transform-react-display-name) /// * [plugin-transform-react-display-name](https://babeljs.io/docs/babel-plugin-transform-react-display-name)
#[derive(Default)] #[allow(unused)]
pub struct React { pub struct React<'a> {
jsx: ReactJsx, ctx: Ctx<'a>,
jsx_self: ReactJsxSelf, jsx: ReactJsx<'a>,
jsx_source: ReactJsxSource, jsx_self: ReactJsxSelf<'a>,
display_name: ReactDisplayName, jsx_source: ReactJsxSource<'a>,
display_name: ReactDisplayName<'a>,
} }
// Constructors // Constructors
impl React { impl<'a> React<'a> {
pub fn new(&mut self, options: ReactOptions) -> &mut Self { pub fn new(options: ReactOptions, ctx: &Ctx<'a>) -> Self {
self.jsx = ReactJsx::new(options); Self {
self ctx: Rc::clone(ctx),
} jsx: ReactJsx::new(options, ctx),
jsx_self: ReactJsxSelf::new(ctx),
pub fn with_jsx_self(&mut self, options: ReactJsxSelfOptions) -> &mut Self { jsx_source: ReactJsxSource::new(ctx),
self.jsx_self = ReactJsxSelf::new(options); display_name: ReactDisplayName::new(ctx),
self }
}
pub fn with_jsx_source(&mut self, options: ReactJsxSourceOptions) -> &mut Self {
self.jsx_source = ReactJsxSource::new(options);
self
}
pub fn with_display_name(&mut self, options: ReactDisplayNameOptions) -> &mut Self {
self.display_name = ReactDisplayName::new(options);
self
} }
} }
// Transformers // Transformers
impl React { impl<'a> React<'a> {
pub fn transform_expression(&mut self, expr: &mut Expression<'_>) { pub fn transform_expression(&mut self, expr: &mut Expression<'a>) {
match expr { match expr {
Expression::JSXElement(_e) => { Expression::JSXElement(_e) => {
// *expr = unimplemented!(); // *expr = unimplemented!();

View file

@ -1,7 +1,11 @@
use std::rc::Rc;
use serde::Deserialize; use serde::Deserialize;
use oxc_ast::ast::*; use oxc_ast::ast::*;
use crate::context::Ctx;
#[derive(Debug, Default, Clone, Deserialize)] #[derive(Debug, Default, Clone, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct TypeScriptOptions; pub struct TypeScriptOptions;
@ -27,19 +31,19 @@ pub struct TypeScriptOptions;
/// ///
/// In: `const x: number = 0;` /// In: `const x: number = 0;`
/// Out: `const x = 0;` /// Out: `const x = 0;`
#[derive(Debug, Default)] #[allow(unused)]
pub struct TypeScript { pub struct TypeScript<'a> {
#[allow(unused)]
options: TypeScriptOptions, options: TypeScriptOptions,
ctx: Ctx<'a>,
} }
impl TypeScript { impl<'a> TypeScript<'a> {
pub fn new(options: TypeScriptOptions) -> Self { pub fn new(options: TypeScriptOptions, ctx: &Ctx<'a>) -> Self {
Self { options } Self { options, ctx: Rc::clone(ctx) }
} }
} }
// Transformers // Transformers
impl TypeScript { impl<'a> TypeScript<'a> {
pub fn transform_statement(&mut self, _stmt: &mut Statement<'_>) {} pub fn transform_statement(&mut self, _stmt: &mut Statement<'a>) {}
} }