Skip to content

Commit 0440b0f

Browse files
v-sayapincamc314
andauthored
feat(linter/eslint): implement id-match rule (#22379)
This PR implements the `eslint/id-match` rule, which enforces a configured naming regex for identifiers ESLint ref: https://eslint.org/docs/latest/rules/id-match Issue: #479 ### Behavior Differences from ESLint This implementation is intentionally stricter in two cases: - Computed destructuring keys are checked, for example `const { [bad_name]: x } = obj` and `({ [bad_name]: x } = obj)`, because the computed key is a normal reference expression, not a binding introduced by destructuring - With `properties` enabled, ordinary top-level dynamic import option keys are checked, for example `import("x", { bad_option: true })`. Import attributes inside `with { ... }` are still ignored ### TypeScript TypeScript syntax is supported on a best-effort basis for identifiers that flow through the same visited AST node kinds and transparent wrappers such as `as`, `satisfies`, non-null assertions, and instantiation expressions This is not a replacement for `@typescript-eslint/naming-convention` or future tsgolint naming-convention work: oxc-project/tsgolint#186 ### Regex Compatibility The pattern is compiled with Rust regex syntax. JavaScript-specific regex features such as lookaround and backreferences are not supported. Unicode escapes should use Rust syntax, for example `\u{XXXX}` ### Algorithmic Complexity The generated rule runner limits the hot path to identifier-like AST nodes: - `BindingIdentifier` - `IdentifierReference` - `IdentifierName` - `PrivateIdentifier` - `LabelIdentifier` Each visited identifier first runs the regex check and returns immediately when the name matches For non-default configurations, the hot path is linear in the total length of checked identifier names, with additional ancestor/context checks only for failed regex matches Space complexity is `O(1)` beyond the compiled regex and options. The hot path does not allocate unless a diagnostic is emitted The default pattern `^.+$` matches every non-empty identifier name, so `should_run` skips rule work entirely for the default configuration ### AI Disclosure Claude Opus 4.7 & Codex GPT 5.5 --------- Co-authored-by: Cameron Clark <cameron.clark@hey.com>
1 parent 0f26de6 commit 0440b0f

10 files changed

Lines changed: 2083 additions & 1 deletion

File tree

apps/oxlint/src-js/package/config.generated.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -531,6 +531,7 @@ export interface DummyRuleMap {
531531
"grouped-accessor-pairs"?: DummyRule;
532532
"guard-for-in"?: DummyRule;
533533
"id-length"?: DummyRule;
534+
"id-match"?: DummyRule;
534535
"import/consistent-type-specifier-style"?: DummyRule;
535536
"import/default"?: DummyRule;
536537
"import/export"?: DummyRule;

crates/oxc_linter/src/generated/rule_runner_impls.rs

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/oxc_linter/src/generated/rules_enum.rs

Lines changed: 30 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/oxc_linter/src/rules.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ pub(crate) mod eslint {
6262
pub mod grouped_accessor_pairs;
6363
pub mod guard_for_in;
6464
pub mod id_length;
65+
pub mod id_match;
6566
pub mod init_declarations;
6667
pub mod logical_assignment_operators;
6768
pub mod max_classes_per_file;

0 commit comments

Comments
 (0)