use anyhow::Result;
#[derive(Debug, Clone)]
pub struct RefactorOperation {
pub file_path: String,
original_code: String,
pub refactored_code: String,
operation_type: String, description: String,
}
impl RefactorOperation {
pub fn original_code(&self) -> &str {
&self.original_code
}
pub fn operation_type(&self) -> &str {
&self.operation_type
}
pub fn description(&self) -> &str {
&self.description
}
}
pub struct RefactorEngine {
operations: Vec<RefactorOperation>,
}
impl RefactorEngine {
pub fn new() -> Self {
Self {
operations: Vec::new(),
}
}
pub fn preview_refactor(&mut self, file_path: &str, refactor_type: &str, params: &RefactorParams) -> Result<String> {
let original_code = std::fs::read_to_string(file_path)?;
let refactored_code = self.apply_refactor(&original_code, refactor_type, params)?;
let operation = RefactorOperation {
file_path: file_path.to_string(),
original_code: original_code.clone(),
refactored_code: refactored_code.clone(),
operation_type: refactor_type.to_string(),
description: format!("{} operation on {}", refactor_type, file_path),
};
self.operations.push(operation);
Ok(refactored_code)
}
fn apply_refactor(&self, code: &str, refactor_type: &str, params: &RefactorParams) -> Result<String> {
match refactor_type {
"rename_variable" => self.rename_variable(code, params),
"extract_function" => self.extract_function(code, params),
"rename_function" => self.rename_function(code, params),
_ => Ok(code.to_string()), }
}
fn rename_variable(&self, code: &str, params: &RefactorParams) -> Result<String> {
if let (Some(old_name), Some(new_name)) = (¶ms.old_name, ¶ms.new_name) {
Ok(code.replace(old_name, new_name))
} else {
Ok(code.to_string())
}
}
fn rename_function(&self, code: &str, params: &RefactorParams) -> Result<String> {
if let (Some(old_name), Some(new_name)) = (¶ms.old_name, ¶ms.new_name) {
Ok(code.replace(&format!("fn {}(", old_name), &format!("fn {}(", new_name)))
} else {
Ok(code.to_string())
}
}
fn extract_function(&self, code: &str, _params: &RefactorParams) -> Result<String> {
Ok(code.to_string())
}
pub fn get_pending_operations(&self) -> &Vec<RefactorOperation> {
&self.operations
}
pub fn apply_pending_operations(&mut self) -> Result<()> {
for operation in &self.operations {
std::fs::write(&operation.file_path, &operation.refactored_code)?;
}
self.operations.clear();
Ok(())
}
pub fn cancel_pending_operations(&mut self) {
self.operations.clear();
}
pub fn get_operation_preview(&self, index: usize) -> Option<&RefactorOperation> {
self.operations.get(index)
}
}
#[derive(Debug, Clone)]
pub struct RefactorParams {
pub old_name: Option<String>,
pub new_name: Option<String>,
pub start_line: Option<usize>,
pub end_line: Option<usize>,
pub function_name: Option<String>,
pub visibility: Option<String>,
}
impl RefactorParams {
pub fn new() -> Self {
Self {
old_name: None,
new_name: None,
start_line: None,
end_line: None,
function_name: None,
visibility: None,
}
}
pub fn start_line(&self) -> Option<usize> {
self.start_line
}
pub fn end_line(&self) -> Option<usize> {
self.end_line
}
pub fn function_name(&self) -> Option<&str> {
self.function_name.as_deref()
}
pub fn visibility(&self) -> Option<&str> {
self.visibility.as_deref()
}
pub fn with_start_line(mut self, start_line: usize) -> Self {
self.start_line = Some(start_line);
self
}
pub fn with_end_line(mut self, end_line: usize) -> Self {
self.end_line = Some(end_line);
self
}
pub fn with_function_name<T: Into<String>>(mut self, function_name: T) -> Self {
self.function_name = Some(function_name.into());
self
}
pub fn with_visibility<T: Into<String>>(mut self, visibility: T) -> Self {
self.visibility = Some(visibility.into());
self
}
}