Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

camc314
Copy link
Contributor

@camc314 camc314 commented May 2, 2025

No description provided.

Copy link
Contributor Author

camc314 commented May 2, 2025


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • 0-merge - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@github-actions github-actions bot added A-linter Area - Linter C-enhancement Category - New feature or request labels May 2, 2025
Copy link

codspeed-hq bot commented May 2, 2025

CodSpeed Instrumentation Performance Report

Merging #10773 will not alter performance

Comparing c/05-02-feat_linter_regex_no-useless-backref (4c62348) with main (3d47159)

Summary

✅ 36 untouched benchmarks

@camc314 camc314 force-pushed the c/05-02-feat_linter_regex_no-useless-backref branch from 0a0f695 to 318956a Compare May 2, 2025 23:15
@camc314 camc314 force-pushed the c/05-02-refactor_linter_move_run_on_regex_node_to_utils branch from bf3ccc8 to 731d8d6 Compare May 2, 2025 23:15
@camc314 camc314 force-pushed the c/05-02-feat_linter_regex_no-useless-backref branch 3 times, most recently from a1b00a5 to eab5e16 Compare May 2, 2025 23:33
@graphite-app graphite-app bot changed the base branch from c/05-02-refactor_linter_move_run_on_regex_node_to_utils to graphite-base/10773 May 3, 2025 00:27
@graphite-app graphite-app bot force-pushed the c/05-02-feat_linter_regex_no-useless-backref branch from eab5e16 to 12fb951 Compare May 3, 2025 00:30
@graphite-app graphite-app bot force-pushed the graphite-base/10773 branch from 731d8d6 to 2efe3f0 Compare May 3, 2025 00:30
@graphite-app graphite-app bot changed the base branch from graphite-base/10773 to main May 3, 2025 00:30
@graphite-app graphite-app bot force-pushed the c/05-02-feat_linter_regex_no-useless-backref branch from 12fb951 to c04b7a8 Compare May 3, 2025 00:30
@camc314 camc314 force-pushed the c/05-02-feat_linter_regex_no-useless-backref branch from c04b7a8 to bdb8701 Compare May 3, 2025 15:54
@github-actions github-actions bot added the A-cli Area - CLI label May 3, 2025
@camc314 camc314 marked this pull request as ready for review May 3, 2025 15:55
@camc314 camc314 force-pushed the c/05-02-feat_linter_regex_no-useless-backref branch from bdb8701 to cf853fd Compare May 3, 2025 15:57
Copy link

coderabbitai bot commented May 3, 2025

Walkthrough

This change introduces a new ESLint lint rule called NoUselessBackreference within the Rust linter. The rule is implemented in its own module and integrated into the existing lint rule registration system. It performs static analysis on regular expressions to identify backreferences that are effectively useless because they refer to capturing groups that have not matched or cannot match at the point of evaluation. The rule uses a visitor pattern to traverse the regex abstract syntax tree (AST), gathering data about capturing groups and backreferences along with their hierarchical positions. It detects five categories of useless backreferences based on their relative positions and contexts within the regex: nested groups, disjunctive alternatives, backward references, forward references in lookbehind assertions, and groups inside negative lookaround assertions. When such cases are detected, the rule emits diagnostic warnings explaining why the backreference is ignored. The implementation includes detailed metadata, rationale, examples, and a comprehensive test suite covering diverse regex scenarios. No existing lint rules or their logic were altered.

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

‼️ IMPORTANT
Auto-reply has been disabled for this repository in the CodeRabbit settings. The CodeRabbit bot will not respond to your replies unless it is explicitly tagged.

  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

🧹 Nitpick comments (4)
crates/oxc_linter/src/rules/eslint/no_useless_backreference.rs (3)

230-238: Doc comment lists tuple elements in the wrong order

The block comment states the function returns “backreference span, capture-group span”, but the implementation returns (Problem, capture_span, backref_span).
Keeping docs in sync with code avoids future misuse.


168-175: path.truncate(path.len().saturating_sub(2)) can drop too much context

Truncating by two assumes every node is wrapped in exactly one Alternative.
For patterns like a top-level reference \1, the stack when entering the node may be [Pattern, Alternative, IndexedReference] (length 3); truncating by 2 leaves only [Pattern], losing the branch information required to distinguish siblings inside the same disjunction.

Consider trimming just the current node:

-let mut path = self.current_path();
-path.truncate(path.len().saturating_sub(2));
+let mut path = self.current_path();
+path.pop(); // remove current node

If an additional ancestor really needs to be pruned, do so conditionally (e.g., when that ancestor is an Alternative).
This will make the LCA computation in problems_for_backref more robust.

Also applies to: 177-184, 186-194


245-248: Unhandled “unknown capture-group” branch

The TODO indicates uncertainty when a back-reference cannot be mapped to a capture group (e.g. \99 or a missing named group).
Returning None silently skips the issue – yet such patterns are either errors or, in some engines, always match the literal digits. Consider emitting a separate diagnostic (or delegating to no_invalid_regexp) so users still get feedback.

