Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix replacement edit range computation #12171

Merged
merged 1 commit into from
Jul 4, 2024
Merged

Conversation

dhruvmanila
Copy link
Member

Summary

This PR fixes various bugs for computing the replacement range between the original and modified source for the language server.

  1. When finding the end offset of the source and modified range, we should apply zip on the reversed iterator. The bug was that it was reversing the already zipped iterator. The problem here is that the length of both slices aren't going to be the same unless the source wasn't modified at all. Refer to the Rust playground where you can see this in action.
  2. Skip the first line when computing the start offset because the first line start value will always be 0 and the default value of the source / modified range start is also 0. So, comparing 0 and 0 is not useful which means we can skip the first value.
  3. While iterating in the reverse direction, we should only stop if the line start is strictly less than the source start i.e., we should use < instead of <=.

fixes: #12128

Test Plan

Add test cases where the text is being inserted, deleted, and replaced between the original and new source code, validate the replacement ranges.

@dhruvmanila dhruvmanila added the bug Something isn't working label Jul 3, 2024
Comment on lines +24 to +25
.zip(modified_line_starts.iter().copied())
.skip(1)
Copy link
Member Author

Choose a reason for hiding this comment

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

Skipping the first line start i.e., change (2)

Copy link
Member

Choose a reason for hiding this comment

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

Is it guaranteed that source_line_starts[0] == TextSize::new(0)?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes:

impl LineIndex {
/// Builds the [`LineIndex`] from the source text of a file.
pub fn from_source_text(text: &str) -> Self {
let mut line_starts: Vec<TextSize> = Vec::with_capacity(text.len() / 88);
line_starts.push(TextSize::default());

Comment on lines -38 to +43
for (old_line_start, new_line_start) in line_iter.by_ref() {
if old_line_start <= source_start
|| new_line_start <= replaced_start
|| source[TextRange::new(old_line_start, source_end)]
!= modified[TextRange::new(new_line_start, replaced_end)]
for (source_line_start, modified_line_start) in source_line_starts
.iter()
.rev()
.copied()
.zip(modified_line_starts.iter().rev().copied())
Copy link
Member Author

Choose a reason for hiding this comment

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

The zip and rev bug u.e., change (1)

Comment on lines -38 to +46
for (old_line_start, new_line_start) in line_iter.by_ref() {
if old_line_start <= source_start
|| new_line_start <= replaced_start
|| source[TextRange::new(old_line_start, source_end)]
!= modified[TextRange::new(new_line_start, replaced_end)]
for (source_line_start, modified_line_start) in source_line_starts
.iter()
.rev()
.copied()
.zip(modified_line_starts.iter().rev().copied())
{
if source_line_start < source_start
|| modified_line_start < modified_start
Copy link
Member Author

Choose a reason for hiding this comment

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

Switching from <= to < i.e., change (3)

@MichaReiser MichaReiser added the server Related to the LSP server label Jul 3, 2024
Comment on lines +24 to +25
.zip(modified_line_starts.iter().copied())
.skip(1)
Copy link
Member

Choose a reason for hiding this comment

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

Is it guaranteed that source_line_starts[0] == TextSize::new(0)?

Copy link
Contributor

github-actions bot commented Jul 3, 2024

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

@dhruvmanila dhruvmanila merged commit d870720 into main Jul 4, 2024
20 checks passed
@dhruvmanila dhruvmanila deleted the dhruv/fix-replacement branch July 4, 2024 03:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working server Related to the LSP server
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cursor jumps to bottom of file when auto-formatting on save
2 participants