name: performance-lint-rules description: Tips for writing performant Oxc linter rules. Use only when editing Rust rule implementations under crates/oxc_linter/src/rules/.
This skill gives performance guidance for Oxc linter rule implementations.
Scope
Use this skill only for Rust code under crates/oxc_linter/src/rules/.
Do not use this skill for linter infrastructure, parser code, semantic analysis, formatter code, tests outside the rules directory, or unrelated crates.
Performance Guidelines
Prefer top-level node kind checks
Put node kind checks at the top level of the rule when possible. Rule runner implementations generated by lintgen can recognize implemented node types, which helps avoid invoking rules on unrelated AST nodes.
Do cheaper checks first
Order checks from cheapest and most selective to most expensive. Simple equality checks, early returns, and fast paths such as ASCII-only checks should come before semantic lookups, allocations, or deeper AST traversal.
Most rules trigger on only a small set of nodes, so quickly return for the common non-matching cases.
Optimize for success
Most files do not contain lint errors. Avoid preparing diagnostics, labels, help text, fix data, or other extra context until the rule knows it needs to report an issue.
Iterate over the smallest set possible
Avoid walking more syntax than necessary.
- Use
run_oncewhen the rule only needs a whole-file pass and does not need to run on every node. - Iterate over symbols instead of AST nodes when looking for references to specific names.
- Prefer targeted lists or semantic data over broad AST traversal when available.
Avoid unnecessary regular expressions
Do not construct regular expressions internally when byte or string checks are enough. Prefer simple operations such as checking whether a string contains a character, starts with a prefix, ends with a suffix, or matches a small fixed set of values.
Avoid heap allocations
Minimize allocations in hot lint paths.
- Use copy-on-write utilities when a value usually does not need to change.
- Avoid intermediate
Vecs andStrings when iteration or borrowed data is enough. - Keep temporary data on the stack when practical.
- Delay allocation until a diagnostic, fix, or transformed value is actually needed.