mirror of
https://github.com/danbulant/oxc
synced 2026-05-24 12:21:58 +00:00
155 lines
5.3 KiB
Rust
155 lines
5.3 KiB
Rust
use oxc_allocator::Allocator;
|
|
#[allow(clippy::wildcard_imports)]
|
|
use oxc_ast::ast::*;
|
|
use oxc_minifier::{CompressOptions, MinifierOptions};
|
|
use oxc_parser::Parser;
|
|
use oxc_span::{SourceType, Span};
|
|
use walkdir::WalkDir;
|
|
|
|
use super::minify;
|
|
|
|
#[test]
|
|
fn test() {
|
|
let files = WalkDir::new("tests/terser/fixtures")
|
|
.into_iter()
|
|
.filter_map(Result::ok)
|
|
.filter(|e| !e.file_type().is_dir())
|
|
.collect::<Vec<_>>();
|
|
assert!(!files.is_empty());
|
|
for file in files {
|
|
let path = file.path();
|
|
let source_text = std::fs::read_to_string(path).unwrap();
|
|
let source_type = SourceType::from_path(path).unwrap();
|
|
let allocator = Allocator::default();
|
|
let parser_return = Parser::new(&allocator, &source_text, source_type).parse();
|
|
let program = allocator.alloc(parser_return.program);
|
|
TestSuite::from_program(&source_text, program).execute_tests();
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Default)]
|
|
struct TestSuite {
|
|
tests: Vec<TestCase>,
|
|
}
|
|
|
|
impl TestSuite {
|
|
fn from_program<'a>(source_text: &str, program: &'a Program<'a>) -> Self {
|
|
let mut tests = vec![];
|
|
for stmt in &program.body {
|
|
if let Statement::LabeledStatement(labeled_stmt) = stmt {
|
|
let test_case = TestCase::from_labeled_statement(source_text, labeled_stmt);
|
|
tests.push(test_case);
|
|
}
|
|
}
|
|
Self { tests }
|
|
}
|
|
|
|
fn execute_tests(&self) {
|
|
assert!(!self.tests.is_empty());
|
|
for test in &self.tests {
|
|
test.execute_test();
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Default)]
|
|
struct TestCase {
|
|
name: String,
|
|
compress_options: CompressOptions,
|
|
input: Box<str>,
|
|
expect: Box<str>,
|
|
}
|
|
|
|
impl TestCase {
|
|
fn execute_test(&self) {
|
|
fn remove_whitespace(s: &str) -> String {
|
|
s.replace(char::is_whitespace, "")
|
|
}
|
|
|
|
let source_type = SourceType::default();
|
|
let options = MinifierOptions { mangle: false, compress: self.compress_options };
|
|
let minified_source_text = minify(self.input.as_ref(), source_type, options);
|
|
assert_eq!(
|
|
remove_whitespace(minified_source_text.as_str()),
|
|
remove_whitespace(self.expect.as_ref()),
|
|
"{} {:?}",
|
|
&self.name,
|
|
&self.compress_options
|
|
);
|
|
}
|
|
|
|
fn from_labeled_statement<'a>(
|
|
source_text: &str,
|
|
labeled_stmt: &'a LabeledStatement<'a>,
|
|
) -> Self {
|
|
let name = labeled_stmt.label.name.to_string();
|
|
let mut options = CompressOptions::default();
|
|
let mut input = String::new().into_boxed_str();
|
|
let mut expect = String::new().into_boxed_str();
|
|
|
|
if let Statement::BlockStatement(block_stmt) = &labeled_stmt.body {
|
|
for stmt in &block_stmt.body {
|
|
// Parse options
|
|
if let Statement::ExpressionStatement(expr_stmt) = stmt {
|
|
if let Expression::AssignmentExpression(assign_expr) = &expr_stmt.expression {
|
|
if let AssignmentTarget::SimpleAssignmentTarget(
|
|
SimpleAssignmentTarget::AssignmentTargetIdentifier(ident),
|
|
) = &assign_expr.left
|
|
{
|
|
if ident.name == "options" {
|
|
if let Expression::ObjectExpression(object_expr) =
|
|
&assign_expr.right
|
|
{
|
|
options = Self::parse_options(object_expr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Parse input / expect
|
|
if let Statement::LabeledStatement(labeled_stmt) = stmt {
|
|
if let Statement::BlockStatement(block_stmt) = &labeled_stmt.body {
|
|
let span = block_stmt.span;
|
|
let code = Span::new(span.start + 1, span.end - 1)
|
|
.source_text(source_text)
|
|
.to_string()
|
|
.into_boxed_str();
|
|
match labeled_stmt.label.name.as_str() {
|
|
"input" => {
|
|
input = code;
|
|
}
|
|
"expect" => {
|
|
expect = code;
|
|
}
|
|
_ => {}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Self { name, compress_options: options, input, expect }
|
|
}
|
|
|
|
#[allow(clippy::single_match)]
|
|
fn parse_options<'a>(object_expr: &'a ObjectExpression<'a>) -> CompressOptions {
|
|
let mut options = CompressOptions::default();
|
|
for object_property in &object_expr.properties {
|
|
if let ObjectPropertyKind::ObjectProperty(property) = object_property {
|
|
if property.key.is_specific_static_name("drop_debugger") {
|
|
options.drop_debugger = Self::get_boolean(&property.value);
|
|
}
|
|
}
|
|
}
|
|
options
|
|
}
|
|
|
|
fn get_boolean<'a>(expr: &'a Expression<'a>) -> bool {
|
|
if let Expression::BooleanLiteral(boolean_literal) = expr {
|
|
boolean_literal.value
|
|
} else {
|
|
false
|
|
}
|
|
}
|
|
}
|