mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-07 13:15:06 +00:00

**Summary** Mostly mechanical symbol rename and search-and-replace, with small changes to the markdown docs to read better
139 lines
4.8 KiB
Rust
139 lines
4.8 KiB
Rust
//! Generate a Markdown-compatible table of supported lint rules.
|
|
//!
|
|
//! Used for <https://docs.astral.sh/ruff/rules/>.
|
|
|
|
use itertools::Itertools;
|
|
use strum::IntoEnumIterator;
|
|
|
|
use ruff_diagnostics::FixKind;
|
|
use ruff_linter::registry::{Linter, Rule, RuleNamespace};
|
|
use ruff_linter::upstream_categories::UpstreamCategoryAndPrefix;
|
|
use ruff_workspace::options::Options;
|
|
use ruff_workspace::options_base::OptionsMetadata;
|
|
|
|
const FIX_SYMBOL: &str = "🛠️";
|
|
const PREVIEW_SYMBOL: &str = "🧪";
|
|
|
|
fn generate_table(table_out: &mut String, rules: impl IntoIterator<Item = Rule>, linter: &Linter) {
|
|
table_out.push_str("| Code | Name | Message | |");
|
|
table_out.push('\n');
|
|
table_out.push_str("| ---- | ---- | ------- | ------: |");
|
|
table_out.push('\n');
|
|
for rule in rules {
|
|
let fix_token = match rule.fixable() {
|
|
FixKind::Always | FixKind::Sometimes => {
|
|
format!("<span style='opacity: 1'>{FIX_SYMBOL}</span>")
|
|
}
|
|
FixKind::None => format!("<span style='opacity: 0.1'>{FIX_SYMBOL}</span>"),
|
|
};
|
|
let preview_token = if rule.is_preview() || rule.is_nursery() {
|
|
format!("<span style='opacity: 1'>{PREVIEW_SYMBOL}</span>")
|
|
} else {
|
|
format!("<span style='opacity: 0.1'>{PREVIEW_SYMBOL}</span>")
|
|
};
|
|
let status_token = format!("{fix_token} {preview_token}");
|
|
|
|
let rule_name = rule.as_ref();
|
|
|
|
#[allow(clippy::or_fun_call)]
|
|
table_out.push_str(&format!(
|
|
"| {0}{1} {{ #{0}{1} }} | {2} | {3} | {4} |",
|
|
linter.common_prefix(),
|
|
linter.code_for_rule(rule).unwrap(),
|
|
rule.explanation()
|
|
.is_some()
|
|
.then_some(format_args!("[{rule_name}](rules/{rule_name}.md)"))
|
|
.unwrap_or(format_args!("{rule_name}")),
|
|
rule.message_formats()[0],
|
|
status_token,
|
|
));
|
|
table_out.push('\n');
|
|
}
|
|
table_out.push('\n');
|
|
}
|
|
|
|
pub(crate) fn generate() -> String {
|
|
// Generate the table string.
|
|
let mut table_out = String::new();
|
|
|
|
table_out.push_str(&format!(
|
|
"The {FIX_SYMBOL} emoji indicates that a rule is automatically fixable by the `--fix` command-line option."));
|
|
table_out.push('\n');
|
|
table_out.push('\n');
|
|
|
|
table_out.push_str(&format!(
|
|
"The {PREVIEW_SYMBOL} emoji indicates that a rule in [\"preview\"](faq.md#what-is-preview)."
|
|
));
|
|
table_out.push('\n');
|
|
table_out.push('\n');
|
|
|
|
for linter in Linter::iter() {
|
|
let codes_csv: String = match linter.common_prefix() {
|
|
"" => linter
|
|
.upstream_categories()
|
|
.unwrap()
|
|
.iter()
|
|
.map(|c| c.prefix)
|
|
.join(", "),
|
|
prefix => prefix.to_string(),
|
|
};
|
|
table_out.push_str(&format!("### {} ({codes_csv})", linter.name()));
|
|
table_out.push('\n');
|
|
table_out.push('\n');
|
|
|
|
if let Some(url) = linter.url() {
|
|
let host = url
|
|
.trim_start_matches("https://")
|
|
.split('/')
|
|
.next()
|
|
.unwrap();
|
|
table_out.push_str(&format!(
|
|
"For more, see [{}]({}) on {}.",
|
|
linter.name(),
|
|
url,
|
|
match host {
|
|
"pypi.org" => "PyPI",
|
|
"github.com" => "GitHub",
|
|
host => panic!(
|
|
"unexpected host in URL of {}, expected pypi.org or github.com but found \
|
|
{host}",
|
|
linter.name()
|
|
),
|
|
}
|
|
));
|
|
table_out.push('\n');
|
|
table_out.push('\n');
|
|
}
|
|
|
|
if Options::metadata().has(linter.name()) {
|
|
table_out.push_str(&format!(
|
|
"For related settings, see [{}](settings.md#{}).",
|
|
linter.name(),
|
|
linter.name(),
|
|
));
|
|
table_out.push('\n');
|
|
table_out.push('\n');
|
|
}
|
|
|
|
let rules_by_upstream_category = linter
|
|
.all_rules()
|
|
.map(|rule| (rule.upstream_category(&linter), rule))
|
|
.into_group_map();
|
|
|
|
if rules_by_upstream_category.len() > 1 {
|
|
for (opt, rules) in &rules_by_upstream_category {
|
|
if opt.is_some() {
|
|
let UpstreamCategoryAndPrefix { category, prefix } = opt.unwrap();
|
|
table_out.push_str(&format!("#### {category} ({prefix})"));
|
|
}
|
|
table_out.push('\n');
|
|
table_out.push('\n');
|
|
generate_table(&mut table_out, rules.clone(), &linter);
|
|
}
|
|
} else {
|
|
generate_table(&mut table_out, linter.all_rules(), &linter);
|
|
}
|
|
}
|
|
|
|
table_out
|
|
}
|