diff --git a/README.md b/README.md index e2e5626..6187b30 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,21 @@

🧼 DepClean

- -A Rust version of [Depcheck](https://github.com/depcheck/depcheck). It supports analyze ESM and require statement in your JS family files currently. +A Rust version of [depcheck]. It supports analyze ESM and require statement in your JS family files currently. ```js ["js", "mjs", "cjs", "jsx", "ts", "mts", "cts", "tsx"] ``` -My goal is to port the original Depcheck. +[depcheck] is a really awesome tool, you definitely should check it out first! + +This project is developed out of personal interest and is currently in the prototype stage. I want to + improve my Rust skill by investigating the feasibility of using [oxc]. If more people like it, I will continue to improve and enhance it, ideally to be a drop-in replacement for [depcheck]. + +## Quick Start -[DepCheck](https://github.com/depcheck/depcheck) is a really awesome tool, you definitely should check it out first! +```sh +npx depclean +``` ## Installation @@ -21,20 +27,28 @@ pnpm install depclean ## Usage ```sh -npx depclean +Usage: depclean [--path=ARG] + +Available options: + --path=ARG The path to run this command, will use the current directory if absent. + -h, --help Prints help information + -V, --version Prints version information ``` -## Add this to your CI +## Add to Github actions + +```yml -```sh -depclean ``` ## Credits -- [depcheck](https://github.com/depcheck/depcheck) -- [oxc](https://github.com/oxc-project/oxc) +- [depcheck] +- [oxc] ## LICENSE [MIT](./LICENSE) + +[oxc]: https://github.com/oxc-project/oxc +[depcheck]: https://github.com/depcheck/depcheck diff --git a/npm/depclean/README.md b/npm/depclean/README.md index 177df7c..6187b30 100644 --- a/npm/depclean/README.md +++ b/npm/depclean/README.md @@ -1,14 +1,21 @@

🧼 DepClean

-A Rust version of [Depcheck](https://github.com/depcheck/depcheck). It supports analyze ESM and require statement in your JS family files currently. +A Rust version of [depcheck]. It supports analyze ESM and require statement in your JS family files currently. ```js ["js", "mjs", "cjs", "jsx", "ts", "mts", "cts", "tsx"] ``` -My goal is to port the original Depcheck. +[depcheck] is a really awesome tool, you definitely should check it out first! -[DepCheck](https://github.com/depcheck/depcheck) is a really awesome tool, you definitely should check it out first! +This project is developed out of personal interest and is currently in the prototype stage. I want to + improve my Rust skill by investigating the feasibility of using [oxc]. If more people like it, I will continue to improve and enhance it, ideally to be a drop-in replacement for [depcheck]. + +## Quick Start + +```sh +npx depclean +``` ## Installation @@ -20,16 +27,28 @@ pnpm install depclean ## Usage ```sh -npx depclean +Usage: depclean [--path=ARG] + +Available options: + --path=ARG The path to run this command, will use the current directory if absent. + -h, --help Prints help information + -V, --version Prints version information ``` -## Add this to your CI +## Add to Github actions + +```yml -```sh -depcheck ``` ## Credits -- [depcheck](https://github.com/depcheck/depcheck) -- [oxc](https://github.com/oxc-project/oxc) +- [depcheck] +- [oxc] + +## LICENSE + +[MIT](./LICENSE) + +[oxc]: https://github.com/oxc-project/oxc +[depcheck]: https://github.com/depcheck/depcheck diff --git a/src/checkers/js.rs b/src/checkers/js.rs index 84a1d63..31dbb0f 100644 --- a/src/checkers/js.rs +++ b/src/checkers/js.rs @@ -31,7 +31,7 @@ impl Checker for JSFamily { continue; } if let Some(str) = - get_string_value(&call_expr.arguments[0].as_expression().unwrap()) + get_string_value(call_expr.arguments[0].as_expression().unwrap()) { if !is_bare_import(&str) { continue; @@ -62,7 +62,7 @@ fn is_global_require_call(call_expr: &CallExpression, ctx: &DepCheckerContext) - return ctx.semantic().is_reference_to_global_variable(ident); } - return false; + false } fn is_bare_import(s: &str) -> bool { diff --git a/src/lib.rs b/src/lib.rs index 12a6a13..a05972d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,12 +33,7 @@ impl DepClean { /// /// # Panics /// if package.json not found in the root directory - pub fn check(&mut self, root_path: &Path) -> FxHashSet { - let paths: FxHashSet> = Walk::new(root_path.to_path_buf()) - .paths() - .into_iter() - .collect(); - + pub fn check(&mut self, paths: &FxHashSet>) -> FxHashSet { let (sender, receiver) = std::sync::mpsc::channel::>(); paths @@ -73,21 +68,30 @@ impl DepClean { std::process::exit(1); } + let text = "Start checking...\n".dark_gray(); + println!("{text}"); + let mut builder = PackageJSONBuilder::new(); builder.with_package_json(&package_json_path); let mut package_json_container = builder.build(); - let used_deps = self.check(path); + let start = std::time::Instant::now(); + let paths: FxHashSet> = Walk::new(path).paths().into_iter().collect(); + + let used_deps = self.check(&paths); package_json_container.compute_unused_deps(&used_deps); let unused_deps = package_json_container.unused_dependencies(); + let elapsed = start.elapsed().as_millis(); if unused_deps.is_empty() { - let text = "No unused dependencies found, Good!".rainbow(); - println!("{:?}", text); + println!("{:?}", "No unused dependency, Good!".rainbow()); std::process::exit(0); } let dep_text = if unused_deps.len() > 1 { - let title = format!("{} dependencies unused in your project:", unused_deps.len(),); + let title = format!( + "Found {} unused dependencies:\n", + unused_deps.len(), + ); let body = unused_deps .iter() .map(|dep| format!(" - {}", dep)) @@ -102,7 +106,7 @@ impl DepClean { }; let footer = format!( - "\nRun `{} {}` to clean your codebase.", + "\nTo clean your codebase, run `{} {}` ", PkgManager::new_from_path(path).get_uninstall_cmd(), unused_deps .iter() @@ -112,6 +116,9 @@ impl DepClean { ) .green(); - println!("{dep_text}\n{}", footer); + let time_text = format!("Checked {} file(s) in {}ms.", paths.len(), elapsed).dark_gray(); + + println!("{dep_text}\n\n{}\n{}", time_text, footer); + std::process::exit(1); } } diff --git a/src/main.rs b/src/main.rs index dce6097..06ac3f8 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,7 +6,7 @@ use depclean::DepClean; #[derive(Clone, Debug, Bpaf)] #[bpaf(options, version)] struct DepCleanOptions { - /// The path to run this command. If absent, it will run in the current directory. + /// The path to run this command, will use the current directory if absent. path: Option, } diff --git a/src/runtime.rs b/src/runtime.rs index c2cfed9..24e1469 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -89,11 +89,13 @@ impl Runtime { /// We will get `["b/foo.mjs", "c"]` pub fn check_js_files(&self, path: &Path) -> Vec { let Ok(source_type) = SourceType::from_path(path) else { + #[cfg(debug_assertions)] eprintln!("Unsupported file type: {:?}", path); return vec![]; }; let Ok(source_text) = fs::read_to_string(path) else { + #[cfg(debug_assertions)] eprintln!("Failed to read file: {:?}", path); return vec![]; }; diff --git a/src/walk.rs b/src/walk.rs index 7f0dae5..682b77b 100644 --- a/src/walk.rs +++ b/src/walk.rs @@ -1,4 +1,4 @@ -use std::path::{Path, PathBuf}; +use std::path::Path; use ignore::{ParallelVisitorBuilder, WalkBuilder, WalkParallel}; @@ -7,7 +7,7 @@ pub(crate) struct Walk { } impl Walk { - pub fn new(path: PathBuf) -> Self { + pub fn new(path: &Path) -> Self { let walker = WalkBuilder::new(path); let walk = walker.build_parallel(); Self { inner: walk } diff --git a/tests/fixtures/simple/depclean b/tests/fixtures/simple/depclean index 08f0f44..0c4452d 100755 Binary files a/tests/fixtures/simple/depclean and b/tests/fixtures/simple/depclean differ diff --git a/tests/fixtures/simple/package.json b/tests/fixtures/simple/package.json index 5c1873e..67051fc 100644 --- a/tests/fixtures/simple/package.json +++ b/tests/fixtures/simple/package.json @@ -11,6 +11,7 @@ "description": "", "dependencies": { "react": "^18.3.1", - "react-dom": "^18.3.1" + "react-dom": "^18.3.1", + "b": "123" } }