crates/oxc_linter/src/rules.rs (1)

587-589: Keep the macro list alphabetically sorted

For readability the macro arguments are roughly alphabetised: inserting no_useless_backreference before no_lonely_if breaks this order (lonely < useless). Moving the new entry below the other no_* rules would preserve the convention and simplify future merges.

🛑 Comments failed to post (1)
crates/oxc_linter/src/rules/eslint/no_useless_backreference.rs (1)

20-26: 🛠️ Refactor suggestion

Swap or re-word variant messages to match the actual Problem semantics

Problem::Disjunctive and Problem::Backward have their diagnostic strings swapped, while Problem::Forward’s wording is also misleading.
As written:

  • Disjunctive warns that the group “appears later in the pattern” (that’s Backward).
  • Backward warns that the group “is in another alternative” (that’s Disjunctive).
  • Forward says the group “appears before … lookbehind” – it actually appears after the back-reference in look-behinds.

Apart from confusing users, this may make triaging reports harder.

-        Problem::Disjunctive => OxcDiagnostic::warn(format!("Backreference '{back_reference}' will be ignored. It references group '{group}' which appears later in the pattern.")).with_label(span),
-        Problem::Forward => OxcDiagnostic::warn(format!("Backreference '{back_reference}' will be ignored. It references group '{group}' which appears before in the same lookbehind.")).with_label(span),
-        Problem::Backward => OxcDiagnostic::warn(format!("Backreference '{back_reference}' will be ignored. It references group '{group}' which is in another alternative.")).with_label(span),
+        Problem::Disjunctive => OxcDiagnostic::warn(format!("Backreference '{back_reference}' will be ignored. It references group '{group}' which is in another alternative of a disjunction.")).with_label(span),
+        Problem::Forward => OxcDiagnostic::warn(format!("Backreference '{back_reference}' will be ignored. It references group '{group}' which appears later in the same lookbehind.")).with_label(span),
+        Problem::Backward => OxcDiagnostic::warn(format!("Backreference '{back_reference}' will be ignored. It references group '{group}' which appears later in the pattern.")).with_label(span),

This will align each message with the rule logic.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

    match problem {
        Problem::Nested =>OxcDiagnostic::warn(format!("Backreference '{back_reference}' will be ignored. It references group '{group}' from within that group.")).with_label(span),
        Problem::Disjunctive => OxcDiagnostic::warn(format!("Backreference '{back_reference}' will be ignored. It references group '{group}' which is in another alternative of a disjunction.")).with_label(span),
        Problem::Forward => OxcDiagnostic::warn(format!("Backreference '{back_reference}' will be ignored. It references group '{group}' which appears later in the same lookbehind.")).with_label(span),
        Problem::Backward => OxcDiagnostic::warn(format!("Backreference '{back_reference}' will be ignored. It references group '{group}' which appears later in the pattern.")).with_label(span),
        Problem::IntoNegativeLookaround => OxcDiagnostic::warn(format!("Backreference '{back_reference}' will be ignored. It references group '{group}' which is in a negative lookaround.")).with_label(span),
    }
🤖 Prompt for AI Agents (early access)
In crates/oxc_linter/src/rules/eslint/no_useless_backreference.rs lines 20 to 26, the diagnostic messages for Problem::Disjunctive and Problem::Backward are swapped and the message for Problem::Forward is misleading. Swap the messages for Disjunctive and Backward to correctly reflect their semantics, and update the Forward message to indicate that the referenced group appears after the back-reference in the same lookbehind. This will ensure the warning messages accurately describe the problem types.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
crates/oxc_linter/src/rules/eslint/no_useless_backreference.rs (1)

22-24: ⚠️ Potential issue

Correct swapped diagnostic messages

The diagnostic messages for Problem::Disjunctive and Problem::Backward are swapped. The messages don't match their corresponding problem types.

-        Problem::Disjunctive => OxcDiagnostic::warn(format!("Backreference '{back_reference}' will be ignored. It references group '{group}' which appears later in the pattern.")).with_label(span),
+        Problem::Disjunctive => OxcDiagnostic::warn(format!("Backreference '{back_reference}' will be ignored. It references group '{group}' which is in another alternative of the same disjunction.")).with_label(span),
-        Problem::Forward => OxcDiagnostic::warn(format!("Backreference '{back_reference}' will be ignored. It references group '{group}' which appears before in the same lookbehind.")).with_label(span),
+        Problem::Forward => OxcDiagnostic::warn(format!("Backreference '{back_reference}' will be ignored. It references group '{group}' which appears before in the same lookbehind.")).with_label(span),
-        Problem::Backward => OxcDiagnostic::warn(format!("Backreference '{back_reference}' will be ignored. It references group '{group}' which is in another alternative.")).with_label(span),
+        Problem::Backward => OxcDiagnostic::warn(format!("Backreference '{back_reference}' will be ignored. It references group '{group}' which appears later in the pattern.")).with_label(span),
🧹 Nitpick comments (2)
crates/oxc_linter/src/rules/eslint/no_useless_backreference.rs (2)

