mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
feat(tasks/website): code generate the linter rules
This commit is contained in:
parent
ead637bf50
commit
3671b5c4d0
5 changed files with 156 additions and 57 deletions
|
|
@ -12,15 +12,15 @@ mod fixer;
|
|||
mod globals;
|
||||
mod javascript_globals;
|
||||
mod options;
|
||||
pub mod partial_loader;
|
||||
pub mod rule;
|
||||
mod rule;
|
||||
mod rules;
|
||||
mod service;
|
||||
mod utils;
|
||||
|
||||
use std::{io::Write, rc::Rc, sync::Arc};
|
||||
pub mod partial_loader;
|
||||
pub mod table;
|
||||
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use std::{io::Write, rc::Rc, sync::Arc};
|
||||
|
||||
use oxc_diagnostics::Error;
|
||||
use oxc_semantic::AstNode;
|
||||
|
|
@ -29,15 +29,15 @@ pub use crate::{
|
|||
config::ESLintConfig,
|
||||
context::LintContext,
|
||||
options::{AllowWarnDeny, LintOptions},
|
||||
rule::RuleWithSeverity,
|
||||
rule::{RuleCategory, RuleMeta, RuleWithSeverity},
|
||||
service::{LintService, LintServiceOptions},
|
||||
};
|
||||
use crate::{
|
||||
config::{ESLintEnv, ESLintGlobals, ESLintSettings},
|
||||
fixer::Fix,
|
||||
fixer::{Fixer, Message},
|
||||
rule::RuleCategory,
|
||||
rules::{RuleEnum, RULES},
|
||||
rules::RuleEnum,
|
||||
table::RuleTable,
|
||||
};
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
|
|
@ -132,51 +132,12 @@ impl Linter {
|
|||
|
||||
/// # Panics
|
||||
pub fn print_rules<W: Write>(writer: &mut W) {
|
||||
let default_rules = Linter::default()
|
||||
.rules
|
||||
.into_iter()
|
||||
.map(|rule| rule.name())
|
||||
.collect::<FxHashSet<&str>>();
|
||||
|
||||
let rules_by_category = RULES.iter().fold(
|
||||
FxHashMap::default(),
|
||||
|mut map: FxHashMap<RuleCategory, Vec<&RuleEnum>>, rule| {
|
||||
map.entry(rule.category()).or_default().push(rule);
|
||||
map
|
||||
},
|
||||
);
|
||||
|
||||
let mut default_count = 0;
|
||||
|
||||
for (category, rules) in rules_by_category {
|
||||
writeln!(writer, "## {} ({}):", category, rules.len()).unwrap();
|
||||
|
||||
let rule_width = rules.iter().map(|r| r.name().len()).max().unwrap();
|
||||
let plugin_width = rules.iter().map(|r| r.plugin_name().len()).max().unwrap();
|
||||
let x = "";
|
||||
writeln!(
|
||||
writer,
|
||||
"| {:<rule_width$} | {:<plugin_width$} | Default |",
|
||||
"Rule name", "Source"
|
||||
)
|
||||
.unwrap();
|
||||
writeln!(writer, "| {x:-<rule_width$} | {x:-<plugin_width$} | {x:-<7} |").unwrap();
|
||||
|
||||
for rule in rules {
|
||||
let rule_name = rule.name();
|
||||
let plugin_name = rule.plugin_name();
|
||||
let (default, default_width) = if default_rules.contains(rule_name) {
|
||||
default_count += 1;
|
||||
("✅", 6)
|
||||
} else {
|
||||
("", 7)
|
||||
};
|
||||
writeln!(writer, "| {rule_name:<rule_width$} | {plugin_name:<plugin_width$} | {default:<default_width$} |").unwrap();
|
||||
}
|
||||
writeln!(writer).unwrap();
|
||||
let table = RuleTable::new();
|
||||
for section in table.sections {
|
||||
writeln!(writer, "{}", section.render_markdown_table()).unwrap();
|
||||
}
|
||||
writeln!(writer, "Default: {default_count}").unwrap();
|
||||
writeln!(writer, "Total: {}", RULES.len()).unwrap();
|
||||
writeln!(writer, "Default: {}", table.turned_on_by_default_count).unwrap();
|
||||
writeln!(writer, "Total: {}", table.total).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ impl RuleWithSeverity {
|
|||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use crate::RULES;
|
||||
use crate::rules::RULES;
|
||||
|
||||
#[test]
|
||||
fn ensure_documentation() {
|
||||
|
|
|
|||
112
crates/oxc_linter/src/table.rs
Normal file
112
crates/oxc_linter/src/table.rs
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
use std::{collections::HashMap, fmt::Write};
|
||||
|
||||
use rustc_hash::FxHashSet;
|
||||
|
||||
use crate::{rules::RULES, Linter};
|
||||
|
||||
pub struct RuleTable {
|
||||
pub sections: Vec<RuleTableSection>,
|
||||
pub total: usize,
|
||||
pub turned_on_by_default_count: usize,
|
||||
}
|
||||
|
||||
pub struct RuleTableSection {
|
||||
pub rows: Vec<RuleTableRow>,
|
||||
pub category: String,
|
||||
pub rule_column_width: usize,
|
||||
pub plugin_column_width: usize,
|
||||
}
|
||||
|
||||
pub struct RuleTableRow {
|
||||
pub name: &'static str,
|
||||
pub plugin: String,
|
||||
pub category: String,
|
||||
pub documentation: Option<&'static str>,
|
||||
pub turned_on_by_default: bool,
|
||||
}
|
||||
|
||||
impl Default for RuleTable {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl RuleTable {
|
||||
pub fn new() -> Self {
|
||||
let default_rules = Linter::default()
|
||||
.rules
|
||||
.into_iter()
|
||||
.map(|rule| rule.name())
|
||||
.collect::<FxHashSet<&str>>();
|
||||
|
||||
let mut rows = RULES
|
||||
.iter()
|
||||
.map(|rule| {
|
||||
let name = rule.name();
|
||||
RuleTableRow {
|
||||
name,
|
||||
documentation: rule.documentation(),
|
||||
plugin: rule.plugin_name().to_string(),
|
||||
category: rule.category().to_string(),
|
||||
turned_on_by_default: default_rules.contains(name),
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let total = rows.len();
|
||||
|
||||
rows.sort_by_key(|row| (row.plugin.clone(), row.name));
|
||||
|
||||
let mut rows_by_category = rows.into_iter().fold(
|
||||
HashMap::default(),
|
||||
|mut map: HashMap<String, Vec<RuleTableRow>>, row| {
|
||||
map.entry(row.category.clone()).or_default().push(row);
|
||||
map
|
||||
},
|
||||
);
|
||||
|
||||
let sections =
|
||||
["Correctness", "Perf", "Restriction", "Suspicious", "Pedantic", "Style", "Nursery"]
|
||||
.into_iter()
|
||||
.filter_map(|category| {
|
||||
let rows = rows_by_category.remove(category)?;
|
||||
let rule_column_width = rows.iter().map(|r| r.name.len()).max()?;
|
||||
let plugin_column_width = rows.iter().map(|r| r.plugin.len()).max()?;
|
||||
Some(RuleTableSection {
|
||||
rows,
|
||||
category: category.to_string(),
|
||||
rule_column_width,
|
||||
plugin_column_width,
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
RuleTable { total, sections, turned_on_by_default_count: default_rules.len() }
|
||||
}
|
||||
}
|
||||
|
||||
impl RuleTableSection {
|
||||
pub fn render_markdown_table(&self) -> String {
|
||||
let mut s = String::new();
|
||||
let category = &self.category;
|
||||
let rows = &self.rows;
|
||||
let rule_width = self.rule_column_width;
|
||||
let plugin_width = self.plugin_column_width;
|
||||
writeln!(s, "## {} ({}):", category, rows.len()).unwrap();
|
||||
|
||||
let x = "";
|
||||
writeln!(s, "| {:<rule_width$} | {:<plugin_width$} | Default |", "Rule name", "Source")
|
||||
.unwrap();
|
||||
writeln!(s, "| {x:-<rule_width$} | {x:-<plugin_width$} | {x:-<7} |").unwrap();
|
||||
|
||||
for row in rows {
|
||||
let rule_name = row.name;
|
||||
let plugin_name = &row.plugin;
|
||||
let (default, default_width) =
|
||||
if row.turned_on_by_default { ("✅", 6) } else { ("", 7) };
|
||||
writeln!(s, "| {rule_name:<rule_width$} | {plugin_name:<plugin_width$} | {default:<default_width$} |").unwrap();
|
||||
}
|
||||
|
||||
s
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
use oxc_linter::rule::{RuleCategory, RuleMeta};
|
||||
use oxc_linter::{RuleCategory, RuleMeta};
|
||||
use oxc_macros::declare_oxc_lint_test;
|
||||
|
||||
struct TestRule;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,33 @@
|
|||
use oxc_linter::table::RuleTable;
|
||||
|
||||
// `cargo run -p website linter-rules > /path/to/oxc/oxc-project.github.io/src/docs/guide/usage/linter/generated-rules.md`
|
||||
// <https://oxc-project.github.io/docs/guide/usage/linter/rules.html>
|
||||
pub fn generate_rules() {
|
||||
use oxc_linter::Linter;
|
||||
let mut v = vec![];
|
||||
Linter::print_rules(&mut v);
|
||||
println!("{}", String::from_utf8(v).unwrap());
|
||||
let table = RuleTable::new();
|
||||
|
||||
let total = table.total;
|
||||
let turned_on_by_default_count = table.turned_on_by_default_count;
|
||||
|
||||
let body = table
|
||||
.sections
|
||||
.into_iter()
|
||||
.map(|section| section.render_markdown_table())
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
|
||||
println!("
|
||||
# Rules
|
||||
|
||||
The progress of all rule implementations is tracked [here](https://github.com/oxc-project/oxc/issues/481).
|
||||
|
||||
- Total number of rules: {total}
|
||||
- Rules turned on by default: {turned_on_by_default_count}
|
||||
|
||||
<!-- textlint-disable terminology -->
|
||||
|
||||
{body}
|
||||
|
||||
<!-- textlint-enable -->
|
||||
|
||||
");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue