This commit is contained in:
nora 2022-12-17 23:35:40 +01:00
parent 865d8a7bc9
commit a36bf95c3e
4 changed files with 106 additions and 53 deletions

View file

@ -1,18 +1,18 @@
use quote::ToTokens; use quote::ToTokens;
use syn::{parse_quote, visit_mut::VisitMut}; 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> { struct Visitor<'a> {
current_path: Vec<String>, current_path: Vec<String>,
checker: &'a mut ProcessChecker, checker: &'a mut PassController,
loop_expr: syn::Block, loop_expr: syn::Block,
process_state: ProcessState, process_state: ProcessState,
} }
impl<'a> Visitor<'a> { impl<'a> Visitor<'a> {
fn new(checker: &'a mut ProcessChecker) -> Self { fn new(checker: &'a mut PassController) -> Self {
Self { Self {
current_path: Vec::new(), current_path: Vec::new(),
checker, checker,
@ -35,30 +35,7 @@ impl VisitMut for Visitor<'_> {
} }
} }
fn visit_item_fn_mut(&mut self, func: &mut syn::ItemFn) { tracking!();
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();
}
} }
#[derive(Default)] #[derive(Default)]
@ -69,7 +46,7 @@ impl Processor for EverybodyLoops {
&mut self, &mut self,
krate: &mut syn::File, krate: &mut syn::File,
_: &SourceFile, _: &SourceFile,
checker: &mut ProcessChecker, checker: &mut PassController,
) -> ProcessState { ) -> ProcessState {
let mut visitor = Visitor::new(checker); let mut visitor = Visitor::new(checker);
visitor.visit_file_mut(krate); visitor.visit_file_mut(krate);

View file

@ -1,36 +1,50 @@
use quote::ToTokens;
use syn::{parse_quote, visit_mut::VisitMut, Visibility}; 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, pub_crate: Visibility,
process_state: ProcessState, process_state: ProcessState,
current_path: Vec<String>,
checker: &'a mut PassController,
} }
impl Visitor { impl<'a> Visitor<'a> {
fn new() -> Self { fn new(checker: &'a mut PassController) -> Self {
Self { Self {
process_state: ProcessState::NoChange, process_state: ProcessState::NoChange,
pub_crate: parse_quote! { pub(crate) }, 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) { fn visit_visibility_mut(&mut self, vis: &mut Visibility) {
if let Visibility::Public(_) = vis { if let Visibility::Public(_) = vis {
self.process_state = ProcessState::Changed; if self.checker.can_process(&self.current_path) {
*vis = self.pub_crate.clone(); self.process_state = ProcessState::Changed;
*vis = self.pub_crate.clone();
}
} }
} }
tracking!();
} }
#[derive(Default)] #[derive(Default)]
pub struct Privatize {} pub struct Privatize {}
impl Processor for Privatize { impl Processor for Privatize {
fn process_file(&mut self, krate: &mut syn::File, _: &SourceFile, _: &mut ProcessChecker) -> ProcessState { fn process_file(
let mut visitor = Visitor::new(); &mut self,
krate: &mut syn::File,
_: &SourceFile,
checker: &mut PassController,
) -> ProcessState {
let mut visitor = Visitor::new(checker);
visitor.visit_file_mut(krate); visitor.visit_file_mut(krate);
visitor.process_state visitor.process_state
} }

View file

@ -21,7 +21,7 @@ pub trait Processor {
&mut self, &mut self,
krate: &mut syn::File, krate: &mut syn::File,
file: &SourceFile, file: &SourceFile,
checker: &mut ProcessChecker, checker: &mut PassController,
) -> ProcessState; ) -> ProcessState;
fn name(&self) -> &'static str; fn name(&self) -> &'static str;
@ -88,7 +88,7 @@ impl Minimizer {
let mut refresh_and_try_again = false; let mut refresh_and_try_again = false;
'pass: loop { loop {
println!("Starting a round of {}", pass.name()); println!("Starting a round of {}", pass.name());
let mut changes = Changes::default(); let mut changes = Changes::default();
@ -104,7 +104,7 @@ impl Minimizer {
let mut krate = syn::parse_file(change.before_content()) let mut krate = syn::parse_file(change.before_content())
.with_context(|| format!("parsing file {file_display}"))?; .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 { match has_made_change {
ProcessState::Changed | ProcessState::FileInvalidated => { ProcessState::Changed | ProcessState::FileInvalidated => {
@ -143,20 +143,59 @@ impl Minimizer {
} }
println!("Finished {}", pass.name()); println!("Finished {}", pass.name());
break 'pass; return Ok(());
} else { } else {
refresh_and_try_again = false; refresh_and_try_again = false;
} }
} }
Ok(())
} }
} }
pub struct ProcessChecker {} pub struct PassController {}
impl ProcessChecker { impl PassController {
pub fn can_process(&mut self, _: &[String]) -> bool { pub fn can_process(&mut self, _: &[String]) -> bool {
// FIXME: Actually do smart things here.
true 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;

View file

@ -2,9 +2,12 @@
use crate::build::Build; 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 anyhow::{ensure, Context, Result};
use proc_macro2::Span; use proc_macro2::Span;
use quote::ToTokens;
use rustfix::{diagnostics::Diagnostic, Suggestion}; use rustfix::{diagnostics::Diagnostic, Suggestion};
use std::{ use std::{
collections::{HashMap, HashSet}, collections::{HashMap, HashSet},
@ -120,14 +123,14 @@ impl Processor for DeleteUnusedFunctions {
&mut self, &mut self,
krate: &mut syn::File, krate: &mut syn::File,
file: &SourceFile, file: &SourceFile,
_: &mut super::ProcessChecker, checker: &mut super::PassController,
) -> ProcessState { ) -> ProcessState {
assert!( assert!(
!self.invalid.contains(file), !self.invalid.contains(file),
"processing with invalid state" "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); visitor.visit_file_mut(krate);
if visitor.process_state == ProcessState::FileInvalidated { if visitor.process_state == ProcessState::FileInvalidated {
@ -161,13 +164,19 @@ impl Unused {
} }
} }
struct FindUnusedFunction { struct FindUnusedFunction<'a> {
unused_functions: Vec<Unused>, unused_functions: Vec<Unused>,
process_state: ProcessState, process_state: ProcessState,
current_path: Vec<String>,
checker: &'a mut PassController,
} }
impl FindUnusedFunction { impl<'a> FindUnusedFunction<'a> {
fn new<'a>(file: &SourceFile, diags: impl Iterator<Item = &'a Diagnostic>) -> Self { fn new<'b>(
file: &SourceFile,
diags: impl Iterator<Item = &'b Diagnostic>,
checker: &'a mut PassController,
) -> Self {
let unused_functions = diags let unused_functions = diags
.filter_map(|diag| { .filter_map(|diag| {
// FIXME: use `code` correctly // FIXME: use `code` correctly
@ -204,6 +213,8 @@ impl FindUnusedFunction {
Self { Self {
unused_functions, unused_functions,
process_state: ProcessState::NoChange, process_state: ProcessState::NoChange,
current_path: Vec::new(),
checker,
} }
} }
@ -224,12 +235,15 @@ impl FindUnusedFunction {
self.process_state = ProcessState::FileInvalidated; 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) { 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 { item_impl.items.retain(|item| match item {
ImplItem::Method(method) => { ImplItem::Method(method) => {
let span = method.sig.ident.span(); let span = method.sig.ident.span();
@ -240,6 +254,8 @@ impl VisitMut for FindUnusedFunction {
}); });
syn::visit_mut::visit_item_impl_mut(self, item_impl); syn::visit_mut::visit_item_impl_mut(self, item_impl);
self.current_path.pop();
} }
fn visit_file_mut(&mut self, krate: &mut syn::File) { 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) { 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 { if let Some((_, content)) = &mut module.content {
content.retain(|item| match item { content.retain(|item| match item {
Item::Fn(func) => { Item::Fn(func) => {
@ -268,5 +286,10 @@ impl VisitMut for FindUnusedFunction {
} }
syn::visit_mut::visit_item_mod_mut(self, module); syn::visit_mut::visit_item_mod_mut(self, module);
self.current_path.pop();
} }
tracking!(visit_item_fn_mut);
tracking!(visit_impl_item_method_mut);
} }