1use std::process::ExitCode;
8
9use colored::Colorize;
10use fallow_config::OutputFormat;
11
12pub use fallow_api::{
13 CHECK_RULES, DUPES_RULES, FLAGS_RULES, HEALTH_RULES, RuleDef, RuleGuide, SECURITY_RULES,
14 coverage_analyze_meta, coverage_setup_meta, rule_by_id, rule_by_token, rule_docs_url,
15 rule_guide, security_meta, serialize_explain_programmatic_json,
16};
17
18#[must_use]
20pub fn run_explain(issue_type: &str, output: OutputFormat) -> ExitCode {
21 let Some(rule) = rule_by_token(issue_type) else {
22 return crate::error::emit_error(
23 &fallow_api::unknown_explain_error(issue_type).message,
24 2,
25 output,
26 );
27 };
28 let guide = rule_guide(rule);
29 match output {
30 OutputFormat::Json => match serialize_explain_programmatic_json(
31 issue_type,
32 crate::output_runtime::current_root_envelope_mode(),
33 crate::output_runtime::telemetry_analysis_run_id().as_deref(),
34 ) {
35 Ok(value) => crate::report::emit_json(&value, "explain"),
36 Err(error) => crate::error::emit_error(&error.message, error.exit_code, output),
37 },
38 OutputFormat::Human => print_explain_human(rule, &guide),
39 OutputFormat::Compact => print_explain_compact(rule),
40 OutputFormat::Markdown => print_explain_markdown(rule, &guide),
41 OutputFormat::Sarif
42 | OutputFormat::CodeClimate
43 | OutputFormat::PrCommentGithub
44 | OutputFormat::PrCommentGitlab
45 | OutputFormat::ReviewGithub
46 | OutputFormat::ReviewGitlab
47 | OutputFormat::Badge => crate::error::emit_error(
48 "explain supports human, compact, markdown, and json output",
49 2,
50 output,
51 ),
52 }
53}
54
55fn print_explain_human(rule: &RuleDef, guide: &RuleGuide) -> ExitCode {
56 println!("{}", rule.name.bold());
57 println!("{}", rule.id.dimmed());
58 println!();
59 println!("{}", rule.short);
60 println!();
61 println!("{}", "Why it matters".bold());
62 println!("{}", rule.full);
63 println!();
64 println!("{}", "Example".bold());
65 println!("{}", guide.example);
66 println!();
67 println!("{}", "How to fix".bold());
68 println!("{}", guide.how_to_fix);
69 println!();
70 println!("{} {}", "Docs:".dimmed(), rule_docs_url(rule).dimmed());
71 ExitCode::SUCCESS
72}
73
74fn print_explain_compact(rule: &RuleDef) -> ExitCode {
75 println!("explain:{}:{}:{}", rule.id, rule.short, rule_docs_url(rule));
76 ExitCode::SUCCESS
77}
78
79fn print_explain_markdown(rule: &RuleDef, guide: &RuleGuide) -> ExitCode {
80 println!("# {}", rule.name);
81 println!();
82 println!("`{}`", rule.id);
83 println!();
84 println!("{}", rule.short);
85 println!();
86 println!("## Why it matters");
87 println!();
88 println!("{}", rule.full);
89 println!();
90 println!("## Example");
91 println!();
92 println!("{}", guide.example);
93 println!();
94 println!("## How to fix");
95 println!();
96 println!("{}", guide.how_to_fix);
97 println!();
98 println!("[Docs]({})", rule_docs_url(rule));
99 ExitCode::SUCCESS
100}