mod detection;
mod rewriting;
use crate::import_match::line_references_module_import;
use crate::token::{module_variant_pairs, replace_module_token};
use detection::line_references_moose_moo_dsl;
pub use detection::{
line_references_isa_assignment, line_references_package_declaration,
line_references_qualified_call,
};
pub use rewriting::replace_module_name_prefix;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ModuleLineEdit {
pub line: usize,
pub start_character: usize,
pub end_character: usize,
pub new_text: String,
}
#[must_use]
pub fn plan_module_rename_edits(
source: &str,
old_module: &str,
new_module: &str,
) -> Vec<ModuleLineEdit> {
if source.is_empty()
|| old_module.is_empty()
|| new_module.is_empty()
|| old_module == new_module
{
return Vec::new();
}
let variants = module_variant_pairs(old_module, new_module);
let mut edits = Vec::new();
for (line_idx, line) in source.lines().enumerate() {
let mut rewritten: Option<String> = None;
for (old_variant, new_variant) in &variants {
{
let current_line = rewritten.as_deref().unwrap_or(line);
if line_references_module_import(current_line, old_variant) {
let (candidate, changed) =
replace_module_token(current_line, old_variant, new_variant);
if changed {
rewritten = Some(candidate);
}
}
}
{
let current_line = rewritten.as_deref().unwrap_or(line);
if line_references_moose_moo_dsl(current_line, old_variant) {
let (candidate, changed) =
replace_module_token(current_line, old_variant, new_variant);
if changed {
rewritten = Some(candidate);
}
}
}
{
let current_line = rewritten.as_deref().unwrap_or(line);
if line_references_isa_assignment(current_line, old_variant) {
let (candidate, changed) =
replace_module_token(current_line, old_variant, new_variant);
if changed {
rewritten = Some(candidate);
}
}
}
{
let current_line = rewritten.as_deref().unwrap_or(line);
if line_references_qualified_call(current_line, old_variant) {
let candidate =
replace_module_name_prefix(current_line, old_variant, new_variant);
if candidate != current_line {
rewritten = Some(candidate);
}
}
}
{
let current_line = rewritten.as_deref().unwrap_or(line);
if line_references_package_declaration(current_line, old_variant) {
let (candidate, changed) =
replace_module_token(current_line, old_variant, new_variant);
if changed {
rewritten = Some(candidate);
}
}
}
}
if let Some(new_text) = rewritten {
edits.push(ModuleLineEdit {
line: line_idx,
start_character: 0,
end_character: line.len(),
new_text,
});
}
}
edits
}
#[must_use]
pub fn apply_module_rename_edits(source: &str, edits: &[ModuleLineEdit]) -> String {
if edits.is_empty() {
return source.to_string();
}
let mut lines: Vec<String> = source.split('\n').map(ToString::to_string).collect();
let mut sorted = edits.to_vec();
sorted.sort_by_key(|edit| edit.line);
for edit in sorted {
if let Some(line) = lines.get_mut(edit.line) {
*line = edit.new_text;
}
}
lines.join("\n")
}