Skip to content

Commit

Permalink
feat(minifier): add skeleton for RemoveDeadCode ast pass (#3802)
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen committed Jun 21, 2024
1 parent 8027b1e commit f3c3970
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 4 deletions.
4 changes: 4 additions & 0 deletions crates/oxc_minifier/src/ast_passes/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#![allow(clippy::wildcard_imports)]

mod remove_dead_code;
mod remove_parens;

pub use remove_dead_code::RemoveDeadCode;
pub use remove_parens::RemoveParens;
45 changes: 45 additions & 0 deletions crates/oxc_minifier/src/ast_passes/remove_dead_code.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use oxc_allocator::Allocator;
use oxc_ast::{ast::*, visit::walk_mut, AstBuilder, VisitMut};
use oxc_span::SPAN;

/// Remove Dead Code from the AST.
///
/// Terser option: `dead_code: true`.
#[derive(Clone, Copy)]
pub struct RemoveDeadCode<'a> {
ast: AstBuilder<'a>,
}

impl<'a> RemoveDeadCode<'a> {
pub fn new(allocator: &'a Allocator) -> Self {
Self { ast: AstBuilder::new(allocator) }
}

pub fn build(&mut self, program: &mut Program<'a>) {
self.visit_program(program);
}

pub fn remove_if(&mut self, stmt: &mut Statement<'a>) {
let Statement::IfStatement(if_stmt) = stmt else { return };
match if_stmt.test.get_boolean_value() {
Some(true) => {
*stmt = self.ast.move_statement(&mut if_stmt.consequent);
}
Some(false) => {
*stmt = if let Some(alternate) = &mut if_stmt.alternate {
self.ast.move_statement(alternate)
} else {
self.ast.empty_statement(SPAN)
};
}
_ => {}
}
}
}

impl<'a> VisitMut<'a> for RemoveDeadCode<'a> {
fn visit_statement(&mut self, stmt: &mut Statement<'a>) {
self.remove_if(stmt);
walk_mut::walk_statement_mut(self, stmt);
}
}
8 changes: 5 additions & 3 deletions crates/oxc_minifier/src/ast_passes/remove_parens.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use oxc_allocator::{Allocator, Vec};
use oxc_ast::visit::walk_mut::{walk_expression_mut, walk_statements_mut};
#[allow(clippy::wildcard_imports)]
use oxc_ast::{ast::*, AstBuilder, VisitMut};
use oxc_ast::{
ast::*,
visit::walk_mut::{walk_expression_mut, walk_statements_mut},
AstBuilder, VisitMut,
};

/// Remove Parenthesized Expression from the AST.
#[derive(Clone, Copy)]
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_minifier/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use oxc_allocator::Allocator;
use oxc_ast::ast::Program;

pub use crate::{
ast_passes::RemoveParens,
ast_passes::{RemoveDeadCode, RemoveParens},
compressor::{CompressOptions, Compressor},
mangler::ManglerBuilder,
};
Expand Down
1 change: 1 addition & 0 deletions crates/oxc_minifier/tests/oxc/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod code_removal;
mod folding;
mod precedence;
mod remove_dead_code;
26 changes: 26 additions & 0 deletions crates/oxc_minifier/tests/oxc/remove_dead_code.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
use oxc_allocator::Allocator;
use oxc_codegen::WhitespaceRemover;
use oxc_minifier::RemoveDeadCode;
use oxc_parser::Parser;
use oxc_span::SourceType;

fn minify(source_text: &str) -> String {
let source_type = SourceType::default();
let allocator = Allocator::default();
let ret = Parser::new(&allocator, source_text, source_type).parse();
let program = allocator.alloc(ret.program);
RemoveDeadCode::new(&allocator).build(program);
WhitespaceRemover::new().build(program).source_text
}

pub(crate) fn test(source_text: &str, expected: &str) {
let minified = minify(source_text);
assert_eq!(minified, expected, "for source {source_text}");
}

#[test]
fn remove_dead_code() {
test("if (true) { foo }", "{foo}");
test("if (true) { foo } else { bar }", "{foo}");
test("if (false) { foo } else { bar }", "{bar}");
}

0 comments on commit f3c3970

Please sign in to comment.