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

x/tools/internal/diff: suboptimal line edits for a common prefix #64023

Closed
findleyr opened this issue Nov 8, 2023 · 6 comments
Closed

x/tools/internal/diff: suboptimal line edits for a common prefix #64023

findleyr opened this issue Nov 8, 2023 · 6 comments
Assignees
Labels
gopls Issues related to the Go language server, gopls. Tools This label describes issues relating to any tools in the x/tools repository.
Milestone

Comments

@findleyr
Copy link
Contributor

findleyr commented Nov 8, 2023

Noticed in https://go.dev/cl/539656. The x/tools/internal/diff package produces suboptimal line diffs, in that it generates edits inside of common prefixes.

Here is a minimal example: https://go.dev/play/p/kS7ykVOJzbm

diff.Strings("\n\n", "\n\na\n") // [{Start:0,End:0,New:"\n"} {Start:1,End:1,New:"a"}]

While the edits are valid, I think it's a bug that an edit is inserted inside a common prefix. Pragmatically, it causes the unified diff to be rather confusing. It may also cause non-nonsensical movement of the cursor in gopls, but I've yet to demonstrate this in practice.

At the very least, I think this warrants investigation.

CC @pjweinb @adonovan

@findleyr findleyr added gopls Issues related to the Go language server, gopls. Tools This label describes issues relating to any tools in the x/tools repository. labels Nov 8, 2023
@gopherbot gopherbot added this to the Unreleased milestone Nov 8, 2023
@gopherbot
Copy link

Change https://go.dev/cl/540715 mentions this issue: internal/regtest/marker: use line-based myers diff implementation

@findleyr findleyr modified the milestones: Unreleased, gopls/v0.15.0 Nov 9, 2023
@pjweinb pjweinb assigned adonovan and unassigned pjweinb Nov 9, 2023
@adonovan
Copy link
Member

adonovan commented Nov 9, 2023

@pjweinb, since the problem is in the core of the diff algorithm, on which you are the expert (and not in the ToUnified presentation logic), could you take a look at it? Thanks.

gopherbot pushed a commit to golang/tools that referenced this issue Nov 9, 2023
The new diff.Strings algorithm produces suboptimal line edits, as
described in golang/go#64023, which lead to confusing test data. Switch
our test diff output to the older myers package (ideally temporarily).

Change-Id: I2327f5551db795dac47c6c8f2a936a5ce49ab8e0
Reviewed-on: https://go-review.googlesource.com/c/tools/+/540715
Auto-Submit: Robert Findley <rfindley@google.com>
Reviewed-by: Alan Donovan <adonovan@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
@pjweinb
Copy link

pjweinb commented Nov 10, 2023 via email

@findleyr
Copy link
Contributor Author

This is a case where a longest common subsequence doesn't include the
common prefix, and unfortunately the algorithm finds it.

Understood. I think this is why many diff algorithms do a line-based diff first before narrowing to sub-line diffs: when "a\n" is considered as a single unit, the trailing '\n' can't be considered part of a sequence.

Perhaps the simplest fix is to do the same: start by diffing lines, and then do a second sub-line pass on each hunk. This may also lead to better performance.

@gopherbot
Copy link

Change https://go.dev/cl/541382 mentions this issue: internal/diff: respect common prefixes

@pjweinb
Copy link

pjweinb commented Jan 2, 2024

This is perhaps unfortunate, but it is not a bug. The same visibly unfortunate thing can happen without a common prefix: diff(xyAA, yyAABA) has the same problem of not returning a minimal diff and being small enough to be dissatisfying to a human observer.

@findleyr findleyr modified the milestones: gopls/v0.15.0, gopls/v0.16.0 Jan 17, 2024
@pjweinb pjweinb closed this as completed Feb 4, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
gopls Issues related to the Go language server, gopls. Tools This label describes issues relating to any tools in the x/tools repository.
Projects
None yet
Development

No branches or pull requests

4 participants