perf(linter): reduce rule config dispatch size (#25461)

Generate `from_configuration` match arms only for the 341 rules that override the default implementation. The other 508 rules clone their default value from `RULES`.

This reduces the release oxlint binary from 13,963,312 to 13,946,800 bytes (-16,512 bytes).

AI-assisted.
This commit is contained in:
Boshen committed 2026-08-10 08:23:40 +00:00
1 parent 030857b509
commit 8f784f35d4
4 files changed
+25 -1650

No files matched your search

File diff suppressed because it is too large. Load diff
+12 -1
View File
@@ -128,7 +128,18 @@ pub fn generate_rules_enum_file() -> io::Result<()> {
.map_err(|e| std::io::Error::other(format!("could not find project root: {e}")))?;
let rules_file_contents = fs::read_to_string(root.join("crates/oxc_linter/src/rules.rs"))?;
let rule_entries = get_all_rules(&rules_file_contents);
let mut rule_entries = get_all_rules(&rules_file_contents);
for rule in &mut rule_entries {
let Some(path) = find_rule_source_file(&root, rule) else { continue };
let Ok(source) = fs::read_to_string(path) else { continue };
let Ok(file) = syn::parse_file(&source) else { continue };
let Some(rule_impl) = find_rule_impl_block(&file, &rule.rule_struct_name()) else {
continue;
};
rule.has_custom_from_configuration =
find_impl_function(rule_impl, "from_configuration").is_some();
}
let out = rules_enum::generate_rules_enum(&rule_entries);
let formatted_out = rust_fmt(&out);
+9 -2
View File
@@ -9,6 +9,8 @@ pub struct RuleEntry<'e> {
pub plugin_module_name: &'e str,
/// The rule's module name, like `no_debugger` in `eslint::no_debugger:NoDebugger`.
pub rule_module_name: &'e str,
/// Whether the rule overrides `Rule::from_configuration`.
pub has_custom_from_configuration: bool,
}
impl RuleEntry<'_> {
@@ -48,8 +50,13 @@ pub fn get_all_rules(contents: &str) -> Vec<RuleEntry<'_>> {
&& line.ends_with(';')
&& let Some(rule_name) = line.strip_prefix("pub mod ").and_then(|s| s.strip_suffix(';'))
{
rule_entries
.push(RuleEntry { plugin_module_name: plugin, rule_module_name: rule_name });
rule_entries.push(RuleEntry {
plugin_module_name: plugin,
rule_module_name: rule_name,
// Preserve the existing generated behavior unless codegen confirms that the rule
// uses the default implementation.
has_custom_from_configuration: true,
});
}
}
+3 -1
View File
@@ -200,6 +200,7 @@ fn generate_rule_enum_impl(rule_entries: &[RuleEntry<'_>]) -> TokenStream {
let from_configuration_arms: Vec<TokenStream> = rule_entries
.iter()
.filter(|rule| rule.has_custom_from_configuration)
.map(|rule| {
let enum_name = make_enum_ident(rule);
quote! { Self::#enum_name(_) => Ok(Self::#enum_name(#enum_name::from_configuration(value)?)) }
@@ -345,7 +346,8 @@ fn generate_rule_enum_impl(rule_entries: &[RuleEntry<'_>]) -> TokenStream {
pub fn from_configuration(&self, value: serde_json::Value) -> Result<Self, serde_json::error::Error> {
match self {
#(#from_configuration_arms),*
#(#from_configuration_arms,)*
_ => Ok(RULES[self.id()].clone()),
}
}