Skip to content

Conversation

@codeshake
Copy link

@codeshake codeshake commented Oct 30, 2025

The issue has started from there: zed-industries/zed#41049

The editor receives a zero range when characters from prettier need to be added. This causes the dropdown menu with actions (fixes) to work incorrectly. I added 1 "ghost" offset index, now it works properly (see video below).

Screen.Recording.2025-10-30.at.13.45.26.mov

Important

Adds a 'ghost' offset in reportDifference() in eslint-plugin-prettier.js to fix dropdown menu behavior for insertion suggestions.

  • Behavior:
    • Adds a 'ghost' offset index for insertion suggestions in reportDifference() in eslint-plugin-prettier.js.
    • Adjusts the range to include the offset when insertText is present, ensuring correct dropdown menu behavior.
  • Functions:
    • Modifies reportDifference() to calculate end with insertSuggestionOffset.
    • Uses getLocFromIndex() to determine start and end positions with the new offset.

This description was created by Ellipsis for 69b4661. You can customize this summary. It will automatically update as commits are pushed.

Summary by CodeRabbit

  • Bug Fixes

    • Improved accuracy of formatting suggestion locations: highlighted spans now show the displayed insertion window while automatic fixes apply only to the exact text range, reducing mismatches between reported positions and applied fixes.
  • Chores

    • Added a changeset for a patch release documenting the insertion-suggestion fix.

✏️ Tip: You can customize this high-level summary in your review settings.

@changeset-bot
Copy link

changeset-bot bot commented Oct 30, 2025

🦋 Changeset detected

Latest commit: 3d8c635

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
eslint-plugin-prettier Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai
Copy link

coderabbitai bot commented Oct 30, 2025

📝 Walkthrough

Walkthrough

reportDifference in eslint-plugin-prettier.js separates the displayed highlight window from the actual replacement range: highlightRange = [offset, offset + Math.max(deleteText.length, 1)] and replaceRange = [offset, offset + deleteText.length]; loc is computed from highlightRange; a patch changeset was added.

Changes

Cohort / File(s) Summary
Diff highlighting and replacement logic
eslint-plugin-prettier.js
Replace single range with highlightRange = [offset, offset + Math.max(deleteText.length, 1)]; introduce replaceRange = [offset, offset + deleteText.length]; compute loc from highlightRange; fixer uses replaceRange.
Release changeset
.changeset/smart-terms-sneeze.md
Add changeset for a patch release: "fix: add range offset for insertion suggestion".

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Poem

🐇 I nibble code with velvet feet,

I mark the span where things should meet,
A tiny range, a gentle nudge,
I swap the text and hop and judge,
Patch in paw — the fix is neat.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and directly describes the main change: fixing insertion suggestion range offset, which matches the primary objective of addressing zero-length range issues for insert operations.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings


📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6a4a546 and 3d8c635.

📒 Files selected for processing (1)
  • eslint-plugin-prettier.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • eslint-plugin-prettier.js
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Agent

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed everything up to 69b4661 in 2 minutes and 6 seconds. Click for details.
  • Reviewed 36 lines of code in 1 files
  • Skipped 0 files when reviewing.
  • Skipped posting 2 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. eslint-plugin-prettier.js:109
  • Draft comment:
    Prefer using a ternary (insertText.length ? 1 : 0) for clarity instead of Math.min(insertText.length, 1).
  • Reason this comment was not posted:
    Confidence changes required: 50% <= threshold 50% None
2. eslint-plugin-prettier.js:125
  • Draft comment:
    Ensure that adding the ghost offset (end + insertSuggestionOffset) does not exceed the source text length. Consider clamping the index if the suggestion is at the very end of the file.
  • Reason this comment was not posted:
    Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 20% vs. threshold = 50% The comment is making a speculative suggestion about potential bounds checking. The diff shows that insertSuggestionOffset is at most 1 (from Math.min(insertText.length, 1)), so we're adding at most 1 to end. The end value comes from offset + deleteText.length, which should be valid indices from the difference calculation. Without seeing evidence that getLocFromIndex fails on out-of-bounds indices, or that the difference calculation can produce invalid offsets, this seems speculative. The comment uses "Consider" language which suggests uncertainty. According to the rules, I should not keep speculative comments that say "If X, then Y is an issue" - only if it's definitely an issue. I might be missing that ESLint's getLocFromIndex or the ponyfill implementation could fail or produce incorrect results with out-of-bounds indices. The ponyfill implementation shown doesn't have explicit bounds checking, so passing an index beyond the text length might produce unexpected results. While the ponyfill might not have explicit bounds checking, there's no evidence in the diff that this is actually causing a problem or that the indices being passed would ever be out of bounds. The difference objects should come from valid text comparisons. This remains a speculative concern without concrete evidence of failure. This comment is speculative and uses "Consider" language without demonstrating that there's an actual bug. It suggests defensive programming but doesn't show strong evidence that the issue occurs. According to the rules, speculative comments should be removed.

Workflow ID: wflow_8LTebGtVsneEozlD

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between befda88 and 69b4661.

