Skip to main content

cargo_shed/
lib.rs

1//! Static dependency health checks for Rust projects.
2//!
3//! `cargo-shed` reads a project's manifest, lockfile, and Rust sources without
4//! compiling the project or running build scripts. The main entry point is
5//! [`analyze`]. Safe edits are available through [`apply_fixes`].
6//!
7//! ```no_run
8//! use cargo_shed::{Config, OutputFormat, analyze};
9//!
10//! let report = analyze(Config {
11//!     manifest_path: Some("Cargo.toml".into()),
12//!     format: OutputFormat::Json,
13//!     ..Config::default()
14//! })?;
15//!
16//! println!("{}", report.to_json()?);
17//! # Ok::<(), Box<dyn std::error::Error>>(())
18//! ```
19
20pub mod cli;
21pub mod error;
22pub mod explain;
23pub mod fix;
24pub mod issue;
25pub mod lockfile;
26pub mod manifest;
27pub mod project;
28pub mod report;
29pub mod rules;
30pub mod scan;
31
32use camino::Utf8PathBuf;
33use serde::{Deserialize, Serialize};
34
35pub use error::ShedError;
36pub use fix::{Edit, Fix, FixReport, FixSafety, apply_fixes};
37pub use issue::{Evidence, Issue, Severity, Suggestion};
38pub use lockfile::{LockDependency, LockPackage, Lockfile};
39pub use manifest::{Dependency, DependencySection, Manifest};
40pub use project::{Project, ProjectKind};
41pub use report::Report;
42pub use rules::Rule;
43pub use scan::{SourceFile, SourceIndex};
44
45/// Output encoding for reports produced by the CLI and library helpers.
46#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
47#[serde(rename_all = "kebab-case")]
48pub enum OutputFormat {
49    /// Human-readable terminal output.
50    Human,
51    /// Stable JSON output for machines and CI integrations.
52    Json,
53}
54
55/// Runtime configuration for project analysis and safe fix application.
56#[derive(Debug, Clone, PartialEq, Eq)]
57pub struct Config {
58    /// Path to `Cargo.toml`, or a directory containing it.
59    pub manifest_path: Option<Utf8PathBuf>,
60    /// Whether the CLI should apply safe fixes instead of only reporting.
61    pub fix: bool,
62    /// Whether medium and high severity findings should fail CI.
63    pub check: bool,
64    /// Output format requested by the caller.
65    pub format: OutputFormat,
66    /// Optional rule or issue id to fix.
67    pub selected_rule: Option<String>,
68    /// Disable terminal color when supported by renderers.
69    pub no_color: bool,
70    /// Enable additional diagnostic output when supported.
71    pub verbose: bool,
72}
73
74impl Default for Config {
75    fn default() -> Self {
76        Self {
77            manifest_path: None,
78            fix: false,
79            check: false,
80            format: OutputFormat::Human,
81            selected_rule: None,
82            no_color: false,
83            verbose: false,
84        }
85    }
86}
87
88pub fn analyze(config: Config) -> Result<Report, ShedError> {
89    let project = Project::load(config.manifest_path.as_ref())?;
90    let issues = rules::run_all(&project);
91    let skipped_checks = project.skipped_checks();
92    Ok(Report::new(project.root, issues, skipped_checks))
93}