diff --git a/src/passes/field_deleter.rs b/src/passes/field_deleter.rs new file mode 100644 index 0000000..bd22276 --- /dev/null +++ b/src/passes/field_deleter.rs @@ -0,0 +1,81 @@ +use quote::ToTokens; +use syn::{visit_mut::VisitMut, Fields}; + +use crate::processor::{tracking, Pass, PassController, ProcessState, SourceFile}; + +struct Visitor<'a> { + current_path: Vec, + checker: &'a mut PassController, + process_state: ProcessState, +} + +impl<'a> Visitor<'a> { + fn new(checker: &'a mut PassController) -> Self { + Self { + current_path: Vec::new(), + checker, + process_state: ProcessState::NoChange, + } + } + + fn consider_deleting_field(&mut self, name: String) -> bool { + self.current_path.push(name); + let can_process = self.checker.can_process(&self.current_path); + if can_process { + self.process_state = ProcessState::Changed; + } + self.current_path.pop(); + !can_process + } +} + +impl VisitMut for Visitor<'_> { + fn visit_fields_mut(&mut self, fields: &mut syn::Fields) { + match fields { + Fields::Named(named) => { + named.named = named + .named + .clone() + .into_pairs() + .filter(|pair| { + let field = pair.value(); + self.consider_deleting_field(field.ident.as_ref().unwrap().to_string()) + }) + .collect(); + } + Fields::Unnamed(unnamed) => { + unnamed.unnamed = unnamed + .unnamed + .clone() + .into_pairs() + .enumerate() + .filter(|(i, _)| self.consider_deleting_field(i.to_string())) + .map(|(_, f)| f) + .collect(); + } + Fields::Unit => {} + } + } + + tracking!(); +} + +#[derive(Default)] +pub struct FieldDeleter; + +impl Pass for FieldDeleter { + fn process_file( + &mut self, + krate: &mut syn::File, + _: &SourceFile, + checker: &mut PassController, + ) -> ProcessState { + let mut visitor = Visitor::new(checker); + visitor.visit_file_mut(krate); + visitor.process_state + } + + fn name(&self) -> &'static str { + "field-deleter" + } +} diff --git a/src/passes/mod.rs b/src/passes/mod.rs index abe6797..b17bb05 100644 --- a/src/passes/mod.rs +++ b/src/passes/mod.rs @@ -1,5 +1,9 @@ mod everybody_loops; +mod field_deleter; mod item_deleter; mod privatize; -pub use self::{everybody_loops::EverybodyLoops, item_deleter::ItemDeleter, privatize::Privatize}; +pub use self::{ + everybody_loops::EverybodyLoops, field_deleter::FieldDeleter, item_deleter::ItemDeleter, + privatize::Privatize, +};