ezno_lib/transformers/
optimisations.rs1use checker::FunctionId;
2use parser::{
3 declarations::{
4 classes::{ClassMember, ClassProperty},
5 ClassDeclaration,
6 },
7 expressions::object_literal::ObjectLiteralMember,
8 visiting::{BlockItemMut, VisitorMut},
9 ASTNode, Expression, ExpressionOrStatementPosition, SourceId, StatementOrDeclaration,
10};
11
12use crate::build::CheckingOutputWithoutDiagnostics;
13
14pub struct ExpressionOptimiser;
19
20impl VisitorMut<Expression, CheckingOutputWithoutDiagnostics> for ExpressionOptimiser {
21 fn visit_mut(
22 &mut self,
23 item: &mut Expression,
24 data: &mut CheckingOutputWithoutDiagnostics,
25 chain: &parser::visiting::Chain,
26 ) {
27 match item {
28 Expression::ObjectLiteral(literal) => {
29 for item in literal.members.iter_mut() {
31 if let ObjectLiteralMember::Method(method) = item {
32 let position = method.get_position();
33 let function_id = FunctionId(chain.get_module(), position.start);
34 if !data.is_function_called(function_id) {
35 let key = method.name.clone();
37 *item = ObjectLiteralMember::Property {
38 key,
39 assignment: false,
40 value: Expression::Null(position),
41 position,
42 };
43 }
44 }
45 }
46 }
47 Expression::ArrowFunction(func) => {
48 if !data
49 .is_function_called(FunctionId(chain.get_module(), func.get_position().start))
50 {
51 *item = Expression::Null(func.get_position());
52 }
53 }
54 Expression::ExpressionFunction(func) => {
55 if !data
56 .is_function_called(FunctionId(chain.get_module(), func.get_position().start))
57 {
58 *item = Expression::Null(func.get_position());
59 }
60 }
61 Expression::ClassExpression(cls) => {
62 shake_class(cls, data, chain.get_module());
63 }
64 _ => {}
65 }
66 }
67}
68
69pub struct StatementOptimiser;
72
73impl VisitorMut<BlockItemMut<'_>, CheckingOutputWithoutDiagnostics> for StatementOptimiser {
74 fn visit_mut(
75 &mut self,
76 item: &mut BlockItemMut,
77 data: &mut CheckingOutputWithoutDiagnostics,
78 chain: &parser::visiting::Chain,
79 ) {
80 if let BlockItemMut::StatementOrDeclaration(StatementOrDeclaration::Declaration(
81 declaration,
82 )) = item
83 {
84 match declaration {
85 parser::Declaration::Variable(_) => {
86 }
88 parser::Declaration::Function(func) => {
89 if !data.is_function_called(FunctionId(
90 chain.get_module(),
91 func.get_position().start,
92 )) {
93 *declaration = parser::Declaration::Variable(
97 parser::declarations::VariableDeclaration::LetDeclaration {
98 declarations: Vec::new(),
99 position: func.get_position(),
100 },
101 )
102 }
103 }
104 parser::Declaration::Class(cls) => {
105 shake_class(&mut cls.on, data, chain.get_module());
106 }
107 parser::Declaration::Import(_) => {
108 }
110 parser::Declaration::Export(_) => {
111 }
113 parser::Declaration::Enum(_)
114 | parser::Declaration::Interface(_)
115 | parser::Declaration::TypeAlias(_)
116 | parser::Declaration::DeclareVariable(_)
117 | parser::Declaration::Namespace(_) => {}
118 }
119 }
120 }
121}
122
123fn shake_class<T: ExpressionOrStatementPosition>(
125 class: &mut ClassDeclaration<T>,
126 data: &CheckingOutputWithoutDiagnostics,
127 source: SourceId,
128) {
129 for item in class.members.iter_mut() {
130 if let ClassMember::Method(is_static, func) = &item.on {
131 let id = FunctionId(source, func.position.start);
132 if !data.is_function_called(id) {
133 item.on = ClassMember::Property(
135 *is_static,
136 ClassProperty {
137 is_readonly: false,
138 is_optional: false,
139 key: func.name.clone(),
140 type_annotation: None,
141 value: Some(Box::new(Expression::Null(func.position))),
142 position: func.position,
143 },
144 );
145 }
146 }
147 }
148}