perl_module/rename/
rewriting.rs1#[must_use]
3pub fn replace_module_name_prefix(line: &str, old_module: &str, new_module: &str) -> String {
4 if old_module.is_empty() || new_module.is_empty() || line.is_empty() {
5 return line.to_string();
6 }
7 let trimmed = line.trim_start();
8 if trimmed.starts_with("package ")
9 || trimmed.starts_with("use ")
10 || trimmed.starts_with("require ")
11 || trimmed.starts_with("no ")
12 {
13 return line.to_string();
14 }
15
16 let mut out = line.to_string();
17
18 for separator in ["::", "'"] {
19 let needle = format!("{old_module}{separator}");
20 let replacement = format!("{new_module}{separator}");
21 let needle_bytes = needle.as_bytes();
22 let needle_len = needle_bytes.len();
23 let line_bytes = out.as_bytes();
24
25 if line_bytes.len() < needle_len {
26 continue;
27 }
28
29 let mut replaced = String::with_capacity(out.len());
30 let mut cursor = 0usize;
31
32 while cursor + needle_len <= line_bytes.len() {
33 let Some(rel) = out[cursor..].find(needle.as_str()) else {
34 break;
35 };
36 let abs = cursor + rel;
37 let after = abs + needle_len;
38
39 let before_ok = abs == 0 || {
40 let ch = line_bytes[abs - 1] as char;
41 !ch.is_alphanumeric() && ch != '_' && ch != ':'
42 };
43
44 let after_ok = after < line_bytes.len() && {
45 let ch = line_bytes[after] as char;
46 ch.is_alphabetic() || ch == '_'
47 };
48
49 if before_ok && after_ok && !index_is_in_quote_or_comment(&out, abs) {
50 replaced.push_str(&out[cursor..abs]);
51 replaced.push_str(&replacement);
52 cursor = after;
53 } else {
54 replaced.push_str(&out[cursor..abs + 1]);
55 cursor = abs + 1;
56 }
57 }
58
59 replaced.push_str(&out[cursor..]);
60 out = replaced;
61 }
62
63 out
64}
65
66pub(super) fn index_is_in_quote_or_comment(line: &str, index: usize) -> bool {
67 let bytes = line.as_bytes();
68 if index >= bytes.len() {
69 return false;
70 }
71
72 let mut in_single = false;
73 let mut in_double = false;
74 let mut escaped = false;
75
76 for (i, &byte) in bytes.iter().enumerate() {
77 if i == index {
78 return in_single || in_double;
79 }
80
81 let ch = byte as char;
82 if escaped {
83 escaped = false;
84 continue;
85 }
86
87 if in_single {
88 if ch == '\\' {
89 escaped = true;
90 continue;
91 }
92 if ch == '\'' {
93 in_single = false;
94 }
95 continue;
96 }
97
98 if in_double {
99 if ch == '\\' {
100 escaped = true;
101 continue;
102 }
103 if ch == '"' {
104 in_double = false;
105 }
106 continue;
107 }
108
109 if ch == '#' {
110 return i < index;
111 }
112
113 if ch == '\'' {
114 in_single = true;
115 continue;
116 }
117
118 if ch == '"' {
119 in_double = true;
120 }
121 }
122
123 false
124}