mirror of
https://github.com/danbulant/oxc
synced 2026-05-25 04:42:10 +00:00
feat(transformer): add "_jsxFileName" variable in jsx source plugin (#3000)
This commit is contained in:
parent
67045467c7
commit
85a3653994
11 changed files with 127 additions and 53 deletions
|
|
@ -1,11 +1,16 @@
|
||||||
use std::{cell::RefCell, mem, path::Path, rc::Rc};
|
use std::{
|
||||||
|
cell::RefCell,
|
||||||
|
mem,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
rc::Rc,
|
||||||
|
};
|
||||||
|
|
||||||
use oxc_allocator::Allocator;
|
use oxc_allocator::Allocator;
|
||||||
use oxc_ast::AstBuilder;
|
use oxc_ast::AstBuilder;
|
||||||
use oxc_diagnostics::Error;
|
use oxc_diagnostics::Error;
|
||||||
use oxc_semantic::Semantic;
|
use oxc_semantic::Semantic;
|
||||||
|
|
||||||
use crate::helpers::module_imports::ModuleImports;
|
use crate::{helpers::module_imports::ModuleImports, TransformOptions};
|
||||||
|
|
||||||
pub type Ctx<'a> = Rc<TransformCtx<'a>>;
|
pub type Ctx<'a> = Rc<TransformCtx<'a>>;
|
||||||
|
|
||||||
|
|
@ -17,6 +22,9 @@ pub struct TransformCtx<'a> {
|
||||||
/// <https://babeljs.io/docs/options#filename>
|
/// <https://babeljs.io/docs/options#filename>
|
||||||
filename: String,
|
filename: String,
|
||||||
|
|
||||||
|
/// Source path in the form of `<CWD>/path/to/file/input.js`
|
||||||
|
source_path: PathBuf,
|
||||||
|
|
||||||
errors: RefCell<Vec<Error>>,
|
errors: RefCell<Vec<Error>>,
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
|
|
@ -25,14 +33,28 @@ pub struct TransformCtx<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> TransformCtx<'a> {
|
impl<'a> TransformCtx<'a> {
|
||||||
pub fn new(allocator: &'a Allocator, source_path: &Path, semantic: Semantic<'a>) -> Self {
|
pub fn new(
|
||||||
let ast = AstBuilder::new(allocator);
|
allocator: &'a Allocator,
|
||||||
|
source_path: &Path,
|
||||||
|
semantic: Semantic<'a>,
|
||||||
|
options: &TransformOptions,
|
||||||
|
) -> Self {
|
||||||
let filename = source_path
|
let filename = source_path
|
||||||
.file_stem() // omit file extension
|
.file_stem() // omit file extension
|
||||||
.map_or_else(|| String::from("unknown"), |name| name.to_string_lossy().to_string());
|
.map_or_else(|| String::from("unknown"), |name| name.to_string_lossy().to_string());
|
||||||
let errors = RefCell::new(vec![]);
|
|
||||||
let module_imports = ModuleImports::new(allocator);
|
let source_path = source_path
|
||||||
Self { ast, semantic, filename, errors, module_imports }
|
.strip_prefix(&options.cwd)
|
||||||
|
.map_or_else(|_| source_path.to_path_buf(), |p| Path::new("<CWD>").join(p));
|
||||||
|
|
||||||
|
Self {
|
||||||
|
ast: AstBuilder::new(allocator),
|
||||||
|
semantic,
|
||||||
|
filename,
|
||||||
|
source_path,
|
||||||
|
errors: RefCell::new(vec![]),
|
||||||
|
module_imports: ModuleImports::new(allocator),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn take_errors(&self) -> Vec<Error> {
|
pub fn take_errors(&self) -> Vec<Error> {
|
||||||
|
|
@ -43,6 +65,10 @@ impl<'a> TransformCtx<'a> {
|
||||||
&self.filename
|
&self.filename
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn source_path(&self) -> &Path {
|
||||||
|
&self.source_path
|
||||||
|
}
|
||||||
|
|
||||||
/// Add an Error
|
/// Add an Error
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn error<T: Into<Error>>(&self, error: T) {
|
pub fn error<T: Into<Error>>(&self, error: T) {
|
||||||
|
|
|
||||||
|
|
@ -129,8 +129,7 @@ impl<'a> ModuleImports<'a> {
|
||||||
let decl = self.ast.variable_declarator(SPAN, var_kind, id, Some(init), false);
|
let decl = self.ast.variable_declarator(SPAN, var_kind, id, Some(init), false);
|
||||||
self.ast.new_vec_single(decl)
|
self.ast.new_vec_single(decl)
|
||||||
};
|
};
|
||||||
let variable_declaration =
|
let var_decl = self.ast.variable_declaration(SPAN, var_kind, decl, Modifiers::empty());
|
||||||
self.ast.variable_declaration(SPAN, var_kind, decl, Modifiers::empty());
|
Statement::Declaration(Declaration::VariableDeclaration(var_decl))
|
||||||
Statement::Declaration(Declaration::VariableDeclaration(variable_declaration))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ impl<'a> Transformer<'a> {
|
||||||
semantic: Semantic<'a>,
|
semantic: Semantic<'a>,
|
||||||
options: TransformOptions,
|
options: TransformOptions,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let ctx = Rc::new(TransformCtx::new(allocator, source_path, semantic));
|
let ctx = Rc::new(TransformCtx::new(allocator, source_path, semantic, &options));
|
||||||
Self {
|
Self {
|
||||||
ctx: Rc::clone(&ctx),
|
ctx: Rc::clone(&ctx),
|
||||||
x0_typescript: TypeScript::new(options.typescript, &ctx),
|
x0_typescript: TypeScript::new(options.typescript, &ctx),
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,18 @@
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
compiler_assumptions::CompilerAssumptions, react::ReactOptions, typescript::TypeScriptOptions,
|
compiler_assumptions::CompilerAssumptions, react::ReactOptions, typescript::TypeScriptOptions,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <https://babel.dev/docs/options>
|
||||||
#[derive(Debug, Default, Clone)]
|
#[derive(Debug, Default, Clone)]
|
||||||
pub struct TransformOptions {
|
pub struct TransformOptions {
|
||||||
|
//
|
||||||
|
// Primary Options
|
||||||
|
//
|
||||||
|
/// The working directory that all paths in the programmatic options will be resolved relative to.
|
||||||
|
pub cwd: PathBuf,
|
||||||
|
|
||||||
// Core
|
// Core
|
||||||
/// Set assumptions in order to produce smaller output.
|
/// Set assumptions in order to produce smaller output.
|
||||||
/// For more information, check the [assumptions](https://babel.dev/docs/assumptions) documentation page.
|
/// For more information, check the [assumptions](https://babel.dev/docs/assumptions) documentation page.
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,8 @@ pub struct ReactJsx<'a> {
|
||||||
|
|
||||||
ctx: Ctx<'a>,
|
ctx: Ctx<'a>,
|
||||||
|
|
||||||
jsx_self: ReactJsxSelf<'a>,
|
pub(super) jsx_self: ReactJsxSelf<'a>,
|
||||||
jsx_source: ReactJsxSource<'a>,
|
pub(super) jsx_source: ReactJsxSource<'a>,
|
||||||
|
|
||||||
// States
|
// States
|
||||||
require_jsx_runtime: bool,
|
require_jsx_runtime: bool,
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use oxc_syntax::NumberBase;
|
||||||
use crate::context::Ctx;
|
use crate::context::Ctx;
|
||||||
|
|
||||||
const SOURCE: &str = "__source";
|
const SOURCE: &str = "__source";
|
||||||
|
const FILE_NAME_VAR: &str = "_jsxFileName";
|
||||||
|
|
||||||
/// [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)
|
||||||
///
|
///
|
||||||
|
|
@ -20,18 +21,31 @@ const SOURCE: &str = "__source";
|
||||||
/// TODO: get lineNumber and columnNumber from somewhere
|
/// TODO: get lineNumber and columnNumber from somewhere
|
||||||
pub struct ReactJsxSource<'a> {
|
pub struct ReactJsxSource<'a> {
|
||||||
ctx: Ctx<'a>,
|
ctx: Ctx<'a>,
|
||||||
|
|
||||||
|
/// Has `var _jsxFileName = "";` been added to program.statements?
|
||||||
|
should_add_jsx_file_name_variable: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ReactJsxSource<'a> {
|
impl<'a> ReactJsxSource<'a> {
|
||||||
pub fn new(ctx: &Ctx<'a>) -> Self {
|
pub fn new(ctx: &Ctx<'a>) -> Self {
|
||||||
Self { ctx: Rc::clone(ctx) }
|
Self { ctx: Rc::clone(ctx), should_add_jsx_file_name_variable: false }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn transform_jsx_opening_element(&self, elem: &mut JSXOpeningElement<'a>) {
|
pub fn transform_program_on_exit(&mut self, program: &mut Program<'a>) {
|
||||||
|
if !self.should_add_jsx_file_name_variable {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let statement = self.get_var_file_name_statement();
|
||||||
|
program.body.insert(0, statement);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn transform_jsx_opening_element(&mut self, elem: &mut JSXOpeningElement<'a>) {
|
||||||
|
self.should_add_jsx_file_name_variable = true;
|
||||||
self.add_source_attribute(elem);
|
self.add_source_attribute(elem);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_object_property_kind_for_jsx_plugin(&self) -> ObjectPropertyKind<'a> {
|
pub fn get_object_property_kind_for_jsx_plugin(&mut self) -> ObjectPropertyKind<'a> {
|
||||||
|
self.should_add_jsx_file_name_variable = true;
|
||||||
let kind = PropertyKind::Init;
|
let kind = PropertyKind::Init;
|
||||||
let ident = IdentifierName::new(SPAN, SOURCE.into());
|
let ident = IdentifierName::new(SPAN, SOURCE.into());
|
||||||
let key = self.ctx.ast.property_key_identifier(ident);
|
let key = self.ctx.ast.property_key_identifier(ident);
|
||||||
|
|
@ -59,8 +73,8 @@ impl<'a> ReactJsxSource<'a> {
|
||||||
let filename = {
|
let filename = {
|
||||||
let name = IdentifierName::new(SPAN, "fileName".into());
|
let name = IdentifierName::new(SPAN, "fileName".into());
|
||||||
let key = self.ctx.ast.property_key_identifier(name);
|
let key = self.ctx.ast.property_key_identifier(name);
|
||||||
let string = StringLiteral::new(SPAN, self.ctx.ast.new_atom(self.ctx.filename()));
|
let ident = self.ctx.ast.identifier_reference(SPAN, FILE_NAME_VAR);
|
||||||
let value = self.ctx.ast.literal_string_expression(string);
|
let value = self.ctx.ast.identifier_reference_expression(ident);
|
||||||
self.ctx.ast.object_property(SPAN, kind, key, value, None, false, false, false)
|
self.ctx.ast.object_property(SPAN, kind, key, value, None, false, false, false)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -86,4 +100,22 @@ impl<'a> ReactJsxSource<'a> {
|
||||||
properties.push(ObjectPropertyKind::ObjectProperty(column_number));
|
properties.push(ObjectPropertyKind::ObjectProperty(column_number));
|
||||||
self.ctx.ast.object_expression(SPAN, properties, None)
|
self.ctx.ast.object_expression(SPAN, properties, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_var_file_name_statement(&self) -> Statement<'a> {
|
||||||
|
let var_kind = VariableDeclarationKind::Var;
|
||||||
|
let id = {
|
||||||
|
let ident = BindingIdentifier::new(SPAN, FILE_NAME_VAR.into());
|
||||||
|
let ident = self.ctx.ast.binding_pattern_identifier(ident);
|
||||||
|
self.ctx.ast.binding_pattern(ident, None, false)
|
||||||
|
};
|
||||||
|
let decl = {
|
||||||
|
let string =
|
||||||
|
self.ctx.ast.string_literal(SPAN, &self.ctx.source_path().to_string_lossy());
|
||||||
|
let init = self.ctx.ast.literal_string_expression(string);
|
||||||
|
let decl = self.ctx.ast.variable_declarator(SPAN, var_kind, id, Some(init), false);
|
||||||
|
self.ctx.ast.new_vec_single(decl)
|
||||||
|
};
|
||||||
|
let var_decl = self.ctx.ast.variable_declaration(SPAN, var_kind, decl, Modifiers::empty());
|
||||||
|
Statement::Declaration(Declaration::VariableDeclaration(var_decl))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,10 +10,7 @@ use oxc_ast::ast::*;
|
||||||
|
|
||||||
use crate::context::Ctx;
|
use crate::context::Ctx;
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{display_name::ReactDisplayName, jsx::ReactJsx, options::ReactOptions};
|
||||||
display_name::ReactDisplayName, jsx::ReactJsx, jsx_self::ReactJsxSelf,
|
|
||||||
jsx_source::ReactJsxSource, options::ReactOptions,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// [Preset React](https://babel.dev/docs/babel-preset-react)
|
/// [Preset React](https://babel.dev/docs/babel-preset-react)
|
||||||
///
|
///
|
||||||
|
|
@ -26,8 +23,6 @@ pub use self::{
|
||||||
pub struct React<'a> {
|
pub struct React<'a> {
|
||||||
options: Rc<ReactOptions>,
|
options: Rc<ReactOptions>,
|
||||||
jsx: ReactJsx<'a>,
|
jsx: ReactJsx<'a>,
|
||||||
jsx_self: ReactJsxSelf<'a>,
|
|
||||||
jsx_source: ReactJsxSource<'a>,
|
|
||||||
display_name: ReactDisplayName<'a>,
|
display_name: ReactDisplayName<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -42,8 +37,6 @@ impl<'a> React<'a> {
|
||||||
Self {
|
Self {
|
||||||
options: Rc::clone(&options),
|
options: Rc::clone(&options),
|
||||||
jsx: ReactJsx::new(&options, ctx),
|
jsx: ReactJsx::new(&options, ctx),
|
||||||
jsx_self: ReactJsxSelf::new(ctx),
|
|
||||||
jsx_source: ReactJsxSource::new(ctx),
|
|
||||||
display_name: ReactDisplayName::new(ctx),
|
display_name: ReactDisplayName::new(ctx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -52,9 +45,14 @@ impl<'a> React<'a> {
|
||||||
// Transforms
|
// Transforms
|
||||||
impl<'a> React<'a> {
|
impl<'a> React<'a> {
|
||||||
pub fn transform_program_on_exit(&mut self, program: &mut Program<'a>) {
|
pub fn transform_program_on_exit(&mut self, program: &mut Program<'a>) {
|
||||||
|
// TODO: PERF: These two transforms reallocathe program.statements,
|
||||||
|
// they should be combined so that allocation is computed only once for program.statements.
|
||||||
if self.options.jsx_plugin {
|
if self.options.jsx_plugin {
|
||||||
self.jsx.transform_program_on_exit(program);
|
self.jsx.transform_program_on_exit(program);
|
||||||
}
|
}
|
||||||
|
if self.options.is_jsx_source_plugin_enabled() {
|
||||||
|
self.jsx.jsx_source.transform_program_on_exit(program);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn transform_expression(&mut self, expr: &mut Expression<'a>) {
|
pub fn transform_expression(&mut self, expr: &mut Expression<'a>) {
|
||||||
|
|
@ -96,12 +94,12 @@ impl<'a> React<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn transform_jsx_opening_element(&self, elem: &mut JSXOpeningElement<'a>) {
|
pub fn transform_jsx_opening_element(&mut self, elem: &mut JSXOpeningElement<'a>) {
|
||||||
if self.options.is_jsx_self_plugin_enabled() {
|
if self.options.is_jsx_self_plugin_enabled() {
|
||||||
self.jsx_self.transform_jsx_opening_element(elem);
|
self.jsx.jsx_self.transform_jsx_opening_element(elem);
|
||||||
}
|
}
|
||||||
if self.options.is_jsx_source_plugin_enabled() {
|
if self.options.is_jsx_source_plugin_enabled() {
|
||||||
self.jsx_source.transform_jsx_opening_element(elem);
|
self.jsx.jsx_source.transform_jsx_opening_element(elem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use std::path::Path;
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
@ -7,6 +7,7 @@ use serde_json::Value;
|
||||||
#[derive(Debug, Default, Clone, Deserialize)]
|
#[derive(Debug, Default, Clone, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct BabelOptions {
|
pub struct BabelOptions {
|
||||||
|
pub cwd: Option<PathBuf>,
|
||||||
#[serde(rename = "BABEL_8_BREAKING")]
|
#[serde(rename = "BABEL_8_BREAKING")]
|
||||||
pub babel_8_breaking: Option<bool>,
|
pub babel_8_breaking: Option<bool>,
|
||||||
pub source_type: Option<String>,
|
pub source_type: Option<String>,
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
Passed: 133/219
|
Passed: 134/219
|
||||||
|
|
||||||
# All Passed:
|
# All Passed:
|
||||||
* babel-plugin-transform-react-jsx-source
|
* babel-plugin-transform-react-jsx-source
|
||||||
|
|
@ -85,8 +85,7 @@ Passed: 133/219
|
||||||
* regression/15768/input.ts
|
* regression/15768/input.ts
|
||||||
* variable-declaration/non-null-in-optional-chain/input.ts
|
* variable-declaration/non-null-in-optional-chain/input.ts
|
||||||
|
|
||||||
# babel-preset-react (7/11)
|
# babel-preset-react (8/11)
|
||||||
* preset-options/development/input.js
|
|
||||||
* preset-options/development-runtime-automatic/input.js
|
* preset-options/development-runtime-automatic/input.js
|
||||||
* preset-options/development-runtime-automatic-windows/input.js
|
* preset-options/development-runtime-automatic-windows/input.js
|
||||||
* preset-options/development-windows/input.js
|
* preset-options/development-windows/input.js
|
||||||
|
|
|
||||||
|
|
@ -28,18 +28,22 @@ pub struct TestRunner {
|
||||||
options: TestRunnerOptions,
|
options: TestRunnerOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn root() -> PathBuf {
|
fn babel_root() -> PathBuf {
|
||||||
project_root().join("tasks/coverage/babel/packages")
|
project_root().join("tasks").join("coverage").join("babel")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn oxc_test_root() -> PathBuf {
|
fn packages_root() -> PathBuf {
|
||||||
project_root().join("tasks/transform_conformance/tests")
|
babel_root().join("packages")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn snap_root() -> PathBuf {
|
fn snap_root() -> PathBuf {
|
||||||
project_root().join("tasks/transform_conformance")
|
project_root().join("tasks/transform_conformance")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn oxc_test_root() -> PathBuf {
|
||||||
|
snap_root().join("tests")
|
||||||
|
}
|
||||||
|
|
||||||
fn fixture_root() -> PathBuf {
|
fn fixture_root() -> PathBuf {
|
||||||
snap_root().join("fixtures")
|
snap_root().join("fixtures")
|
||||||
}
|
}
|
||||||
|
|
@ -138,7 +142,7 @@ impl TestRunner {
|
||||||
/// # Panics
|
/// # Panics
|
||||||
pub fn run(self) {
|
pub fn run(self) {
|
||||||
for (root, snapshot, exec_snapshot) in &[
|
for (root, snapshot, exec_snapshot) in &[
|
||||||
(root(), CONFORMANCE_SNAPSHOT, EXEC_SNAPSHOT),
|
(packages_root(), CONFORMANCE_SNAPSHOT, EXEC_SNAPSHOT),
|
||||||
(oxc_test_root(), OXC_CONFORMANCE_SNAPSHOT, OXC_EXEC_SNAPSHOT),
|
(oxc_test_root(), OXC_CONFORMANCE_SNAPSHOT, OXC_EXEC_SNAPSHOT),
|
||||||
] {
|
] {
|
||||||
let (transform_paths, exec_files) =
|
let (transform_paths, exec_files) =
|
||||||
|
|
@ -160,6 +164,7 @@ impl TestRunner {
|
||||||
root: &Path,
|
root: &Path,
|
||||||
filter: Option<&String>,
|
filter: Option<&String>,
|
||||||
) -> (IndexMap<String, Vec<TestCaseKind>>, IndexMap<String, Vec<TestCaseKind>>) {
|
) -> (IndexMap<String, Vec<TestCaseKind>>, IndexMap<String, Vec<TestCaseKind>>) {
|
||||||
|
let cwd = babel_root();
|
||||||
// use `IndexMap` to keep the order of the test cases the same in insert order.
|
// use `IndexMap` to keep the order of the test cases the same in insert order.
|
||||||
let mut transform_files = IndexMap::<String, Vec<TestCaseKind>>::new();
|
let mut transform_files = IndexMap::<String, Vec<TestCaseKind>>::new();
|
||||||
let mut exec_files = IndexMap::<String, Vec<TestCaseKind>>::new();
|
let mut exec_files = IndexMap::<String, Vec<TestCaseKind>>::new();
|
||||||
|
|
@ -180,7 +185,8 @@ impl TestRunner {
|
||||||
if EXCLUDE_TESTS.iter().any(|p| path.to_string_lossy().contains(p)) {
|
if EXCLUDE_TESTS.iter().any(|p| path.to_string_lossy().contains(p)) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
TestCaseKind::new(path).filter(|test_case| !test_case.skip_test_case())
|
TestCaseKind::new(&cwd, path)
|
||||||
|
.filter(|test_case| !test_case.skip_test_case())
|
||||||
})
|
})
|
||||||
.partition(|p| matches!(p, TestCaseKind::Transform(_)));
|
.partition(|p| matches!(p, TestCaseKind::Transform(_)));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ use oxc_span::{SourceType, VALID_EXTENSIONS};
|
||||||
use oxc_tasks_common::{normalize_path, print_diff_in_terminal, BabelOptions};
|
use oxc_tasks_common::{normalize_path, print_diff_in_terminal, BabelOptions};
|
||||||
use oxc_transformer::{ReactOptions, TransformOptions, Transformer, TypeScriptOptions};
|
use oxc_transformer::{ReactOptions, TransformOptions, Transformer, TypeScriptOptions};
|
||||||
|
|
||||||
use crate::{fixture_root, root, TestRunnerEnv, PLUGINS_NOT_SUPPORTED_YET};
|
use crate::{fixture_root, packages_root, TestRunnerEnv, PLUGINS_NOT_SUPPORTED_YET};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum TestCaseKind {
|
pub enum TestCaseKind {
|
||||||
|
|
@ -24,25 +24,25 @@ pub enum TestCaseKind {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestCaseKind {
|
impl TestCaseKind {
|
||||||
pub fn new(path: &Path) -> Option<Self> {
|
pub fn new(cwd: &Path, path: &Path) -> Option<Self> {
|
||||||
// in `exec` directory
|
// in `exec` directory
|
||||||
if path.parent().is_some_and(|path| path.file_name().is_some_and(|n| n == "exec"))
|
if path.parent().is_some_and(|path| path.file_name().is_some_and(|n| n == "exec"))
|
||||||
&& path.extension().is_some_and(|ext| VALID_EXTENSIONS.contains(&ext.to_str().unwrap()))
|
&& path.extension().is_some_and(|ext| VALID_EXTENSIONS.contains(&ext.to_str().unwrap()))
|
||||||
{
|
{
|
||||||
return Some(Self::Exec(ExecTestCase::new(path)));
|
return Some(Self::Exec(ExecTestCase::new(cwd, path)));
|
||||||
}
|
}
|
||||||
// named `exec.[ext]`
|
// named `exec.[ext]`
|
||||||
if path.file_stem().is_some_and(|name| name == "exec")
|
if path.file_stem().is_some_and(|name| name == "exec")
|
||||||
&& path.extension().is_some_and(|ext| VALID_EXTENSIONS.contains(&ext.to_str().unwrap()))
|
&& path.extension().is_some_and(|ext| VALID_EXTENSIONS.contains(&ext.to_str().unwrap()))
|
||||||
{
|
{
|
||||||
return Some(Self::Exec(ExecTestCase::new(path)));
|
return Some(Self::Exec(ExecTestCase::new(cwd, path)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// named `input.[ext]``
|
// named `input.[ext]``
|
||||||
if path.file_stem().is_some_and(|name| name == "input")
|
if path.file_stem().is_some_and(|name| name == "input")
|
||||||
&& path.extension().is_some_and(|ext| VALID_EXTENSIONS.contains(&ext.to_str().unwrap()))
|
&& path.extension().is_some_and(|ext| VALID_EXTENSIONS.contains(&ext.to_str().unwrap()))
|
||||||
{
|
{
|
||||||
return Some(Self::Transform(ConformanceTestCase::new(path)));
|
return Some(Self::Transform(ConformanceTestCase::new(cwd, path)));
|
||||||
}
|
}
|
||||||
|
|
||||||
None
|
None
|
||||||
|
|
@ -95,6 +95,7 @@ fn transform_options(options: &BabelOptions) -> serde_json::Result<TransformOpti
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(TransformOptions {
|
Ok(TransformOptions {
|
||||||
|
cwd: options.cwd.clone().unwrap(),
|
||||||
assumptions: serde_json::from_value(options.assumptions.clone()).unwrap_or_default(),
|
assumptions: serde_json::from_value(options.assumptions.clone()).unwrap_or_default(),
|
||||||
typescript: options
|
typescript: options
|
||||||
.get_plugin("transform-typescript")
|
.get_plugin("transform-typescript")
|
||||||
|
|
@ -106,7 +107,7 @@ fn transform_options(options: &BabelOptions) -> serde_json::Result<TransformOpti
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait TestCase {
|
pub trait TestCase {
|
||||||
fn new(path: &Path) -> Self;
|
fn new(cwd: &Path, path: &Path) -> Self;
|
||||||
|
|
||||||
fn options(&self) -> &BabelOptions;
|
fn options(&self) -> &BabelOptions;
|
||||||
|
|
||||||
|
|
@ -213,8 +214,9 @@ pub struct ConformanceTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestCase for ConformanceTestCase {
|
impl TestCase for ConformanceTestCase {
|
||||||
fn new(path: &Path) -> Self {
|
fn new(cwd: &Path, path: &Path) -> Self {
|
||||||
let options = BabelOptions::from_path(path.parent().unwrap());
|
let mut options = BabelOptions::from_path(path.parent().unwrap());
|
||||||
|
options.cwd.replace(cwd.to_path_buf());
|
||||||
let transform_options = transform_options(&options);
|
let transform_options = transform_options(&options);
|
||||||
Self { path: path.to_path_buf(), options, transform_options }
|
Self { path: path.to_path_buf(), options, transform_options }
|
||||||
}
|
}
|
||||||
|
|
@ -361,10 +363,11 @@ impl ExecTestCase {
|
||||||
|
|
||||||
fn write_to_test_files(&self, content: &str) -> PathBuf {
|
fn write_to_test_files(&self, content: &str) -> PathBuf {
|
||||||
let allocator = Allocator::default();
|
let allocator = Allocator::default();
|
||||||
let new_file_name: String = normalize_path(self.path.strip_prefix(&root()).unwrap())
|
let new_file_name: String =
|
||||||
.split('/')
|
normalize_path(self.path.strip_prefix(&packages_root()).unwrap())
|
||||||
.collect::<Vec<&str>>()
|
.split('/')
|
||||||
.join("-");
|
.collect::<Vec<&str>>()
|
||||||
|
.join("-");
|
||||||
|
|
||||||
let mut target_path = fixture_root().join(new_file_name);
|
let mut target_path = fixture_root().join(new_file_name);
|
||||||
target_path.set_extension("test.js");
|
target_path.set_extension("test.js");
|
||||||
|
|
@ -385,8 +388,9 @@ impl ExecTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TestCase for ExecTestCase {
|
impl TestCase for ExecTestCase {
|
||||||
fn new(path: &Path) -> Self {
|
fn new(cwd: &Path, path: &Path) -> Self {
|
||||||
let options = BabelOptions::from_path(path.parent().unwrap());
|
let mut options = BabelOptions::from_path(path.parent().unwrap());
|
||||||
|
options.cwd.replace(cwd.to_path_buf());
|
||||||
let transform_options = transform_options(&options);
|
let transform_options = transform_options(&options);
|
||||||
Self { path: path.to_path_buf(), options, transform_options }
|
Self { path: path.to_path_buf(), options, transform_options }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue