perl_module/rename/
mod.rs1mod detection;
6mod rewriting;
7
8use crate::import_match::line_references_module_import;
9use crate::token::{module_variant_pairs, replace_module_token};
10use detection::line_references_moose_moo_dsl;
11pub use detection::{
12 line_references_isa_assignment, line_references_package_declaration,
13 line_references_qualified_call,
14};
15pub use rewriting::replace_module_name_prefix;
16
17#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct ModuleLineEdit {
20 pub line: usize,
22 pub start_character: usize,
24 pub end_character: usize,
26 pub new_text: String,
28}
29
30#[must_use]
32pub fn plan_module_rename_edits(
33 source: &str,
34 old_module: &str,
35 new_module: &str,
36) -> Vec<ModuleLineEdit> {
37 if source.is_empty()
38 || old_module.is_empty()
39 || new_module.is_empty()
40 || old_module == new_module
41 {
42 return Vec::new();
43 }
44
45 let variants = module_variant_pairs(old_module, new_module);
46 let mut edits = Vec::new();
47
48 for (line_idx, line) in source.lines().enumerate() {
49 let mut rewritten: Option<String> = None;
50
51 for (old_variant, new_variant) in &variants {
52 {
53 let current_line = rewritten.as_deref().unwrap_or(line);
54 if line_references_module_import(current_line, old_variant) {
55 let (candidate, changed) =
56 replace_module_token(current_line, old_variant, new_variant);
57 if changed {
58 rewritten = Some(candidate);
59 }
60 }
61 }
62
63 {
64 let current_line = rewritten.as_deref().unwrap_or(line);
65 if line_references_moose_moo_dsl(current_line, old_variant) {
66 let (candidate, changed) =
67 replace_module_token(current_line, old_variant, new_variant);
68 if changed {
69 rewritten = Some(candidate);
70 }
71 }
72 }
73
74 {
75 let current_line = rewritten.as_deref().unwrap_or(line);
76 if line_references_isa_assignment(current_line, old_variant) {
77 let (candidate, changed) =
78 replace_module_token(current_line, old_variant, new_variant);
79 if changed {
80 rewritten = Some(candidate);
81 }
82 }
83 }
84
85 {
86 let current_line = rewritten.as_deref().unwrap_or(line);
87 if line_references_qualified_call(current_line, old_variant) {
88 let candidate =
89 replace_module_name_prefix(current_line, old_variant, new_variant);
90 if candidate != current_line {
91 rewritten = Some(candidate);
92 }
93 }
94 }
95
96 {
97 let current_line = rewritten.as_deref().unwrap_or(line);
98 if line_references_package_declaration(current_line, old_variant) {
99 let (candidate, changed) =
100 replace_module_token(current_line, old_variant, new_variant);
101 if changed {
102 rewritten = Some(candidate);
103 }
104 }
105 }
106 }
107
108 if let Some(new_text) = rewritten {
109 edits.push(ModuleLineEdit {
110 line: line_idx,
111 start_character: 0,
112 end_character: line.len(),
113 new_text,
114 });
115 }
116 }
117
118 edits
119}
120
121#[must_use]
123pub fn apply_module_rename_edits(source: &str, edits: &[ModuleLineEdit]) -> String {
124 if edits.is_empty() {
125 return source.to_string();
126 }
127
128 let mut lines: Vec<String> = source.split('\n').map(ToString::to_string).collect();
129
130 let mut sorted = edits.to_vec();
131 sorted.sort_by_key(|edit| edit.line);
132
133 for edit in sorted {
134 if let Some(line) = lines.get_mut(edit.line) {
135 *line = edit.new_text;
136 }
137 }
138
139 lines.join("\n")
140}