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 accurately cover inserted text while automatic fixes replace the original range, so reported locations and applied fixes align correctly in diffs.

@changeset-bot
Copy link

changeset-bot bot commented Oct 30, 2025

⚠️ No Changeset found

Latest commit: 9ec8fa3

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

@coderabbitai
Copy link

coderabbitai bot commented Oct 30, 2025

Walkthrough

reportDifference in eslint-plugin-prettier.js now computes a two-value highlight window (start = offset, end = offset + (deleteText.length || min(insertText.length,1))), introduces replaceRange = [offset, offset + deleteText.length], derives loc from the highlight window, and uses replaceRange for the fixer.

Changes

Cohort / File(s) Summary
Diff highlighting and replacement logic
eslint-plugin-prettier.js
In reportDifference, set highlightStart = offset and `highlightEnd = offset + (deleteText.length

Sequence Diagram(s)

sequenceDiagram
    participant Linter
    participant reportDifference
    participant Fixer

    Linter->>reportDifference: provide offset, deleteText, insertText
    reportDifference->>reportDifference: highlightStart = offset
    reportDifference->>reportDifference: highlightEnd = offset + (deleteText.length || min(insertText.length,1))
    reportDifference->>reportDifference: replaceRange = [offset, offset + deleteText.length]
    reportDifference->>reportDifference: loc = getLocFromIndex(sourceCode, highlightStart/End)
    reportDifference->>Fixer: register fix using replaceRange
    Fixer-->>Linter: fix applied or suggested
    note right of reportDifference #DFF7DF: highlight window may expand for insertions\nfixer uses dedicated replace range
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

  • Check edge cases: zero-length delete, zero-length insert, multi-char insert.
  • Verify replaceRange shape matches the fixer API and that location mapping (getLocFromIndex) displays expected positions.
  • Run relevant tests or sample diffs to confirm behavior.

Poem

🐰 A hop to mark where text may grow,

I set a span and only replace what's owed,
A careful nibble, a tidy swap,
Highlight bright, then hop off the block. ✨

Pre-merge checks and finishing touches

✅ 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 "fix: add range offset for insertion suggestion" accurately captures the main change in the PR. The changeset's primary purpose is to fix a zero-length range issue by introducing a range offset mechanism (insertSuggestionOffset) specifically for insertion scenarios. The title is clear, specific, and concise, directly conveying that the PR adds a range offset feature to handle insertion suggestions properly, which aligns perfectly with the stated objectives and the file-level changes.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4c93d1b and 9ec8fa3.

📒 Files selected for processing (1)
  • eslint-plugin-prettier.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • eslint-plugin-prettier.js

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.

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.

1 participant