21-22: Fix inconsistent spacing in diagnostic function

There is inconsistent spacing after the arrow in the match expression.

-        Problem::Nested =>OxcDiagnostic::warn(format!("Backreference '{back_reference}' will be ignored. It references group '{group}' from within that group.")).with_label(span),
+        Problem::Nested => OxcDiagnostic::warn(format!("Backreference '{back_reference}' will be ignored. It references group '{group}' from within that group.")).with_label(span),

206-208: Fix documentation comment formatting

There's an extra slash in the documentation comment, making the formatting inconsistent.

-//////
+///
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bdb8701 and cf853fd.

⛔ Files ignored due to path filters (45)
  • apps/oxlint/src/snapshots/_--ignore-path fixtures__linter__.customignore --no-ignore [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_--ignore-pattern _____.js --ignore-pattern _____.vue [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_--import-plugin -A all -D no-cycle [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_--import-plugin [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_--vitest-plugin -c fixtures__eslintrc_vitest_replace__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-D correctness [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-W correctness -A no-debugger [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-W no-undef -c fixtures__eslintrc_env__eslintrc_no_env.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-W no-undef -c fixtures__no_undef__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__config_ignore_patterns__ignore_extension__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__eslintrc_env__eslintrc_env_browser.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__eslintrc_off__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__eslintrc_vitest_replace__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__linter__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__no_console_off__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__no_empty_allow_empty_catch__eslintrc.json -W no-empty [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__no_empty_disallow_empty_catch__eslintrc.json -W no-empty [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__overrides__.oxlintrc.json fixtures__overrides__test.js -c fixtures__overrides__.oxlintrc.json fixtures__overrides__test.ts -c fixtures__overrides__.oxlintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__overrides__directories-config.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__typescript_eslint__eslintrc.json --disable-typescript-plugin [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__typescript_eslint__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_fixtures__linter__debugger.js [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__config_ignore_patterns__ignore_directory_-c [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__config_ignore_patterns__with_oxlintrc_-c .__test__eslintrc.json --ignore-pattern _.ts [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__disable_eslint_and_unicorn_alias_rules_-c .oxlintrc-eslint.json test.js -c .oxlintrc-unicorn.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__extends_config_--config extends_rules_config.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__extends_config_--config relative_paths__extends_extends_config.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__ignore_file_current_dir_ [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__import-cycle_--import-plugin -D [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__import_-c .oxlintrc.json test.js -c .oxlintrc-import-x.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__nested_config_--config [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__nested_config_-A no-console --config [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__overrides_env_globals_-c .oxlintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__report_unused_directives_-c .oxlintrc.json --report-unused-disable-directives [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__two_rules_with_same_rule_name_-c .oxlintrc.json [email protected] is excluded by !**/*.snap
  • crates/oxc_linter/src/snapshots/eslint_no_useless_backreference.snap is excluded by !**/*.snap
📒 Files selected for processing (2)
  • crates/oxc_linter/src/rules.rs (2 hunks)
  • crates/oxc_linter/src/rules/eslint/no_useless_backreference.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/oxc_linter/src/rules.rs
⏰ Context from checks skipped due to timeout of 90000ms (3)
  • GitHub Check: Benchmark linter (1)
  • GitHub Check: Benchmark linter (0)
  • GitHub Check: Test NAPI
🔇 Additional comments (2)
crates/oxc_linter/src/rules/eslint/no_useless_backreference.rs (2)

354-558: Comprehensive test coverage

The rule has an extensive test suite covering a wide range of regex patterns, which is excellent for ensuring the correctness of the implementation.


246-248:

❓ Verification inconclusive

Resolve TODO comment

The TODO comment indicates uncertainty about how to handle unmapped backreferences. This should be resolved or documented with a clearer explanation of the expected behavior.

Currently, when a backreference can't be mapped to a capture group, the function returns None, which means no problem is reported. Is this the intended behavior? If so, consider adding a comment explaining this decision. If not, consider implementing appropriate error handling.


🏁 Script executed:

#!/bin/bash
# Search for similar handling of unmapped/unknown backreferences in the codebase
rg --type rust "TODO.*unmapped.*backreference|TODO.*map.*backreference" -A 2 -B 2

Length of output: 83


Clarify handling of unmapped backreferences
The TODO in crates/oxc_linter/src/rules/eslint/no_useless_backreference.rs (lines 246–248) highlights uncertainty about what should happen when a backreference can’t be mapped to a capture group. Today the code simply returns None (i.e., no lint is reported). Please confirm the intended behavior:

  • If silently ignoring unmapped backreferences is correct, replace the TODO with a clear comment explaining why they’re skipped.
  • Otherwise, implement the appropriate handling (for example, emit a warning or error when mapping fails) and remove the TODO.

Affected snippet:

// TODO: is this right? what happens when we can't map back ref to a capture group
return None;

@camc314 camc314 force-pushed the c/05-02-feat_linter_regex_no-useless-backref branch from cf853fd to c572ca1 Compare May 3, 2025 16:03
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
crates/oxc_linter/src/rules/eslint/no_useless_backreference.rs (3)

20-26: Fix inconsistent spacing in the diagnostic function.

There's missing whitespace after Problem::Nested => which makes the code formatting inconsistent with other match arms.

-        Problem::Nested =>OxcDiagnostic::warn(format!("Backreference '{back_reference}' will be ignored. It references group '{group}' from within that group.")).with_label(span),
+        Problem::Nested => OxcDiagnostic::warn(format!("Backreference '{back_reference}' will be ignored. It references group '{group}' from within that group.")).with_label(span),

265-276: Improve variable naming and add a clarifying comment.

The variables i and j are used to find the lowest common ancestor in the AST paths, but their purpose isn't immediately clear without context. Consider renaming them and adding a brief comment explaining the algorithm.

-    let mut i = 0;
-    let mut j = 0;
+    // Find the lowest common ancestor by comparing paths until they diverge
+    let mut bref_path_idx = 0;
+    let mut group_path_idx = 0;

-    while i + 1 < bref.path.len()
-        && j + 1 < cap_group.path.len()
-        && bref.path[i + 1] == cap_group.path[j + 1]
+    while bref_path_idx + 1 < bref.path.len()
+        && group_path_idx + 1 < cap_group.path.len()
+        && bref.path[bref_path_idx + 1] == cap_group.path[group_path_idx + 1]
     {
-        i += 1;
-        j += 1;
+        bref_path_idx += 1;
+        group_path_idx += 1;
     }
-    let index_of_lowest_common_ancestor = j + 1;
+    let index_of_lowest_common_ancestor = group_path_idx + 1;

206-207: Fix documentation formatting inconsistency.

There's an extra forward slash in the documentation which creates inconsistent formatting with the rest of the function comment.

- //////
+ ///
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cf853fd and c572ca1.

⛔ Files ignored due to path filters (45)
  • apps/oxlint/src/snapshots/_--ignore-path fixtures__linter__.customignore --no-ignore [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_--ignore-pattern _____.js --ignore-pattern _____.vue [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_--import-plugin -A all -D no-cycle [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_--import-plugin [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_--vitest-plugin -c fixtures__eslintrc_vitest_replace__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-D correctness [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-W correctness -A no-debugger [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-W no-undef -c fixtures__eslintrc_env__eslintrc_no_env.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-W no-undef -c fixtures__no_undef__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__config_ignore_patterns__ignore_extension__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__eslintrc_env__eslintrc_env_browser.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__eslintrc_off__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__eslintrc_vitest_replace__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__linter__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__no_console_off__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__no_empty_allow_empty_catch__eslintrc.json -W no-empty [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__no_empty_disallow_empty_catch__eslintrc.json -W no-empty [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__overrides__.oxlintrc.json fixtures__overrides__test.js -c fixtures__overrides__.oxlintrc.json fixtures__overrides__test.ts -c fixtures__overrides__.oxlintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__overrides__directories-config.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__typescript_eslint__eslintrc.json --disable-typescript-plugin [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__typescript_eslint__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_fixtures__linter__debugger.js [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__config_ignore_patterns__ignore_directory_-c [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__config_ignore_patterns__with_oxlintrc_-c .__test__eslintrc.json --ignore-pattern _.ts [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__disable_eslint_and_unicorn_alias_rules_-c .oxlintrc-eslint.json test.js -c .oxlintrc-unicorn.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__extends_config_--config extends_rules_config.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__extends_config_--config relative_paths__extends_extends_config.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__ignore_file_current_dir_ [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__import-cycle_--import-plugin -D [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__import_-c .oxlintrc.json test.js -c .oxlintrc-import-x.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__nested_config_--config [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__nested_config_-A no-console --config [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__overrides_env_globals_-c .oxlintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__report_unused_directives_-c .oxlintrc.json --report-unused-disable-directives [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__two_rules_with_same_rule_name_-c .oxlintrc.json [email protected] is excluded by !**/*.snap
  • crates/oxc_linter/src/snapshots/eslint_no_useless_backreference.snap is excluded by !**/*.snap
📒 Files selected for processing (2)
  • crates/oxc_linter/src/rules.rs (2 hunks)
  • crates/oxc_linter/src/rules/eslint/no_useless_backreference.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/oxc_linter/src/rules.rs
🔇 Additional comments (4)
crates/oxc_linter/src/rules/eslint/no_useless_backreference.rs (4)

236-236: Previous typo fix confirmed.

The comment was previously flagged for having a typo ("backrefernce") which has been corrected.


71-91: Well-implemented Rule trait.

The implementation of the Rule trait for NoUselessBackreference is clean and follows the visitor pattern effectively. It correctly collects information about regex nodes and emits appropriate diagnostics when problematic backreferences are found.


204-353: Excellent problem detection logic with thorough documentation.

The implementation of problems_for_backref is well-structured with comprehensive comments explaining each problem type. The examples provided in the comments help developers understand the reasoning behind each check, making the code more maintainable.


355-558: Comprehensive test suite.

The test suite is extensive and covers a wide range of valid and invalid regular expressions. This ensures that the rule correctly identifies useless backreferences in various contexts.

@camc314 camc314 force-pushed the c/05-02-feat_linter_regex_no-useless-backref branch from c572ca1 to 6d456b9 Compare May 3, 2025 16:08
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
crates/oxc_linter/src/rules/eslint/no_useless_backreference.rs (2)

236-236: Fix typo in comment.

There's a typo in the comment: "backrefernce" should be "backreference".

-    /* span of the backrefernce */ Span,
+    /* span of the backreference */ Span,

204-353: Consider breaking down complex logic into helper functions.

The problems_for_backref function contains several distinct checks that could be extracted into helper functions to improve readability and maintainability.

The function could be restructured to use separate helper functions for each problem type detection, making the main function more concise:

 fn problems_for_backref<'a>(
     bref: &'a BackRefInfo<'a>,
     nodes: &IndexVec<RegexNodeId, RegExpAstKind<'a>>,
     groups: &'a [GroupInfo<'a>],
 ) -> Option<(
     Problem,
     /* span of the backreference */ Span,
     /* span of the capture group */ Span,
 )> {
     let cap_group = match bref.target {
         BackRefInfoTarget::Index(i) => groups.get(i as usize - 1),
         BackRefInfoTarget::Name(cap_group_name) => {
             groups.iter().find(|g| g.name.is_some_and(|n| n == cap_group_name))
         }
     };
     let Some(cap_group) = cap_group else {
         // We return None for unmappable backreferences to align with ESLint's behavior,
         // which ignores unmatched backreferences rather than reporting them as errors.
         return None;
     };
 
+    // Check for Problem::Nested
+    if let Some(problem) = check_nested_problem(bref, cap_group) {
+        return Some(problem);
+    }
+    
     // Problem::Nested
     // In this scenario, the backreference appears *inside* the group it refers to.
     // e.g. `/(a\1)/`
     //        ^^^^^ capture group
     //          ^^ backreference
     // This is invalid because when the regex engine reaches the backreference,
     // the group it points to has not finished matching yet — it's still open.
     // As a result, the group has not captured any text at that point, so the
     // backreference is always interpreted as the empty string.
     // While this does not cause a syntax error, the reference serves no purpose
     // and is almost certainly a logic mistake or misunderstanding of how regex works.
     if cap_group.span.contains_inclusive(bref.span) {
         return Some((Problem::Nested, cap_group.span, bref.span));
     }
 
     // ... similar refactoring for other problem types

This refactoring would make the code more maintainable while preserving the detailed comments.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c572ca1 and 6d456b9.

⛔ Files ignored due to path filters (45)
  • apps/oxlint/src/snapshots/_--ignore-path fixtures__linter__.customignore --no-ignore [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_--ignore-pattern _____.js --ignore-pattern _____.vue [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_--import-plugin -A all -D no-cycle [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_--import-plugin [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_--vitest-plugin -c fixtures__eslintrc_vitest_replace__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-D correctness [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-W correctness -A no-debugger [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-W no-undef -c fixtures__eslintrc_env__eslintrc_no_env.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-W no-undef -c fixtures__no_undef__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__config_ignore_patterns__ignore_extension__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__eslintrc_env__eslintrc_env_browser.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__eslintrc_off__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__eslintrc_vitest_replace__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__linter__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__no_console_off__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__no_empty_allow_empty_catch__eslintrc.json -W no-empty [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__no_empty_disallow_empty_catch__eslintrc.json -W no-empty [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__overrides__.oxlintrc.json fixtures__overrides__test.js -c fixtures__overrides__.oxlintrc.json fixtures__overrides__test.ts -c fixtures__overrides__.oxlintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__overrides__directories-config.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__typescript_eslint__eslintrc.json --disable-typescript-plugin [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__typescript_eslint__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_fixtures__linter__debugger.js [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__config_ignore_patterns__ignore_directory_-c [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__config_ignore_patterns__with_oxlintrc_-c .__test__eslintrc.json --ignore-pattern _.ts [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__disable_eslint_and_unicorn_alias_rules_-c .oxlintrc-eslint.json test.js -c .oxlintrc-unicorn.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__extends_config_--config extends_rules_config.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__extends_config_--config relative_paths__extends_extends_config.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__ignore_file_current_dir_ [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__import-cycle_--import-plugin -D [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__import_-c .oxlintrc.json test.js -c .oxlintrc-import-x.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__nested_config_--config [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__nested_config_-A no-console --config [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__overrides_env_globals_-c .oxlintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__report_unused_directives_-c .oxlintrc.json --report-unused-disable-directives [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__two_rules_with_same_rule_name_-c .oxlintrc.json [email protected] is excluded by !**/*.snap
  • crates/oxc_linter/src/snapshots/eslint_no_useless_backreference.snap is excluded by !**/*.snap
📒 Files selected for processing (2)
  • crates/oxc_linter/src/rules.rs (3 hunks)
  • crates/oxc_linter/src/rules/eslint/no_useless_backreference.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/oxc_linter/src/rules.rs
⏰ Context from checks skipped due to timeout of 90000ms (14)
  • GitHub Check: Benchmark (formatter)
  • GitHub Check: Test NAPI
  • GitHub Check: Benchmark (codegen)
  • GitHub Check: Benchmark (minifier)
  • GitHub Check: Clippy
  • GitHub Check: Benchmark (semantic)
  • GitHub Check: Benchmark (isolated_declarations)
  • GitHub Check: Benchmark (transformer)
  • GitHub Check: Test wasm32-wasip1-threads
  • GitHub Check: Build Linter Benchmark
  • GitHub Check: Test (macos-latest)
  • GitHub Check: Benchmark (parser)
  • GitHub Check: Test (ubuntu-latest)
  • GitHub Check: Benchmark (lexer)
🔇 Additional comments (5)
crates/oxc_linter/src/rules/eslint/no_useless_backreference.rs (5)

246-248: Replace TODO comment with proper documentation.

The TODO comment should be replaced with a clear explanation of why returning None for unmappable backreferences is the correct behavior.

Per previous review comments, this appears to be intentional behavior that matches ESLint. Please replace the TODO with proper documentation that explains the rationale.

-    // TODO: is this right? what happens when we can't map back ref to a capture group
+    // We return None for unmappable backreferences to align with ESLint's behavior,
+    // which ignores unmatched backreferences rather than reporting them as errors.
     return None;

21-26: LGTM: Well-formatted diagnostic messages.

The diagnostic messages are clear and correctly explain each type of useless backreference problem to users.


71-91: LGTM: Good rule implementation.

The rule implementation follows the visitor pattern well and properly integrates with the linter framework. The code efficiently collects regex data and reports any issues found.


32-69: LGTM: Excellent documentation and examples.

The rule documentation is comprehensive, including a clear explanation of the problem, why it's bad, and examples of both correct and incorrect code. This provides excellent guidance for users.


355-558: LGTM: Comprehensive test suite.

The test suite is thorough, covering a wide range of regex patterns and edge cases. This ensures the rule works correctly in various scenarios.

@camc314 camc314 changed the title feat(linter): regex/no-useless-backref feat(linter): regex/no-useless-backreference May 3, 2025
@camc314 camc314 force-pushed the c/05-02-feat_linter_regex_no-useless-backref branch from 6d456b9 to 02aa62c Compare May 3, 2025 20:15
@camc314 camc314 force-pushed the c/05-02-feat_linter_regex_no-useless-backref branch 2 times, most recently from 0192acf to 630123d Compare May 3, 2025 20:18
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
crates/oxc_linter/src/rules/eslint/no_useless_backreference.rs (1)

239-241: 💡 Verification agent

🧩 Analysis chain

Address the TODO comment about unmappable backreferences.

There's still an unresolved TODO comment about handling unmappable backreferences. This should be documented with a clear explanation.

Based on ESLint behavior, please replace the TODO with an explanation like:

-        // TODO: is this right? what happens when we can't map back ref to a capture group
+        // We return None for unmappable backreferences as they're not considered problematic.
+        // This aligns with ESLint's behavior where unmatched backreferences are ignored
+        // by this rule, as they're often handled by other rules or syntax validation.

🏁 Script executed:

#!/bin/bash
# Search for ESLint's implementation to understand how it handles unmappable backreferences
rg -A 3 "can't map back ref|unmapped reference|unmatched group" --type rust

Length of output: 452


🌐 Web query:

In ESLint’s no-useless-backreference rule implementation, how are unmatched or unmappable backreferences handled?

💡 Result:

ESLint's no-useless-backreference rule specifically targets backreferences in regular expressions that are syntactically valid but functionally useless because they can only match zero-length strings and cannot match anything else. These backreferences are essentially ignored by the regex engine and can be safely removed.

Types of Useless Backreferences

The rule identifies several scenarios where backreferences become useless:

  1. Backreferences to groups in another alternative
    When a backreference refers to a capturing group that exists in a different alternative branch, such as /(a)|\1b/, the backreference attempts to match what was captured in a non-participating group[1].

  2. Forward references
    Backreferences to groups that appear later in the pattern, like /\1(a)/. In this case, the group hasn't captured anything yet, and ECMAScript doesn't support forward references[1].

  3. Self-references within a group
    Backreferences to a group from within the same group, such as /(\1)/. Similar to forward references, the group hasn't captured anything when the backreference is encountered[1].

  4. References to negative lookaround groups
    Backreferences to groups within negative lookarounds (when the backreference isn't in the same negative lookaround), such as /a(?!(b)).\1/. Since negative lookarounds succeed only when their pattern fails to match, the group has effectively failed to capture anything[1].

How These Backreferences Behave

When a backreference refers to an unmatched or unmappable capturing group (as in the cases above), the backreference will always succeed by matching an empty string (zero-length)[7]. This behavior is specified in the JavaScript regex engine:

/(?:a|(b))\1c/.test("ac"); // true
/\1(a)/.test("a"); // true

In these examples, the backreference \1 refers to either an unmatched group or a group that hasn't been encountered yet, so it successfully matches an empty string[7].

Rule Implementation Details

The ESLint rule was introduced in ESLint v7.0.0-alpha.0[1] and aims to detect these scenarios where backreferences are parsed as valid syntax but are functionally useless. The rule helps prevent potential errors in regular expressions by flagging patterns that are likely mistakes rather than intentional code.

It's important to note that in Unicode-unaware mode, invalid backreferences are treated differently - they become legacy octal escape sequences (a deprecated syntax maintained for web compatibility)[7]. This behavior is not the primary target of the rule, which focuses on syntactically valid but functionally useless backreferences.

The rule performs static analysis of regular expression patterns to identify these cases, helping developers write more efficient and error-free regular expressions by eliminating constructs that have no functional impact on the matching behavior.

Citations:


🏁 Script executed:

#!/bin/bash
# Display context around the TODO in the no_useless_backreference rule
sed -n '200,260p' crates/oxc_linter/src/rules/eslint/no_useless_backreference.rs

Length of output: 2550


Document handling of unmappable backreferences

Replace the existing TODO with a clear explanation that we deliberately ignore backreferences which can’t be resolved to a capture group:

--- a/crates/oxc_linter/src/rules/eslint/no_useless_backreference.rs
+++ b/crates/oxc_linter/src/rules/eslint/no_useless_backreference.rs
@@ fn problems_for_backref<'a>(...)
-    let Some(cap_group) = cap_group else {
-        // TODO: is this right? what happens when we can't map back ref to a capture group
-        return None;
-    };
+    let Some(cap_group) = cap_group else {
+        // Unmappable backrefs (no matching capture group) are interpreted by the JS regex
+        // engine as matching an empty string and are not considered “useless” by this rule.
+        // Such syntax errors or legacy octals are handled by the parser or by other rules.
+        return None;
+    };
  • File: crates/oxc_linter/src/rules/eslint/no_useless_backreference.rs
  • Lines: 207–213
🧹 Nitpick comments (3)
crates/oxc_linter/src/rules/eslint/no_useless_backreference.rs (3)

258-289: Consider adding a comment to explain the path matching algorithm.

The algorithm for finding the lowest common ancestor and determining if the regex is matching backwards is somewhat complex. A brief comment explaining the overall approach would improve maintainability.

    let index_of_lowest_common_ancestor = {
+       // Find the deepest common ancestor node in the AST paths of both
+       // the backreference and the capture group
        let mut i = 0;
        let mut j = 0;

        while i + 1 < bref.path.len()
            && j + 1 < cap_group.path.len()
            && bref.path[i + 1] == cap_group.path[j + 1]
        {
            i += 1;
            j += 1;
        }
        j + 1
    };

538-539: Consider implementing support for global references.

There's a TODO comment about not supporting global references yet. Consider implementing this feature to provide complete coverage of all ESLint's original rule capabilities.

How does ESLint handle global references in the no-useless-backreference rule?

146-149: Consider using the builder pattern for RegexCollector.

The current implementation initializes all fields in the new() method. For more complex initialization scenarios, you might want to consider a builder pattern in the future.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 02aa62c and 630123d.

⛔ Files ignored due to path filters (45)
  • apps/oxlint/src/snapshots/_--ignore-path fixtures__linter__.customignore --no-ignore [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_--ignore-pattern _____.js --ignore-pattern _____.vue [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_--import-plugin -A all -D no-cycle [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_--import-plugin [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_--vitest-plugin -c fixtures__eslintrc_vitest_replace__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-D correctness [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-W correctness -A no-debugger [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-W no-undef -c fixtures__eslintrc_env__eslintrc_no_env.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-W no-undef -c fixtures__no_undef__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__config_ignore_patterns__ignore_extension__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__eslintrc_env__eslintrc_env_browser.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__eslintrc_off__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__eslintrc_vitest_replace__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__linter__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__no_console_off__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__no_empty_allow_empty_catch__eslintrc.json -W no-empty [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__no_empty_disallow_empty_catch__eslintrc.json -W no-empty [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__overrides__.oxlintrc.json fixtures__overrides__test.js -c fixtures__overrides__.oxlintrc.json fixtures__overrides__test.ts -c fixtures__overrides__.oxlintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__overrides__directories-config.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__typescript_eslint__eslintrc.json --disable-typescript-plugin [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_-c fixtures__typescript_eslint__eslintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/_fixtures__linter__debugger.js [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__config_ignore_patterns__ignore_directory_-c [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__config_ignore_patterns__with_oxlintrc_-c .__test__eslintrc.json --ignore-pattern _.ts [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__disable_eslint_and_unicorn_alias_rules_-c .oxlintrc-eslint.json test.js -c .oxlintrc-unicorn.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__extends_config_--config extends_rules_config.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__extends_config_--config relative_paths__extends_extends_config.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__ignore_file_current_dir_ [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__import-cycle_--import-plugin -D [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__import_-c .oxlintrc.json test.js -c .oxlintrc-import-x.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/[email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__nested_config_--config [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__nested_config_-A no-console --config [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__overrides_env_globals_-c .oxlintrc.json [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__report_unused_directives_-c .oxlintrc.json --report-unused-disable-directives [email protected] is excluded by !**/*.snap
  • apps/oxlint/src/snapshots/fixtures__two_rules_with_same_rule_name_-c .oxlintrc.json [email protected] is excluded by !**/*.snap
  • crates/oxc_linter/src/snapshots/eslint_no_useless_backreference.snap is excluded by !**/*.snap
📒 Files selected for processing (2)
  • crates/oxc_linter/src/rules.rs (3 hunks)
  • crates/oxc_linter/src/rules/eslint/no_useless_backreference.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/oxc_linter/src/rules.rs
⏰ Context from checks skipped due to timeout of 90000ms (9)
  • GitHub Check: Benchmark (formatter)
  • GitHub Check: Benchmark (codegen)
  • GitHub Check: Benchmark (minifier)
  • GitHub Check: Benchmark (transformer)
  • GitHub Check: Benchmark (parser)
  • GitHub Check: Build Linter Benchmark
  • GitHub Check: Clippy
  • GitHub Check: Test Linux
  • GitHub Check: Test NAPI
🔇 Additional comments (7)
crates/oxc_linter/src/rules/eslint/no_useless_backreference.rs (7)

229-229: Great job fixing the typo in the comment.

The comment now correctly uses "backreference" instead of "backrefernce" as noted in a previous review.


21-25: The diagnostic messages are now correctly aligned with their problem types.

The error messages now properly describe each problem scenario, addressing the previous mismatch between Problem::Disjunctive and Problem::Backward descriptions.


32-69: Excellent documentation for the lint rule.

The documentation is comprehensive and well-structured:

  • Clear explanation of what the rule does
  • Detailed rationale for why useless backreferences are problematic
  • Helpful examples of both incorrect and correct code

197-223: Well-documented problem types with clear examples.

The comments explaining each problem type include illustrative examples and clear explanations of why each backreference case is problematic. This will be very helpful for maintainers and contributors.


71-91: Implementation follows the standard pattern for lint rules.

The rule implementation is clean and follows the established pattern for OXC linter rules, using the visitor pattern appropriately.


350-554: Comprehensive test suite.

The test suite is extensive, covering a wide range of valid and invalid regex patterns. This will help ensure the rule works correctly and remains robust against future changes.


1-12: Well-structured imports that follow the codebase conventions.

The imports are appropriately organized and include all necessary components for implementing a lint rule.

@Boshen Boshen requested a review from leaysgur May 4, 2025 00:50
@leaysgur
Copy link
Member

leaysgur commented May 4, 2025

(Noticed the assignment, but it will be a little while before I can look into it since AFK until Tuesday for a holiday. If you have any problems, please go ahead and I will catch up later!)

Copy link
Member

@leaysgur leaysgur left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, except for the part I commented about TODO.
(Feel free to merge after you fix it~.)

@Boshen Boshen assigned camc314 and unassigned leaysgur May 7, 2025
@camc314 camc314 force-pushed the c/05-02-feat_linter_regex_no-useless-backref branch from 630123d to 53ffdd4 Compare May 7, 2025 08:32
@camc314 camc314 added the 0-merge Merge with Graphite Merge Queue label May 7, 2025
Copy link
Contributor Author

camc314 commented May 7, 2025

Merge activity

  • May 7, 4:33 AM EDT: The merge label '0-merge' was detected. This PR will be added to the Graphite merge queue once it meets the requirements.
  • May 7, 4:33 AM EDT: The merge label '0-merge' was detected. This PR will be added to the Graphite merge queue once it meets the requirements.
  • May 7, 4:39 AM EDT: camc314 added this pull request to the Graphite merge queue.
  • May 7, 4:46 AM EDT: Merged by the Graphite merge queue.

@graphite-app graphite-app bot force-pushed the c/05-02-feat_linter_regex_no-useless-backref branch from 53ffdd4 to 4c62348 Compare May 7, 2025 08:39
@graphite-app graphite-app bot merged commit 4c62348 into main May 7, 2025
25 checks passed
@graphite-app graphite-app bot deleted the c/05-02-feat_linter_regex_no-useless-backref branch May 7, 2025 08:46
@graphite-app graphite-app bot removed the 0-merge Merge with Graphite Merge Queue label May 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-cli Area - CLI A-linter Area - Linter C-enhancement Category - New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants