mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-28 21:05:08 +00:00

## Summary We treat these rules as `preview` elsewhere, so adding `preview: false` to the JSON and such seems like an error. Closes https://github.com/astral-sh/ruff/issues/7804.
118 lines
3.4 KiB
Rust
118 lines
3.4 KiB
Rust
use std::io::{self, BufWriter, Write};
|
|
|
|
use anyhow::Result;
|
|
use serde::ser::SerializeSeq;
|
|
use serde::{Serialize, Serializer};
|
|
use strum::IntoEnumIterator;
|
|
|
|
use ruff_diagnostics::FixAvailability;
|
|
use ruff_linter::registry::{Linter, Rule, RuleNamespace};
|
|
|
|
use crate::args::HelpFormat;
|
|
|
|
#[derive(Serialize)]
|
|
struct Explanation<'a> {
|
|
name: &'a str,
|
|
code: String,
|
|
linter: &'a str,
|
|
summary: &'a str,
|
|
message_formats: &'a [&'a str],
|
|
fix: String,
|
|
explanation: Option<&'a str>,
|
|
preview: bool,
|
|
}
|
|
|
|
impl<'a> Explanation<'a> {
|
|
fn from_rule(rule: &'a Rule) -> Self {
|
|
let code = rule.noqa_code().to_string();
|
|
let (linter, _) = Linter::parse_code(&code).unwrap();
|
|
let fix = rule.fixable().to_string();
|
|
Self {
|
|
name: rule.as_ref(),
|
|
code,
|
|
linter: linter.name(),
|
|
summary: rule.message_formats()[0],
|
|
message_formats: rule.message_formats(),
|
|
fix,
|
|
explanation: rule.explanation(),
|
|
preview: rule.is_preview() || rule.is_nursery(),
|
|
}
|
|
}
|
|
}
|
|
|
|
fn format_rule_text(rule: Rule) -> String {
|
|
let mut output = String::new();
|
|
output.push_str(&format!("# {} ({})", rule.as_ref(), rule.noqa_code()));
|
|
output.push('\n');
|
|
output.push('\n');
|
|
|
|
let (linter, _) = Linter::parse_code(&rule.noqa_code().to_string()).unwrap();
|
|
output.push_str(&format!("Derived from the **{}** linter.", linter.name()));
|
|
output.push('\n');
|
|
output.push('\n');
|
|
|
|
let fix_availability = rule.fixable();
|
|
if matches!(
|
|
fix_availability,
|
|
FixAvailability::Always | FixAvailability::Sometimes
|
|
) {
|
|
output.push_str(&fix_availability.to_string());
|
|
output.push('\n');
|
|
output.push('\n');
|
|
}
|
|
|
|
if rule.is_preview() || rule.is_nursery() {
|
|
output.push_str(
|
|
r#"This rule is in preview and is not stable. The `--preview` flag is required for use."#,
|
|
);
|
|
output.push('\n');
|
|
output.push('\n');
|
|
}
|
|
|
|
if let Some(explanation) = rule.explanation() {
|
|
output.push_str(explanation.trim());
|
|
} else {
|
|
output.push_str("Message formats:");
|
|
for format in rule.message_formats() {
|
|
output.push('\n');
|
|
output.push_str(&format!("* {format}"));
|
|
}
|
|
}
|
|
output
|
|
}
|
|
|
|
/// Explain a `Rule` to the user.
|
|
pub(crate) fn rule(rule: Rule, format: HelpFormat) -> Result<()> {
|
|
let mut stdout = BufWriter::new(io::stdout().lock());
|
|
match format {
|
|
HelpFormat::Text => {
|
|
writeln!(stdout, "{}", format_rule_text(rule))?;
|
|
}
|
|
HelpFormat::Json => {
|
|
serde_json::to_writer_pretty(stdout, &Explanation::from_rule(&rule))?;
|
|
}
|
|
};
|
|
Ok(())
|
|
}
|
|
|
|
/// Explain all rules to the user.
|
|
pub(crate) fn rules(format: HelpFormat) -> Result<()> {
|
|
let mut stdout = BufWriter::new(io::stdout().lock());
|
|
match format {
|
|
HelpFormat::Text => {
|
|
for rule in Rule::iter() {
|
|
writeln!(stdout, "{}", format_rule_text(rule))?;
|
|
writeln!(stdout)?;
|
|
}
|
|
}
|
|
HelpFormat::Json => {
|
|
let mut serializer = serde_json::Serializer::pretty(stdout);
|
|
let mut seq = serializer.serialize_seq(None)?;
|
|
for rule in Rule::iter() {
|
|
seq.serialize_element(&Explanation::from_rule(&rule))?;
|
|
}
|
|
seq.end()?;
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|