Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ anyhow = "1.0.65"
clap = { version = "4.0.29", features = ["derive"] }
ctrlc = "3.2.5"
genemichaels = "0.1.21"
markdown = { version = "=1.0.0-alpha.14" } # pinning the version to ensure genemichaels builds.
libloading = "0.8.0"
owo-colors = "3.5.0"
proc-macro2 = { version = "1.0.48", features = ["span-locations"] }
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# cargo-minimize

Install with `cargo install --git https://github.com/Nilstrieb/cargo-minimize cargo-minimize` and use with `cargo minimize`.
Install with `cargo install --git https://github.com/Noratrieb/cargo-minimize cargo-minimize` and use with `cargo minimize`.

For more info, see the [cookbook](https://github.com/Nilstrieb/cargo-minimize#cookbook).
For more info, see the [cookbook](https://github.com/Noratrieb/cargo-minimize#cookbook).

## Idea

Expand Down
8 changes: 8 additions & 0 deletions full-tests/nested-items.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
pub mod foo {
/// ~MINIMIZE-ROOT good
pub fn good(){}
/// ~REQUIRE-DELETED bad
pub fn bad(){}
}
/// ~MINIMIZE-ROOT main
fn main(){}
24 changes: 24 additions & 0 deletions full-tests/nested-items2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// this should all get deleted in a single swoop *and* not panic about it
/// ~REQUIRE-DELETED l1
mod l1 {
mod l2 {
mod l3 {
mod l4{
mod l5 {
fn foo(){}
fn bar(){}
mod l6 {
fn x1(){}
}
fn x2(){}
}
}
mod l4_2 {
fn y(){}
}
}
}
fn x8(){}
}
/// ~MINIMIZE-ROOT main
fn main(){}
12 changes: 12 additions & 0 deletions full-tests/reexports.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

use hello::{thingy, whatever};
mod hello{
pub fn thingy(){}
/// ~REQUIRE-DELETED whatever
pub fn whatever(){}
}

fn main(){
"~MINIMIZE-ROOT let x = thingy";
let x = thingy();
}
15 changes: 15 additions & 0 deletions full-tests/reexports2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
mod A {
/// ~REQUIRE-DELETED S1
pub struct S1;
pub struct S2;
}

mod B {
use crate::A::{self, S1};
pub use A::S2 as thingy;
}

fn main() {
"~MINIMIZE-ROOT let x = B::thingy";
let x = B::thingy;
}
3 changes: 2 additions & 1 deletion src/dylib_flag.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ impl FromStr for RustFunction {
type Err = anyhow::Error;

fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::compile(s).context("compiling and loading rust function")
Self::compile(s)
.map_err(|e| anyhow::format_err!("compiling and loading rust function: {:?}", e))
}
}

Expand Down
10 changes: 8 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ mod expand;

use anyhow::{Context, Result};
use dylib_flag::RustFunction;
use processor::Minimizer;
use processor::{Minimizer, PassSelection};
use tracing::Level;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Registry};

Expand Down Expand Up @@ -83,7 +83,7 @@ pub struct Options {

/// A comma-seperated list of passes that should be enabled. By default, all passes are enabled.
#[arg(long)]
pub passes: Option<String>,
pub passes: Option<PassSelection>,

/// A path to a script that is run to check whether code reproduces. When it exits with code 0, the
/// problem reproduces. If `--script-path-lints` isn't set, this script is also run to get lints.
Expand All @@ -105,6 +105,10 @@ pub struct Options {

#[arg(skip)]
pub no_delete_functions: bool,

/// Remove individual use statements manually, instead of relying on rustc lints output
#[arg(long)]
pub bisect_delete_imports: bool,
}

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -142,6 +146,7 @@ pub fn minimize(options: Options, stop: Arc<AtomicBool>) -> Result<()> {

minimizer.run_passes([
passes::EverybodyLoops::default().boxed(),
passes::SplitUse::default().boxed(),
passes::FieldDeleter::default().boxed(),
passes::Privatize::default().boxed(),
])?;
Expand Down Expand Up @@ -186,6 +191,7 @@ impl Default for Options {
script_path_lints: None,
ignore_file: Vec::new(),
no_delete_functions: false,
bisect_delete_imports: false,
}
}
}
15 changes: 12 additions & 3 deletions src/passes/item_deleter.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use quote::ToTokens;
use syn::{
visit_mut::VisitMut, Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn, ItemMacro, ItemMacro2,
ItemMod, ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType, ItemUnion, Signature,
ItemMod, ItemStatic, ItemStruct, ItemTrait, ItemTraitAlias, ItemType, ItemUnion, ItemUse,
Signature,
};

use crate::processor::{tracking, Pass, PassController, ProcessState, SourceFile};
Expand Down Expand Up @@ -73,9 +74,17 @@ impl<'a> Visitor<'a> {
self.current_path.pop();
should_retain
}
// We would hope for the unused imports pass to catch all of these
// but sadly that's not the case
Item::Use(ItemUse { tree, .. }) if self.checker.options.bisect_delete_imports => {
self.current_path.push(tree.to_token_stream().to_string());

let should_retain = self.should_retain_item();

self.current_path.pop();
should_retain
}
Item::ForeignMod(_) => true,
// We hope for the unused imports to show them all.
Item::Use(_) => true,
Item::Verbatim(_) => true,
_ => true,
}
Expand Down
3 changes: 2 additions & 1 deletion src/passes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ mod everybody_loops;
mod field_deleter;
mod item_deleter;
mod privatize;
mod split_use;

pub use self::{
everybody_loops::EverybodyLoops, field_deleter::FieldDeleter, item_deleter::ItemDeleter,
privatize::Privatize,
privatize::Privatize, split_use::SplitUse,
};
20 changes: 20 additions & 0 deletions src/passes/privatize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,32 @@ impl<'a> Visitor<'a> {
impl VisitMut for Visitor<'_> {
fn visit_visibility_mut(&mut self, vis: &mut Visibility) {
if let Visibility::Public(_) = vis {
self.current_path.push("{{vis}}".to_string());
if self.checker.can_process(&self.current_path) {
self.process_state = ProcessState::Changed;
*vis = self.pub_crate.clone();
}
self.current_path.pop();
}
}
fn visit_item_mut(&mut self, item: &mut syn::Item) {
match item {
syn::Item::Use(u) => {
if let Visibility::Public(_) = u.vis {
let mut path = self.current_path.clone();
path.push(u.to_token_stream().to_string());
if self.checker.can_process(&path) {
self.process_state = ProcessState::Changed;
u.vis = self.pub_crate.clone();
}
path.pop();
}
return; // early return; do not walk the child items
}
_ => {}
}
syn::visit_mut::visit_item_mut(self, item);
}

tracking!();
}
Expand Down
Loading