From a36bf95c3e47c293825f7d7d8cfd4eec4635858f Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sat, 17 Dec 2022 23:35:40 +0100 Subject: [PATCH] checker --- src/everybody_loops.rs | 33 ++++--------------------- src/privatize.rs | 32 +++++++++++++++++------- src/processor/mod.rs | 55 +++++++++++++++++++++++++++++++++++------ src/processor/reaper.rs | 39 +++++++++++++++++++++++------ 4 files changed, 106 insertions(+), 53 deletions(-) diff --git a/src/everybody_loops.rs b/src/everybody_loops.rs index cf811f4..4bbd129 100644 --- a/src/everybody_loops.rs +++ b/src/everybody_loops.rs @@ -1,18 +1,18 @@ use quote::ToTokens; use syn::{parse_quote, visit_mut::VisitMut}; -use crate::processor::{ProcessChecker, ProcessState, Processor, SourceFile}; +use crate::processor::{tracking, PassController, ProcessState, Processor, SourceFile}; struct Visitor<'a> { current_path: Vec, - checker: &'a mut ProcessChecker, + checker: &'a mut PassController, loop_expr: syn::Block, process_state: ProcessState, } impl<'a> Visitor<'a> { - fn new(checker: &'a mut ProcessChecker) -> Self { + fn new(checker: &'a mut PassController) -> Self { Self { current_path: Vec::new(), checker, @@ -35,30 +35,7 @@ impl VisitMut for Visitor<'_> { } } - fn visit_item_fn_mut(&mut self, func: &mut syn::ItemFn) { - self.current_path.push(func.sig.ident.to_string()); - syn::visit_mut::visit_item_fn_mut(self, func); - self.current_path.pop(); - } - - fn visit_impl_item_method_mut(&mut self, method: &mut syn::ImplItemMethod) { - self.current_path.push(method.sig.ident.to_string()); - syn::visit_mut::visit_impl_item_method_mut(self, method); - self.current_path.pop(); - } - - fn visit_item_impl_mut(&mut self, item: &mut syn::ItemImpl) { - self.current_path - .push(item.self_ty.clone().into_token_stream().to_string()); - syn::visit_mut::visit_item_impl_mut(self, item); - self.current_path.pop(); - } - - fn visit_item_mod_mut(&mut self, module: &mut syn::ItemMod) { - self.current_path.push(module.ident.to_string()); - syn::visit_mut::visit_item_mod_mut(self, module); - self.current_path.pop(); - } + tracking!(); } #[derive(Default)] @@ -69,7 +46,7 @@ impl Processor for EverybodyLoops { &mut self, krate: &mut syn::File, _: &SourceFile, - checker: &mut ProcessChecker, + checker: &mut PassController, ) -> ProcessState { let mut visitor = Visitor::new(checker); visitor.visit_file_mut(krate); diff --git a/src/privatize.rs b/src/privatize.rs index 88f0019..aabb357 100644 --- a/src/privatize.rs +++ b/src/privatize.rs @@ -1,36 +1,50 @@ +use quote::ToTokens; use syn::{parse_quote, visit_mut::VisitMut, Visibility}; -use crate::processor::{ProcessChecker, ProcessState, Processor, SourceFile}; +use crate::processor::{tracking, PassController, ProcessState, Processor, SourceFile}; -struct Visitor { +struct Visitor<'a> { pub_crate: Visibility, process_state: ProcessState, + current_path: Vec, + checker: &'a mut PassController, } -impl Visitor { - fn new() -> Self { +impl<'a> Visitor<'a> { + fn new(checker: &'a mut PassController) -> Self { Self { process_state: ProcessState::NoChange, pub_crate: parse_quote! { pub(crate) }, + current_path: Vec::new(), + checker, } } } -impl VisitMut for Visitor { +impl VisitMut for Visitor<'_> { fn visit_visibility_mut(&mut self, vis: &mut Visibility) { if let Visibility::Public(_) = vis { - self.process_state = ProcessState::Changed; - *vis = self.pub_crate.clone(); + if self.checker.can_process(&self.current_path) { + self.process_state = ProcessState::Changed; + *vis = self.pub_crate.clone(); + } } } + + tracking!(); } #[derive(Default)] pub struct Privatize {} impl Processor for Privatize { - fn process_file(&mut self, krate: &mut syn::File, _: &SourceFile, _: &mut ProcessChecker) -> ProcessState { - let mut visitor = Visitor::new(); + 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 } diff --git a/src/processor/mod.rs b/src/processor/mod.rs index bec06b1..43b961e 100644 --- a/src/processor/mod.rs +++ b/src/processor/mod.rs @@ -21,7 +21,7 @@ pub trait Processor { &mut self, krate: &mut syn::File, file: &SourceFile, - checker: &mut ProcessChecker, + checker: &mut PassController, ) -> ProcessState; fn name(&self) -> &'static str; @@ -88,7 +88,7 @@ impl Minimizer { let mut refresh_and_try_again = false; - 'pass: loop { + loop { println!("Starting a round of {}", pass.name()); let mut changes = Changes::default(); @@ -104,7 +104,7 @@ impl Minimizer { let mut krate = syn::parse_file(change.before_content()) .with_context(|| format!("parsing file {file_display}"))?; - let has_made_change = pass.process_file(&mut krate, file, &mut ProcessChecker {}); + let has_made_change = pass.process_file(&mut krate, file, &mut PassController {}); match has_made_change { ProcessState::Changed | ProcessState::FileInvalidated => { @@ -143,20 +143,59 @@ impl Minimizer { } println!("Finished {}", pass.name()); - break 'pass; + return Ok(()); } else { refresh_and_try_again = false; } } - - Ok(()) } } -pub struct ProcessChecker {} +pub struct PassController {} -impl ProcessChecker { +impl PassController { pub fn can_process(&mut self, _: &[String]) -> bool { + // FIXME: Actually do smart things here. true } } + +macro_rules! tracking { + () => { + tracking!(visit_item_fn_mut); + tracking!(visit_impl_item_method_mut); + tracking!(visit_item_impl_mut); + tracking!(visit_item_mod_mut); + }; + (visit_item_fn_mut) => { + fn visit_item_fn_mut(&mut self, func: &mut syn::ItemFn) { + self.current_path.push(func.sig.ident.to_string()); + syn::visit_mut::visit_item_fn_mut(self, func); + self.current_path.pop(); + } + }; + (visit_impl_item_method_mut) => { + fn visit_impl_item_method_mut(&mut self, method: &mut syn::ImplItemMethod) { + self.current_path.push(method.sig.ident.to_string()); + syn::visit_mut::visit_impl_item_method_mut(self, method); + self.current_path.pop(); + } + }; + (visit_item_impl_mut) => { + fn visit_item_impl_mut(&mut self, item: &mut syn::ItemImpl) { + self.current_path + .push(item.self_ty.clone().into_token_stream().to_string()); + syn::visit_mut::visit_item_impl_mut(self, item); + self.current_path.pop(); + } + }; + (visit_item_mod_mut) => { + fn visit_item_mod_mut(&mut self, module: &mut syn::ItemMod) { + self.current_path.push(module.ident.to_string()); + syn::visit_mut::visit_item_mod_mut(self, module); + self.current_path.pop(); + } + }; +} + +pub(crate) use tracking; diff --git a/src/processor/reaper.rs b/src/processor/reaper.rs index 8652428..3b16ead 100644 --- a/src/processor/reaper.rs +++ b/src/processor/reaper.rs @@ -2,9 +2,12 @@ use crate::build::Build; -use super::{files::Changes, Minimizer, ProcessState, Processor, SourceFile}; +use super::{ + files::Changes, tracking, Minimizer, PassController, ProcessState, Processor, SourceFile, +}; use anyhow::{ensure, Context, Result}; use proc_macro2::Span; +use quote::ToTokens; use rustfix::{diagnostics::Diagnostic, Suggestion}; use std::{ collections::{HashMap, HashSet}, @@ -120,14 +123,14 @@ impl Processor for DeleteUnusedFunctions { &mut self, krate: &mut syn::File, file: &SourceFile, - _: &mut super::ProcessChecker, + checker: &mut super::PassController, ) -> ProcessState { assert!( !self.invalid.contains(file), "processing with invalid state" ); - let mut visitor = FindUnusedFunction::new(file, self.diags.iter()); + let mut visitor = FindUnusedFunction::new(file, self.diags.iter(), checker); visitor.visit_file_mut(krate); if visitor.process_state == ProcessState::FileInvalidated { @@ -161,13 +164,19 @@ impl Unused { } } -struct FindUnusedFunction { +struct FindUnusedFunction<'a> { unused_functions: Vec, process_state: ProcessState, + current_path: Vec, + checker: &'a mut PassController, } -impl FindUnusedFunction { - fn new<'a>(file: &SourceFile, diags: impl Iterator) -> Self { +impl<'a> FindUnusedFunction<'a> { + fn new<'b>( + file: &SourceFile, + diags: impl Iterator, + checker: &'a mut PassController, + ) -> Self { let unused_functions = diags .filter_map(|diag| { // FIXME: use `code` correctly @@ -204,6 +213,8 @@ impl FindUnusedFunction { Self { unused_functions, process_state: ProcessState::NoChange, + current_path: Vec::new(), + checker, } } @@ -224,12 +235,15 @@ impl FindUnusedFunction { self.process_state = ProcessState::FileInvalidated; } - span_matches == 0 + span_matches == 0 && self.checker.can_process(&self.current_path) } } -impl VisitMut for FindUnusedFunction { +impl VisitMut for FindUnusedFunction<'_> { fn visit_item_impl_mut(&mut self, item_impl: &mut syn::ItemImpl) { + self.current_path + .push(item_impl.self_ty.clone().into_token_stream().to_string()); + item_impl.items.retain(|item| match item { ImplItem::Method(method) => { let span = method.sig.ident.span(); @@ -240,6 +254,8 @@ impl VisitMut for FindUnusedFunction { }); syn::visit_mut::visit_item_impl_mut(self, item_impl); + + self.current_path.pop(); } fn visit_file_mut(&mut self, krate: &mut syn::File) { @@ -256,6 +272,8 @@ impl VisitMut for FindUnusedFunction { } fn visit_item_mod_mut(&mut self, module: &mut syn::ItemMod) { + self.current_path.push(module.ident.to_string()); + if let Some((_, content)) = &mut module.content { content.retain(|item| match item { Item::Fn(func) => { @@ -268,5 +286,10 @@ impl VisitMut for FindUnusedFunction { } syn::visit_mut::visit_item_mod_mut(self, module); + + self.current_path.pop(); } + + tracking!(visit_item_fn_mut); + tracking!(visit_impl_item_method_mut); }