use crate::engine::ASTRegApply;
use crate::executor::registry::converter::{ConvertError, MutationConverter};
use crate::executor::registry::converters::ResolveTargetSymbol;
use crate::executor::spec::MutationSpec;
use ryo_analysis::AnalysisContext;
use ryo_mutations::MoveItemMutation;
pub struct MoveConverter;
impl MoveConverter {
pub fn new() -> Self {
Self
}
}
impl Default for MoveConverter {
fn default() -> Self {
Self::new()
}
}
impl ResolveTargetSymbol for MoveConverter {}
impl MutationConverter for MoveConverter {
fn spec_kinds(&self) -> &'static [&'static str] {
&["MoveItem"]
}
fn convert_v2(
&self,
spec: &MutationSpec,
ctx: &AnalysisContext,
) -> Result<Vec<Box<dyn ASTRegApply>>, ConvertError> {
match spec {
MutationSpec::MoveItem {
source: source_symbol,
target: target_symbol,
item_name,
item_kind,
add_use,
} => {
let source_id = self.resolve_target_symbol(source_symbol, ctx)?;
let target_id = self.resolve_target_symbol(target_symbol, ctx)?;
let source_path = ctx
.registry
.resolve(source_id)
.ok_or_else(|| {
ConvertError::TargetNotFound(format!(
"Source module {:?} not found",
source_id
))
})?
.clone();
let target_path = ctx
.registry
.resolve(target_id)
.ok_or_else(|| {
ConvertError::TargetNotFound(format!(
"Target module {:?} not found",
target_id
))
})?
.clone();
let mutation = MoveItemMutation::new(
source_path,
target_path,
item_name.clone(),
*item_kind,
*add_use,
);
Ok(vec![Box::new(mutation)])
}
_ => Err(ConvertError::TypeMismatch {
expected: "MoveItem",
actual: spec.kind_name().to_string(),
}),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::executor::spec::MutationSpec;
use ryo_source::ItemKind;
use ryo_symbol::{SymbolKind, SymbolPath, SymbolRegistry};
#[test]
fn test_move_converter_spec_kinds() {
let converter = MoveConverter::new();
assert_eq!(converter.spec_kinds(), &["MoveItem"]);
}
#[test]
fn test_move_converter_can_handle() {
let converter = MoveConverter::new();
let move_spec = MutationSpec::MoveItem {
source: crate::executor::spec::MutationTargetSymbol::ByPath(Box::new(
SymbolPath::parse("test_crate").unwrap(),
)),
target: crate::executor::spec::MutationTargetSymbol::ByPath(Box::new(
SymbolPath::parse("test_crate::core").unwrap(),
)),
item_name: "Task".into(),
item_kind: ItemKind::Struct,
add_use: true,
};
assert!(converter.can_handle(&move_spec));
let mut registry = SymbolRegistry::new();
let path = SymbolPath::parse("test_crate::old").unwrap();
let symbol_id = registry.register(path, SymbolKind::Function).unwrap();
let other_spec = MutationSpec::Rename {
target: crate::executor::spec::MutationTargetSymbol::ById(symbol_id),
to: "new".into(),
scope: crate::executor::spec::Scope::Project,
};
assert!(!converter.can_handle(&other_spec));
}
}