refactor(transformer)!: return String as error instead of OxcDiagnostic (#7424)

This commit is contained in:
Boshen 2024-11-22 16:22:49 +00:00
parent e88cf1bfd6
commit bb2c0c219b
9 changed files with 42 additions and 45 deletions

View file

@ -89,9 +89,11 @@ pub struct TransformOptions {
pub inject: Option<FxHashMap<String, Either<String, Vec<String>>>>, pub inject: Option<FxHashMap<String, Either<String, Vec<String>>>>,
} }
impl From<TransformOptions> for oxc_transformer::TransformOptions { impl TryFrom<TransformOptions> for oxc_transformer::TransformOptions {
fn from(options: TransformOptions) -> Self { type Error = String;
Self {
fn try_from(options: TransformOptions) -> Result<Self, Self::Error> {
Ok(Self {
cwd: options.cwd.map(PathBuf::from).unwrap_or_default(), cwd: options.cwd.map(PathBuf::from).unwrap_or_default(),
typescript: options typescript: options
.typescript .typescript
@ -99,7 +101,7 @@ impl From<TransformOptions> for oxc_transformer::TransformOptions {
.unwrap_or_default(), .unwrap_or_default(),
jsx: options.jsx.map(Into::into).unwrap_or_default(), jsx: options.jsx.map(Into::into).unwrap_or_default(),
..Self::default() ..Self::default()
} })
} }
} }

View file

@ -3,8 +3,6 @@ use std::str::FromStr;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use serde::Deserialize; use serde::Deserialize;
use oxc_diagnostics::Error;
pub use browserslist::Version; pub use browserslist::Version;
use crate::options::{BrowserslistQuery, Engine, EngineTargets}; use crate::options::{BrowserslistQuery, Engine, EngineTargets};
@ -35,7 +33,7 @@ pub enum BabelTargetsValue {
} }
impl TryFrom<BabelTargets> for EngineTargets { impl TryFrom<BabelTargets> for EngineTargets {
type Error = Error; type Error = String;
fn try_from(value: BabelTargets) -> Result<Self, Self::Error> { fn try_from(value: BabelTargets) -> Result<Self, Self::Error> {
match value { match value {
BabelTargets::String(s) => BrowserslistQuery::Single(s).exec(), BabelTargets::String(s) => BrowserslistQuery::Single(s).exec(),
@ -52,7 +50,7 @@ impl TryFrom<BabelTargets> for EngineTargets {
continue; continue;
}; };
let BabelTargetsValue::String(v) = value else { let BabelTargetsValue::String(v) = value else {
return Err(Error::msg(format!("{value:?} is not a string for {key}."))); return Err(format!("{value:?} is not a string for {key}."));
}; };
// TODO: Implement this target. // TODO: Implement this target.
if key == "node" && v == "current" { if key == "node" && v == "current" {
@ -66,16 +64,14 @@ impl TryFrom<BabelTargets> for EngineTargets {
// <https://babel.dev/docs/options#targets>: // <https://babel.dev/docs/options#targets>:
// Supported environments: android, chrome, deno, edge, electron, firefox, ie, ios, node, opera, rhino, safari, samsung. // Supported environments: android, chrome, deno, edge, electron, firefox, ie, ios, node, opera, rhino, safari, samsung.
let Ok(engine) = Engine::from_str(&key) else { let Ok(engine) = Engine::from_str(&key) else {
return Err(Error::msg(format!("engine '{key}' is not supported."))); return Err(format!("engine '{key}' is not supported."));
}; };
match Version::parse(&v) { match Version::parse(&v) {
Ok(version) => { Ok(version) => {
engine_targets.insert(engine, version); engine_targets.insert(engine, version);
} }
Err(err) => { Err(err) => {
return Err(oxc_diagnostics::Error::msg(format!( return Err(format!("Failed to parse `{v}` for `{key}`\n{err:?}"))
"Failed to parse `{v}` for `{key}`\n{err:?}"
)))
} }
} }
} }

View file

@ -3,8 +3,6 @@ use std::sync::OnceLock;
use dashmap::DashMap; use dashmap::DashMap;
use serde::Deserialize; use serde::Deserialize;
use oxc_diagnostics::{Error, OxcDiagnostic};
use super::EngineTargets; use super::EngineTargets;
#[derive(Debug, Clone, Deserialize, Eq, PartialEq, PartialOrd, Ord, Hash)] #[derive(Debug, Clone, Deserialize, Eq, PartialEq, PartialOrd, Ord, Hash)]
@ -20,7 +18,7 @@ fn cache() -> &'static DashMap<BrowserslistQuery, EngineTargets> {
} }
impl BrowserslistQuery { impl BrowserslistQuery {
pub fn exec(&self) -> Result<EngineTargets, Error> { pub fn exec(&self) -> Result<EngineTargets, String> {
if let Some(v) = cache().get(self) { if let Some(v) = cache().get(self) {
return Ok(v.clone()); return Ok(v.clone());
} }
@ -50,9 +48,7 @@ impl BrowserslistQuery {
.collect::<Vec<_>>(); .collect::<Vec<_>>();
EngineTargets::parse_versions(versions) EngineTargets::parse_versions(versions)
} }
Err(err) => { Err(err) => return Err(format!("failed to resolve query: {err}")),
return Err(OxcDiagnostic::error(format!("failed to resolve query: {err}")).into())
}
}; };
cache().insert(self.clone(), result.clone()); cache().insert(self.clone(), result.clone());

View file

@ -2,7 +2,6 @@ use std::{str::FromStr, sync::OnceLock};
use browserslist::Version; use browserslist::Version;
use cow_utils::CowUtils; use cow_utils::CowUtils;
use oxc_diagnostics::Error;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use serde::Deserialize; use serde::Deserialize;
@ -38,17 +37,17 @@ impl Engine {
/// ///
/// * No matching target /// * No matching target
/// * Invalid version /// * Invalid version
pub fn parse_name_and_version(s: &str) -> Result<(Engine, Version), Error> { pub fn parse_name_and_version(s: &str) -> Result<(Engine, Version), String> {
let s = s.cow_to_ascii_lowercase(); let s = s.cow_to_ascii_lowercase();
for (name, engine) in engines() { for (name, engine) in engines() {
if let Some(v) = s.strip_prefix(name) { if let Some(v) = s.strip_prefix(name) {
return Version::from_str(v).map(|version| (*engine,version)) return Version::from_str(v).map(|version| (*engine,version))
.map_err(|_| Error::msg( .map_err(|_|
r#"All version numbers must be in the format "X", "X.Y", or "X.Y.Z" where X, Y, and Z are non-negative integers."#, String::from(r#"All version numbers must be in the format "X", "X.Y", or "X.Y.Z" where X, Y, and Z are non-negative integers."#),
)); );
} }
} }
Err(Error::msg(format!("Invalid target '{s}'."))) Err(format!("Invalid target '{s}'."))
} }
} }

View file

@ -8,8 +8,6 @@ use browserslist::Version;
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use serde::Deserialize; use serde::Deserialize;
use oxc_diagnostics::Error;
use super::{ use super::{
babel::BabelTargets, babel::BabelTargets,
engine::Engine, engine::Engine,
@ -42,7 +40,7 @@ impl EngineTargets {
/// # Errors /// # Errors
/// ///
/// * Query is invalid. /// * Query is invalid.
pub fn try_from_query(query: &str) -> Result<Self, Error> { pub fn try_from_query(query: &str) -> Result<Self, String> {
BrowserslistQuery::Single(query.to_string()).exec() BrowserslistQuery::Single(query.to_string()).exec()
} }

View file

@ -1,6 +1,5 @@
use std::str::FromStr; use std::str::FromStr;
use oxc_diagnostics::Error;
use serde::Deserialize; use serde::Deserialize;
use crate::{ use crate::{
@ -101,11 +100,14 @@ impl EnvOptions {
/// * When the query failed to parse. /// * When the query failed to parse.
/// ///
/// [browserslist]: <https://github.com/browserslist/browserslist> /// [browserslist]: <https://github.com/browserslist/browserslist>
pub fn from_browserslist_query(query: &str) -> Result<Self, Error> { pub fn from_browserslist_query(query: &str) -> Result<Self, String> {
EngineTargets::try_from_query(query).map(Self::from) EngineTargets::try_from_query(query).map(Self::from)
} }
pub(crate) fn from_target(s: &str) -> Result<Self, Error> { /// # Errors
///
/// * When the query failed to parse.
pub fn from_target(s: &str) -> Result<Self, String> {
if s.contains(',') { if s.contains(',') {
Self::from_target_list(&s.split(',').collect::<Vec<_>>()) Self::from_target_list(&s.split(',').collect::<Vec<_>>())
} else { } else {
@ -113,7 +115,10 @@ impl EnvOptions {
} }
} }
pub(crate) fn from_target_list<S: AsRef<str>>(list: &[S]) -> Result<Self, Error> { /// # Errors
///
/// * When the query failed to parse.
pub fn from_target_list<S: AsRef<str>>(list: &[S]) -> Result<Self, String> {
let mut es_target = None; let mut es_target = None;
let mut engine_targets = EngineTargets::default(); let mut engine_targets = EngineTargets::default();
@ -122,14 +127,14 @@ impl EnvOptions {
// Parse `esXXXX`. // Parse `esXXXX`.
if let Ok(target) = ESTarget::from_str(s) { if let Ok(target) = ESTarget::from_str(s) {
if let Some(target) = es_target { if let Some(target) = es_target {
return Err(Error::msg(format!("'{target}' is already specified."))); return Err(format!("'{target}' is already specified."));
} }
es_target = Some(target); es_target = Some(target);
} else { } else {
// Parse `chromeXX`, `edgeXX` etc. // Parse `chromeXX`, `edgeXX` etc.
let (engine, version) = Engine::parse_name_and_version(s)?; let (engine, version) = Engine::parse_name_and_version(s)?;
if engine_targets.insert(engine, version).is_some() { if engine_targets.insert(engine, version).is_some() {
return Err(Error::msg(format!("'{s}' is already specified."))); return Err(format!("'{s}' is already specified."));
} }
} }
} }

View file

@ -10,8 +10,6 @@ mod module;
use std::path::PathBuf; use std::path::PathBuf;
use oxc_diagnostics::Error;
use crate::{ use crate::{
common::helper_loader::{HelperLoaderMode, HelperLoaderOptions}, common::helper_loader::{HelperLoaderMode, HelperLoaderOptions},
compiler_assumptions::CompilerAssumptions, compiler_assumptions::CompilerAssumptions,
@ -97,7 +95,7 @@ impl TransformOptions {
/// * Same targets specified multiple times. /// * Same targets specified multiple times.
/// * No matching target. /// * No matching target.
/// * Invalid version. /// * Invalid version.
pub fn from_target(s: &str) -> Result<Self, Error> { pub fn from_target(s: &str) -> Result<Self, String> {
EnvOptions::from_target(s).map(|env| Self { env, ..Self::default() }) EnvOptions::from_target(s).map(|env| Self { env, ..Self::default() })
} }
@ -115,7 +113,7 @@ impl TransformOptions {
/// * Same targets specified multiple times. /// * Same targets specified multiple times.
/// * No matching target. /// * No matching target.
/// * Invalid version. /// * Invalid version.
pub fn from_target_list<S: AsRef<str>>(list: &[S]) -> Result<Self, Error> { pub fn from_target_list<S: AsRef<str>>(list: &[S]) -> Result<Self, String> {
EnvOptions::from_target_list(list).map(|env| Self { env, ..Self::default() }) EnvOptions::from_target_list(list).map(|env| Self { env, ..Self::default() })
} }
} }
@ -129,13 +127,13 @@ impl From<ESTarget> for TransformOptions {
} }
impl TryFrom<&BabelOptions> for TransformOptions { impl TryFrom<&BabelOptions> for TransformOptions {
type Error = Vec<Error>; type Error = Vec<String>;
/// If the `options` contains any unknown fields, they will be returned as a list of errors. /// If the `options` contains any unknown fields, they will be returned as a list of errors.
fn try_from(options: &BabelOptions) -> Result<Self, Self::Error> { fn try_from(options: &BabelOptions) -> Result<Self, Self::Error> {
let mut errors = Vec::<Error>::new(); let mut errors = Vec::<String>::new();
errors.extend(options.plugins.errors.iter().map(|err| Error::msg(err.clone()))); errors.extend(options.plugins.errors.iter().map(Clone::clone));
errors.extend(options.presets.errors.iter().map(|err| Error::msg(err.clone()))); errors.extend(options.presets.errors.iter().map(Clone::clone));
let typescript = options let typescript = options
.presets .presets

View file

@ -84,8 +84,11 @@ impl Compiler {
.transpose()? .transpose()?
.map(InjectGlobalVariablesConfig::new); .map(InjectGlobalVariablesConfig::new);
let transform_options = let transform_options = match options {
options.map(oxc::transformer::TransformOptions::from).unwrap_or_default(); Some(options) => oxc::transformer::TransformOptions::try_from(options)
.map_err(|err| vec![OxcDiagnostic::error(err)])?,
None => oxc::transformer::TransformOptions::default(),
};
Ok(Self { Ok(Self {
transform_options, transform_options,

View file

@ -8,7 +8,7 @@ use oxc::parser::ParseOptions;
use oxc::{ use oxc::{
allocator::Allocator, allocator::Allocator,
codegen::{CodeGenerator, CodegenOptions}, codegen::{CodeGenerator, CodegenOptions},
diagnostics::{Error, NamedSource, OxcDiagnostic}, diagnostics::{NamedSource, OxcDiagnostic},
parser::Parser, parser::Parser,
span::{SourceType, VALID_EXTENSIONS}, span::{SourceType, VALID_EXTENSIONS},
transformer::{BabelOptions, HelperLoaderMode, TransformOptions}, transformer::{BabelOptions, HelperLoaderMode, TransformOptions},
@ -27,7 +27,7 @@ pub struct TestCase {
pub path: PathBuf, pub path: PathBuf,
options: BabelOptions, options: BabelOptions,
source_type: SourceType, source_type: SourceType,
transform_options: Result<TransformOptions, Vec<Error>>, transform_options: Result<TransformOptions, Vec<String>>,
pub errors: Vec<OxcDiagnostic>, pub errors: Vec<OxcDiagnostic>,
} }