📒 Files selected for processing (1)
  • eslint-plugin-prettier.js (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: dotcarmen
PR: prettier/eslint-plugin-prettier#743
File: eslint-plugin-prettier.js:0-0
Timestamp: 2025-06-14T15:04:53.678Z
Learning: In the getLocFromOffset function for eslint-plugin-prettier.js, the correct implementation uses `const withSentinel = [-1, 0, ...lineIndexes]` to create an array of line start positions without variable shadowing, and calculates column as `offset - withSentinel[line]` without additional offsets.
📚 Learning: 2025-06-14T15:04:53.678Z
Learnt from: dotcarmen
PR: prettier/eslint-plugin-prettier#743
File: eslint-plugin-prettier.js:0-0
Timestamp: 2025-06-14T15:04:53.678Z
Learning: In the getLocFromOffset function for eslint-plugin-prettier.js, the correct implementation uses `const withSentinel = [-1, 0, ...lineIndexes]` to create an array of line start positions without variable shadowing, and calculates column as `offset - withSentinel[line]` without additional offsets.

Applied to files:

  • eslint-plugin-prettier.js
🔇 Additional comments (1)
eslint-plugin-prettier.js (1)

124-127: Verify boundary handling and REPLACE operation behavior.

The concern about boundary handling when offset is at the end of the file is valid. Analysis reveals:

  • insertSuggestionOffset is Math.min(insertText.length, 1), so it's either 0 or 1
  • When an INSERT operation occurs at the end of file, loc.end becomes getLocFromIndex(sourceCode, sourceCode.text.length + 1), which is out of bounds
  • The getLocFromIndex ponyfill clamps to the last line and returns a column value equal to (out-of-bounds-index) - (last-line-start), which can exceed the actual line length
  • No tests currently exist for INSERT, DELETE, or REPLACE operations, including boundary cases

While ESLint may accept such positions, this behavior should be explicitly tested to confirm it doesn't cause issues in editors or downstream tools. Additionally, if REPLACE operations intentionally extend the location range beyond deleted text (as mentioned in the original comment), this should be clarified and tested.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Nov 17, 2025

Open in StackBlitz

npm i https://pkg.pr.new/eslint-plugin-prettier@768

commit: 3d8c635

@JounQin JounQin requested a review from BPScott November 17, 2025 02:10
@JounQin JounQin requested a review from Copilot January 14, 2026 10:02
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes an issue where ESLint's dropdown menu for code actions doesn't work correctly when Prettier suggests inserting characters at a zero-width range. The fix separates the highlight range (used for visual indication) from the replace range (used for the actual fix).

Changes:

  • Split the single range variable into highlightRange (for visualization) and replaceRange (for fixes)
  • Added a minimum width of 1 character to highlightRange for insertion suggestions using Math.max(deleteText.length, 1)
  • Added a changeset documenting this patch-level fix

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
eslint-plugin-prettier.js Separates highlight range from replace range, ensuring insertion suggestions have a visible 1-character highlight width while maintaining correct fix behavior
.changeset/smart-terms-sneeze.md Documents the fix as a patch-level change

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

const deleteText = 'deleteText' in difference ? difference.deleteText : '';
/** @type {AST.Range} */
const range = [offset, offset + deleteText.length];
const highlightRange = [offset, offset + Math.max(deleteText.length, 1)];
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

The change to use Math.max(deleteText.length, 1) for highlightRange will modify the behavior of INSERT operations, changing the end position from the insertion point to insertion point + 1. Existing tests in test/prettier.mjs (lines 244-258 and 262-293) expect INSERT operations to have matching start and end columns (e.g., column: 27, endColumn: 27), but this change will make endColumn be column + 1. The tests need to be updated to reflect this new behavior, or this PR will cause test failures.

Copilot uses AI. Check for mistakes.
@JounQin
Copy link
Member

JounQin commented Jan 14, 2026

image image

I tried on VSCode, there is no such issue, so I believe it should be resolved on Zed's ESLint integration instead.

@JounQin JounQin closed this Jan 14, 2026
@codeshake
Copy link
Author

image image

I tried on VSCode, there is no such issue, so I believe it should be resolved on Zed's ESLint integration instead.

What does VSCode have to do with it? The guys from Zed said that this plugin returns indexes [0, 0] (see screenshots with debugging). How does the Zed cursor know that edits should be suggested at this point? It's logically simple.

@codeshake
Copy link
Author

As an example, take a look at how the eslint plugin react hooks works: the array does not contain the required dependencies, but they return the indexes of the array to which the dependencies need to be added. The same logic should be here, but with an empty symbol plus ghost offset. Wdyt?

Screenshot 2026-01-14 at 13 57 41

@JounQin
Copy link
Member

JounQin commented Jan 14, 2026

What does VSCode have to do with it?

The editor experience is powered by vscode-eslint, so it should be handled there.

The same logic should be here, but with an empty symbol plus ghost offset. Wdyt?

The offsets contains [] which is at least 2, right?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants