use std::fmt::Write as _;
use std::path::PathBuf;
use crate::config::LintConfig;
use crate::linter::check::check_source;
use crate::linter::fix::apply_fixes;
use crate::linter::render::{OutputMode, render_findings};
use crate::linter::rules::Rule;
fn example_path() -> PathBuf {
PathBuf::from("example.jl")
}
pub fn render_rule_doc(rule: &dyn Rule) -> String {
let mut out = String::new();
let id = rule.id();
let _ = writeln!(out, "# `{id}`");
let description = rule.description().trim();
if !description.is_empty() {
let _ = writeln!(out);
let _ = writeln!(out, "{description}");
}
let config = LintConfig {
select: Some(vec![id.to_string()]),
..Default::default()
};
let path = example_path();
for example in rule.examples() {
let _ = writeln!(out);
if !example.caption.is_empty() {
let _ = writeln!(out, "{}", example.caption);
let _ = writeln!(out);
}
fenced(&mut out, "julia", example.source);
let report = check_source(Some(&path), example.source, &config);
let source = example.source.to_string();
let rendered = render_findings(&report.diagnostics, OutputMode::Pretty, false, &|p| {
(p == Some(path.as_path())).then(|| source.clone())
});
let _ = writeln!(out);
fenced(&mut out, "text", &rendered);
let fixed = apply_fixes(example.source, &report.diagnostics, false);
if fixed.output != example.source {
let _ = writeln!(out);
let _ = writeln!(out, "After applying the fix:");
let _ = writeln!(out);
fenced(&mut out, "julia", &fixed.output);
}
}
out
}
fn fenced(out: &mut String, lang: &str, body: &str) {
let _ = writeln!(out, "```{lang}");
let _ = out.write_str(body);
if !body.ends_with('\n') {
let _ = out.write_str("\n");
}
let _ = writeln!(out, "```");
}
pub fn documented_pages() -> Vec<(&'static str, String)> {
crate::linter::rules::all_rules()
.iter()
.filter(|rule| !rule.examples().is_empty())
.map(|rule| (rule.id(), render_rule_doc(rule.as_ref())))
.collect()
}