react_compiler_swc/
apply_renames.rs1use std::collections::HashMap;
7
8use react_compiler::entrypoint::compile_result::BindingRenameInfo;
9use react_compiler_ast::scope::BindingId;
10use swc_atoms::Atom;
11use swc_ecma_ast::*;
12use swc_ecma_visit::{VisitMut, VisitMutWith};
13
14use crate::convert_scope::build_scope_info;
15
16pub fn apply_renames(module: &mut Module, renames: &[BindingRenameInfo]) {
17 if renames.is_empty() {
18 return;
19 }
20
21 let scope_info = build_scope_info(module);
22 let renames_by_declaration: HashMap<u32, &BindingRenameInfo> = renames
23 .iter()
24 .map(|rename| (rename.declaration_start, rename))
25 .collect();
26 let mut renamed_bindings: HashMap<BindingId, String> = HashMap::new();
27
28 for binding in &scope_info.bindings {
29 let Some(rename) = binding
30 .declaration_start
31 .and_then(|start| renames_by_declaration.get(&start))
32 else {
33 continue;
34 };
35 if binding.name == rename.original {
36 renamed_bindings.insert(binding.id, rename.renamed.clone());
37 }
38 }
39
40 if renamed_bindings.is_empty() {
41 return;
42 }
43
44 let rewrite_plan: HashMap<u32, String> = scope_info
45 .reference_to_binding
46 .iter()
47 .filter_map(|(&position, binding_id)| {
48 renamed_bindings.get(binding_id).map(|renamed| (position, renamed.clone()))
49 })
50 .collect();
51
52 module.visit_mut_with(&mut RenameApplyVisitor { rewrite_plan });
53}
54
55struct RenameApplyVisitor {
56 rewrite_plan: HashMap<u32, String>,
57}
58
59impl RenameApplyVisitor {
60 fn renamed_at(&self, position: u32) -> Option<String> {
61 self.rewrite_plan.get(&position).cloned()
62 }
63}
64
65impl VisitMut for RenameApplyVisitor {
66 fn visit_mut_ident(&mut self, ident: &mut Ident) {
67 if let Some(renamed) = self.renamed_at(ident.span.lo.0) {
68 ident.sym = Atom::from(renamed);
69 }
70 }
71
72 fn visit_mut_member_expr(&mut self, member: &mut MemberExpr) {
73 member.obj.visit_mut_with(self);
74 if let MemberProp::Computed(computed) = &mut member.prop {
75 computed.visit_mut_with(self);
76 }
77 }
78
79 fn visit_mut_prop(&mut self, prop: &mut Prop) {
80 match prop {
81 Prop::Shorthand(ident) => {
82 if let Some(renamed) = self.renamed_at(ident.span.lo.0) {
83 let mut value = ident.clone();
84 value.sym = Atom::from(renamed);
85 *prop = Prop::KeyValue(KeyValueProp {
87 key: PropName::Ident(IdentName {
88 span: ident.span,
89 sym: ident.sym.clone(),
90 }),
91 value: Box::new(Expr::Ident(value)),
92 });
93 }
94 }
95 Prop::Assign(assign) => {
96 assign.value.visit_mut_with(self);
97 }
98 _ => prop.visit_mut_children_with(self),
99 }
100 }
101
102 fn visit_mut_object_pat_prop(&mut self, prop: &mut ObjectPatProp) {
103 match prop {
104 ObjectPatProp::Assign(assign) => {
105 if let Some(value) = &mut assign.value {
106 value.visit_mut_with(self);
107 }
108
109 if let Some(renamed) = self.renamed_at(assign.key.id.span.lo.0) {
110 let mut binding = assign.key.clone();
111 binding.id.sym = Atom::from(renamed);
112 let value = match assign.value.take() {
113 Some(default_value) => Pat::Assign(AssignPat {
114 span: assign.span,
115 left: Box::new(Pat::Ident(binding)),
116 right: default_value,
117 }),
118 None => Pat::Ident(binding),
119 };
120
121 *prop = ObjectPatProp::KeyValue(KeyValuePatProp {
122 key: PropName::Ident(IdentName {
123 span: assign.key.id.span,
124 sym: assign.key.id.sym.clone(),
125 }),
126 value: Box::new(value),
127 });
128 }
129 }
130 _ => prop.visit_mut_children_with(self),
131 }
132 }
133}