Skip to content

fix(linter): prevent duplicate fix insertions when multiple tsconfigs match the same file#452

Merged
fansenze merged 1 commit intomainfrom
fix/issue-451-duplicate-async-insertion
Feb 2, 2026
Merged

fix(linter): prevent duplicate fix insertions when multiple tsconfigs match the same file#452
fansenze merged 1 commit intomainfrom
fix/issue-451-duplicate-async-insertion

Conversation

@fansenze
Copy link
Copy Markdown
Contributor

@fansenze fansenze commented Feb 2, 2026

Summary

Problem

When a file is matched by multiple tsconfig projects (e.g., tsconfig.json and tsconfig.app.json), each project reports the same diagnostic independently. This causes the auto-fixer to apply the same fix multiple times, resulting in incorrect output like async async async function render().

Root Cause

The original conflict detection logic only checked lastFixEnd > pos, which works for overlapping replacement fixes but fails to detect duplicate insertions. For insertion operations where pos == end, after applying the first insertion, lastFixEnd equals pos (not greater than), so subsequent duplicate insertions were not detected as conflicts.

Solution

Improved the fix conflict detection in ApplyRuleFixes to properly handle insertion operations:

  1. Added lastWasInsertion flag to track whether the previous fix was an insertion
  2. Enhanced conflict detection: skip fixes when lastFixEnd == pos AND either current or previous fix is an insertion
  3. Adjacent replacement fixes (end == start) are still allowed since they operate on non-overlapping ranges

Fix Conflict Strategy

Scenario Behavior Reason
Replace [0,3]Replace [3,6] Both applied Adjacent replacements, non-overlapping [0,3) and [3,6)
Insert at 0Insert at 0 Skip second Duplicate insertion
Insert at 0Replace [0,3] Skip replacement Replacement starts at insertion position
Replace [0,3]Insert at 3 Skip insertion Ambiguous position after replacement

This strategy is more precise than ESLint's approach (which uses lastPos >= start and skips all adjacent fixes). Our implementation correctly allows adjacent replacement fixes while preventing duplicate insertions and position conflicts.

Related Links

Checklist

  • Tests updated (or not required).
  • Documentation updated (or not required).

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @fansenze, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request resolves a critical bug in the linter's auto-fixer that caused unintended code duplication when multiple configuration files applied the same diagnostic fix to a single source file. The core change involves refining the fix conflict detection mechanism to accurately identify and prevent redundant insertion operations, ensuring that auto-fixes are applied cleanly and correctly without introducing artifacts.

Highlights

  • Problem Addressed: Fixed an issue where the linter's auto-fixer would apply the same fix multiple times, leading to incorrect code (e.g., 'async async async function') when a file was matched by multiple tsconfig projects.
  • Root Cause Identified: The previous conflict detection logic (lastFixEnd > pos) was insufficient for insertion operations where the fix position (pos) and end position (end) were identical. This allowed duplicate insertions at the same point to go undetected.
  • Enhanced Fix Conflict Detection: Introduced a lastWasInsertion flag and updated the conflict detection condition. Now, a fix is skipped if lastFixEnd == pos AND either the current fix or the previous fix was an insertion, preventing duplicate insertions and ambiguous position conflicts.
  • Improved Fix Strategy: The new strategy correctly allows adjacent replacement fixes (where one ends and the next begins at the same position) while preventing duplicate insertions and conflicts between insertions and replacements at the same boundary.
  • Comprehensive Testing: Added a new test file with extensive unit tests covering various fix scenarios, including single/multiple insertions, overlapping/consecutive/adjacent replacements, mixed fix types, edge cases, and a specific regression test for the duplicate insertion problem.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request effectively addresses a bug that caused duplicate auto-fixes when a file is processed by multiple tsconfig projects. The core change introduces more sophisticated conflict detection logic that correctly handles overlapping and adjacent fixes, particularly for insertion operations. The solution is robust and is supported by an excellent and comprehensive set of new tests, including a specific regression test for the issue. The code is well-commented and the logic appears sound. I have one minor suggestion to improve the readability of the new conflict detection logic.

… match the same file

When a file is matched by multiple tsconfig projects, the same diagnostic
is reported multiple times, leading to duplicate fix insertions (e.g.,
"async async async function").

This change improves the fix conflict detection logic to properly handle
insertion operations (where pos == end). The key changes:

1. Track whether the previous fix was an insertion via `lastWasInsertion`
2. Skip fixes when `lastFixEnd == pos` and either current or previous fix
   is an insertion (prevents duplicate insertions and position conflicts)
3. Allow adjacent replacement fixes (end == start) since they don't overlap

Also adds comprehensive test cases for the fix application logic.
@fansenze fansenze merged commit 6a24966 into main Feb 2, 2026
14 checks passed
@fansenze fansenze deleted the fix/issue-451-duplicate-async-insertion branch February 2, 2026 05:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Rslint v0.2.0 Bug - Auto Fixer Incorrectly Inserts Async Keywords

2 participants