fix(transform_conformance): only print semantic mismatch errors when output is correct (#5589)

closes #5166

Had to rerun for mismatch errors :-/
This commit is contained in:
Boshen 2024-09-07 16:32:53 +00:00
parent 24d6a47f8b
commit 919d17fc5c
6 changed files with 2831 additions and 4732 deletions

View file

@ -102,7 +102,7 @@ impl BabelOptions {
}
pub fn is_module(&self) -> bool {
self.source_type.as_ref().map_or(false, |s| matches!(s.as_str(), "module"))
self.source_type.as_ref().map_or(false, |s| s.as_str() == "module")
}
pub fn is_unambiguous(&self) -> bool {

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -10,6 +10,7 @@ use oxc::{
};
pub struct Driver {
check_semantic: bool,
options: TransformOptions,
printed: String,
errors: Vec<OxcDiagnostic>,
@ -41,20 +42,22 @@ impl CompilerInterface for Driver {
program: &mut Program<'_>,
transformer_return: &mut TransformerReturn,
) -> ControlFlow<()> {
if let Some(errors) = check_semantic_after_transform(
&transformer_return.symbols,
&transformer_return.scopes,
program,
) {
self.errors.extend(errors);
if self.check_semantic {
if let Some(errors) = check_semantic_after_transform(
&transformer_return.symbols,
&transformer_return.scopes,
program,
) {
self.errors.extend(errors);
}
}
ControlFlow::Continue(())
}
}
impl Driver {
pub fn new(options: TransformOptions) -> Self {
Self { options, printed: String::new(), errors: vec![] }
pub fn new(check_semantic: bool, options: TransformOptions) -> Self {
Self { check_semantic, options, printed: String::new(), errors: vec![] }
}
pub fn errors(&mut self) -> Vec<OxcDiagnostic> {

View file

@ -175,12 +175,12 @@ impl TestRunner {
let errors = test_case.errors();
if !errors.is_empty() {
snapshot.push('\n');
for error in test_case.errors() {
for error in errors {
snapshot.push_str(&error.message);
snapshot.push('\n');
}
snapshot.push('\n');
}
snapshot.push('\n');
}
snapshot.push('\n');
}

View file

@ -172,16 +172,13 @@ pub trait TestCase {
// Some babel test cases have a js extension, but contain typescript code.
// Therefore, if the typescript plugin exists, enable typescript.
let mut source_type = SourceType::from_path(path).unwrap();
if !source_type.is_typescript()
&& (self.options().get_plugin("transform-typescript").is_some()
|| self.options().get_plugin("syntax-typescript").is_some())
{
source_type = source_type.with_typescript(true);
}
let source_type = SourceType::from_path(path).unwrap().with_typescript(
self.options().get_plugin("transform-typescript").is_some()
|| self.options().get_plugin("syntax-typescript").is_some(),
);
let driver =
Driver::new(transform_options.clone()).execute(&source_text, source_type, path);
Driver::new(false, transform_options.clone()).execute(&source_text, source_type, path);
Ok(driver)
}
}
@ -228,25 +225,27 @@ impl TestCase for ConformanceTestCase {
let allocator = Allocator::default();
let input = fs::read_to_string(&self.path).unwrap();
let input_is_js = self.path.extension().and_then(std::ffi::OsStr::to_str) == Some("js");
let output_is_js = output_path
.as_ref()
.is_some_and(|path| path.extension().and_then(std::ffi::OsStr::to_str) == Some("js"));
let mut source_type = SourceType::from_path(&self.path)
.unwrap()
.with_script(if self.options.source_type.is_some() {
!self.options.is_module()
} else {
input_is_js && output_is_js
})
.with_jsx(self.options.get_plugin("syntax-jsx").is_some());
if !source_type.is_typescript()
&& (self.options.get_plugin("transform-typescript").is_some()
|| self.options.get_plugin("syntax-typescript").is_some())
{
source_type = source_type.with_typescript(true);
}
let source_type = {
let mut source_type = SourceType::from_path(&self.path)
.unwrap()
.with_jsx(self.options.get_plugin("syntax-jsx").is_some());
source_type = match self.options.source_type.as_deref() {
Some("unambiguous") => source_type.with_unambiguous(true),
Some("script") => source_type.with_script(true),
Some("module") => source_type.with_module(true),
Some(s) => panic!("Unexpected source type {s}"),
None => source_type,
};
source_type = source_type.with_typescript(
self.options.get_plugin("transform-typescript").is_some()
|| self.options.get_plugin("syntax-typescript").is_some(),
);
source_type
};
if filtered {
println!("input_path: {:?}", &self.path);
@ -255,14 +254,18 @@ impl TestCase for ConformanceTestCase {
let project_root = project_root();
let mut transformed_code = String::new();
let mut actual_errors = String::new();
let mut actual_errors = None;
let mut transform_options = None;
match self.transform_options() {
Err(json_err) => {
let error = json_err.iter().map(ToString::to_string).collect::<Vec<_>>().join("\n");
actual_errors.replace(get_babel_error(&error));
}
Ok(options) => {
transform_options.replace(options.clone());
let mut driver =
Driver::new(options.clone()).execute(&input, source_type, &self.path);
Driver::new(false, options.clone()).execute(&input, source_type, &self.path);
transformed_code = driver.printed();
let errors = driver.errors();
if !errors.is_empty() {
@ -275,13 +278,9 @@ impl TestCase for ConformanceTestCase {
.map(|err| format!("{:?}", err.with_source_code(source.clone())))
.collect::<Vec<_>>()
.join("\n");
actual_errors = get_babel_error(&error);
actual_errors.replace(get_babel_error(&error));
}
}
Err(json_err) => {
let error = json_err.iter().map(ToString::to_string).collect::<Vec<_>>().join("\n");
actual_errors = get_babel_error(&error);
}
}
let babel_options = self.options();
@ -289,7 +288,8 @@ impl TestCase for ConformanceTestCase {
let output;
let passed = if let Some(throws) = &babel_options.throws {
output = throws.to_string().replace(" (1:6)", "");
!output.is_empty() && actual_errors.contains(&output)
!output.is_empty()
&& actual_errors.as_ref().is_some_and(|errors| errors.contains(&output))
} else {
// Get output.js by using our code gen so code comparison can match.
output = output_path.and_then(|path| fs::read_to_string(path).ok()).map_or_else(
@ -302,10 +302,10 @@ impl TestCase for ConformanceTestCase {
);
if transformed_code == output {
actual_errors.is_empty()
actual_errors.is_none()
} else {
if !actual_errors.is_empty() && !transformed_code.is_empty() {
actual_errors.insert_str(0, " x Output mismatch\n");
if actual_errors.is_none() {
actual_errors.replace("x Output mismatch".to_string());
}
false
}
@ -320,10 +320,12 @@ impl TestCase for ConformanceTestCase {
println!("Expected Errors:\n");
println!("{output}\n");
println!("Actual Errors:\n");
println!("{actual_errors}\n");
if !passed {
println!("Diff:\n");
print_diff_in_terminal(&output, &actual_errors);
if let Some(actual_errors) = &actual_errors {
println!("{actual_errors}\n");
if !passed {
println!("Diff:\n");
print_diff_in_terminal(&output, actual_errors);
}
}
} else {
println!("Expected:\n");
@ -331,7 +333,9 @@ impl TestCase for ConformanceTestCase {
println!("Transformed:\n");
println!("{transformed_code}");
println!("Errors:\n");
println!("{actual_errors}\n");
if let Some(actual_errors) = &actual_errors {
println!("{actual_errors}\n");
}
if !passed {
println!("Diff:\n");
print_diff_in_terminal(&output, &transformed_code);
@ -341,7 +345,15 @@ impl TestCase for ConformanceTestCase {
println!("Passed: {passed}");
}
if !passed {
if passed {
if let Some(options) = transform_options {
let mismatch_errors =
Driver::new(/* check transform mismatch */ true, options)
.execute(&input, source_type, &self.path)
.errors();
self.errors.extend(mismatch_errors);
}
} else if let Some(actual_errors) = actual_errors {
self.errors.push(OxcDiagnostic::error(actual_errors));
}
}