use crate::ast::RustAST;
use crate::ops::{Rename, RenameResult};
#[derive(Debug)]
pub struct MutResult<T> {
pub ast: RustAST,
pub result: T,
}
pub struct CowMut;
impl CowMut {
pub fn rename(ast: &RustAST, old: &str, new: &str) -> MutResult<RenameResult> {
let mut cloned = ast.clone();
let result = Rename::apply(&mut cloned, old, new);
MutResult {
ast: cloned,
result,
}
}
pub fn multi_rename(ast: &RustAST, renames: &[(&str, &str)]) -> Vec<MutResult<RenameResult>> {
renames
.iter()
.map(|(old, new)| Self::rename(ast, old, new))
.collect()
}
pub fn chain_renames(ast: &RustAST, renames: &[(&str, &str)]) -> MutResult<Vec<RenameResult>> {
let mut current = ast.clone();
let mut results = Vec::with_capacity(renames.len());
for (old, new) in renames {
let result = Rename::apply(&mut current, old, new);
results.push(result);
}
MutResult {
ast: current,
result: results,
}
}
}
pub struct SourceParallel;
impl SourceParallel {
#[cfg(feature = "parallel")]
pub fn analyze_sources<F, T>(sources: &[&str], analyzer: F) -> Vec<T>
where
F: Fn(&RustAST) -> T + Sync,
T: Send,
{
use rayon::prelude::*;
sources
.par_iter()
.filter_map(|src| {
let ast = RustAST::parse(src).ok()?;
Some(analyzer(&ast))
})
.collect()
}
#[cfg(feature = "parallel")]
pub fn transform_sources<F, T>(sources: &[&str], transformer: F) -> Vec<(String, T)>
where
F: Fn(&mut RustAST) -> T + Sync,
T: Send,
{
use rayon::prelude::*;
sources
.par_iter()
.filter_map(|src| {
let mut ast = RustAST::parse(src).ok()?;
let result = transformer(&mut ast);
Some((ast.to_string(), result))
})
.collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cow_rename() {
let original = RustAST::parse("fn foo() {}").unwrap();
let original_str = original.to_string();
let result = CowMut::rename(&original, "foo", "bar");
assert_eq!(original.to_string(), original_str);
assert!(result.ast.to_string().contains("fn bar"));
assert_eq!(result.result.count, 1);
}
#[test]
fn test_multi_rename() {
let ast = RustAST::parse(
r#"
fn alpha() {}
fn beta() {}
fn gamma() {}
"#,
)
.unwrap();
let renames = vec![("alpha", "first"), ("beta", "second"), ("gamma", "third")];
let results = CowMut::multi_rename(&ast, &renames);
assert_eq!(results.len(), 3);
assert!(results[0].ast.to_string().contains("fn first"));
assert!(results[0].ast.to_string().contains("fn beta"));
assert!(results[1].ast.to_string().contains("fn second"));
assert!(results[1].ast.to_string().contains("fn alpha"));
assert!(results[2].ast.to_string().contains("fn third"));
assert!(results[2].ast.to_string().contains("fn alpha")); }
#[test]
fn test_chain_renames() {
let ast = RustAST::parse(
r#"
fn alpha() {}
fn beta() {}
"#,
)
.unwrap();
let renames = vec![("alpha", "first"), ("beta", "second")];
let result = CowMut::chain_renames(&ast, &renames);
assert!(result.ast.to_string().contains("fn first"));
assert!(result.ast.to_string().contains("fn second"));
assert!(!result.ast.to_string().contains("alpha"));
assert!(!result.ast.to_string().contains("beta"));
assert_eq!(result.result.len(), 2);
}
}