Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen committed Mar 18, 2024
1 parent f40bdc1 commit 22ee52c
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 43 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ cargo_metadata = "0.18.1"
cargo_toml = "0.19.2"
bpaf = { version = "0.9.9", features = ["derive", "batteries"] }
proc-macro2 = {version="1", features = ["span-locations"]}
syn = { version = "2", features = ["full", "visit", "extra-traits"] }
syn = { version = "2", features = ["full", "visit" ] } # add "extra-traits" to debug syn ast
regex = "1.10.3"
rayon = "1.9.0"
toml_edit = { version = "0.22.7", features = ["parse"] }
Expand Down
88 changes: 46 additions & 42 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,25 +52,21 @@ impl CargoShear {
#[must_use]
pub fn run(self) -> ExitCode {
match self.shear() {
Ok(unused_dependencies) => {
if unused_dependencies == 0 {
ExitCode::from(0)
} else {
ExitCode::from(1)
}
}
Ok(0) => ExitCode::from(0),
Ok(_) => ExitCode::from(1),
Err(err) => {
println!("{err}");
ExitCode::from(2)
}
}
}

/// Returns the number of unused dependencies.
fn shear(&self) -> Result<usize> {
let metadata = MetadataCommand::new().current_dir(&self.options.path).exec()?;
let workspace_root = metadata.workspace_root.as_std_path();

let all_pkg_deps = metadata
let packages = metadata
.workspace_packages()
.par_iter()
.map(|package| self.shear_package(workspace_root, package))
Expand All @@ -81,11 +77,11 @@ impl CargoShear {
unused_dependencies: a.unused_dependencies + b.unused_dependencies,
});

let unused_dependencies = self.shear_workspace(&metadata, &all_pkg_deps.dependencies)?;

Ok(unused_dependencies + all_pkg_deps.unused_dependencies)
let unused_dependencies = self.shear_workspace(&metadata, &packages.dependencies)?;
Ok(unused_dependencies + packages.unused_dependencies)
}

/// Returns the number of unused dependencies.
fn shear_workspace(&self, metadata: &Metadata, all_pkg_deps: &Deps) -> Result<usize> {
if metadata.workspace_packages().len() <= 1 {
return Ok(0);
Expand All @@ -106,41 +102,14 @@ impl CargoShear {
Ok(unused_deps.len())
}

/// Returns the remaining dependencies
/// Returns the remaining dependencies and number of unused dependencies.
fn shear_package(&self, workspace_root: &Path, package: &Package) -> Result<ShearedPackage> {
let dir = package
.manifest_path
.parent()
.unwrap_or_else(|| panic!("failed to get parent path {}", &package.manifest_path))
.as_std_path();

let rust_file_paths = package
.targets
.iter()
.flat_map(|target| {
if target.kind.iter().any(|s| s == "custom-build") {
vec![target.src_path.clone().into_std_path_buf()]
} else {
let target_dir = target.src_path.parent().unwrap_or_else(|| {
panic!("failed to get parentp path {}", &target.src_path)
});
WalkDir::new(target_dir)
.into_iter()
.filter_map(Result::ok)
.filter(|e| e.path().extension().is_some_and(|ext| ext == "rs"))
.map(DirEntry::into_path)
.collect::<Vec<_>>()
}
})
.collect::<HashSet<_>>();

let rust_file_deps = rust_file_paths
.par_iter()
.map(|path| Self::process_rust_source(path))
.collect::<Result<Vec<Deps>>>()?
.into_iter()
.fold(HashSet::new(), |a, b| a.union(&b).cloned().collect());

let dependency_names =
package.dependencies.iter().map(Self::dependency_name).collect::<Deps>();

Expand All @@ -154,17 +123,19 @@ impl CargoShear {
.collect::<HashMap<String, String>>();

let mod_names = package_deps_map.keys().cloned().collect::<HashSet<_>>();
let rust_file_deps = Self::get_package_dependencies_from_rust_files(package)?;
let unused_deps = mod_names.difference(&rust_file_deps).collect::<Vec<_>>();

if unused_deps.is_empty() {
return Ok(ShearedPackage { dependencies: dependency_names, unused_dependencies: 0 });
}

let unused_dep_names =
unused_deps.into_iter().map(|name| package_deps_map[name].clone()).collect::<Vec<_>>();
self.try_fix_package(package.manifest_path.as_std_path(), &unused_dep_names)?;

let path = dir.strip_prefix(workspace_root).unwrap_or(dir);
println!("{path:?}: {unused_dep_names:?}");
self.try_fix_package(package.manifest_path.as_std_path(), &unused_dep_names)?;

let unused_dependencies = unused_dep_names.len();
let dependency_names = dependency_names
.difference(&HashSet::from_iter(unused_dep_names))
Expand All @@ -173,6 +144,37 @@ impl CargoShear {
Ok(ShearedPackage { dependencies: dependency_names, unused_dependencies })
}

fn get_package_dependencies_from_rust_files(package: &Package) -> Result<Deps> {
Ok(Self::get_package_rust_files(package)
.par_iter()
.map(|path| Self::process_rust_source(path))
.collect::<Result<Vec<Deps>>>()?
.into_iter()
.fold(HashSet::new(), |a, b| a.union(&b).cloned().collect()))
}

fn get_package_rust_files(package: &Package) -> Vec<PathBuf> {
package
.targets
.iter()
.flat_map(|target| {
if target.kind.iter().any(|s| s == "custom-build") {
vec![target.src_path.clone().into_std_path_buf()]
} else {
let target_dir = target.src_path.parent().unwrap_or_else(|| {
panic!("failed to get parentp path {}", &target.src_path)
});
WalkDir::new(target_dir)
.into_iter()
.filter_map(Result::ok)
.filter(|e| e.path().extension().is_some_and(|ext| ext == "rs"))
.map(DirEntry::into_path)
.collect::<Vec<_>>()
}
})
.collect()
}

fn dependency_name(dependency: &Dependency) -> String {
dependency.rename.as_ref().unwrap_or(&dependency.name).clone()
}
Expand All @@ -191,6 +193,7 @@ impl CargoShear {
let manifest = fs::read_to_string(cargo_toml_path)?;
let mut manifest = toml_edit::DocumentMut::from_str(&manifest)?;

// Try `[workspace.dependencies]`
if let Some(dependencies) = manifest
.get_mut("workspace")
.and_then(|item| item.as_table_mut())
Expand All @@ -202,6 +205,7 @@ impl CargoShear {
}
}

// Try `[dependencies]`, `[dev-dependencies]`, `[build-dependencies]`
for table_name in ["dependencies", "dev-dependencies", "build-dependencies"] {
if let Some(dependencies) =
manifest.get_mut(table_name).and_then(|item| item.as_table_mut())
Expand All @@ -213,7 +217,7 @@ impl CargoShear {
}

let serialized = manifest.to_string();
fs::write(cargo_toml_path, serialized).expect("Cargo.toml write error");
fs::write(cargo_toml_path, serialized)?;
Ok(())
}
}

0 comments on commit 22ee52c

Please sign in to comment.