1pub 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#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
47#[serde(rename_all = "kebab-case")]
48pub enum OutputFormat {
49 Human,
51 Json,
53}
54
55#[derive(Debug, Clone, PartialEq, Eq)]
57pub struct Config {
58 pub manifest_path: Option<Utf8PathBuf>,
60 pub fix: bool,
62 pub check: bool,
64 pub format: OutputFormat,
66 pub selected_rule: Option<String>,
68 pub no_color: bool,
70 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}