-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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/gopls: FoldingRange omitempty causes EndCharacter=0 to be omitted, changing its semantics in clients that distinguish 0 from missing #71489
Comments
endLine
of textDocument/foldingRange
is off by 1
This session shows the output of the gopls CLI tool on the same input. The CLI tool and nl both use 1-based numbering.
The first range is between the (...) parens of the import declaration; the second range is between the {...} braces of the function. This all looks correct to me, so I plan to close this issue. I don't know what tool you used to generate the screenshot in the issue. If you think gopls is at fault, please reproduce the problem using VS Code, or the gopls CLI tool, or show the incorrect JSON response from the server, and feel free to reopen this issue. |
@adonovan {
"jsonrpc" : "2.0",
"id" : "42",
"result" : [ {
"startLine" : 2,
"endLine" : 5,
"startCharacter" : 8,
"kind" : "imports"
}, {
"startLine" : 7,
"endLine" : 8,
"startCharacter" : 12
} ]
} The range for the import is this: {
"startLine" : 2,
"endLine" : 5,
"startCharacter" : 8,
"kind" : "imports"
} Property This is different to what The LSP spec on
|
Ah, I see what is happening: the encoding/json schema type is this: type FoldingRange struct {
// The zero-based start line of the range to fold. The folded area starts after the line's last character.
// To be valid, the end must be zero or larger and smaller than the number of lines in the document.
StartLine uint32 `json:"startLine"`
// The zero-based character offset from where the folded range starts. If not defined, defaults to the length of the start line.
StartCharacter uint32 `json:"startCharacter,omitempty"`
// The zero-based end line of the range to fold. The folded area ends with the line's last character.
// To be valid, the end must be zero or larger and smaller than the number of lines in the document.
EndLine uint32 `json:"endLine"`
// The zero-based character offset before the folded range ends. If not defined, defaults to the length of the end line.
EndCharacter uint32 `json:"endCharacter,omitempty"`
...
} and the actual value of EndCharacter is 0, but since the field is marked omitempty, it is not encoded; the client, following the comment, interprets the lack of a field a value as "the length of the end of the line". The problem is that 0 and missing have different semantics in the JSON protocol, but the Go representation cannot distinguish them. We should remove omitempty. Thanks for reporting this. |
endLine
of textDocument/foldingRange
is off by 1
Ah, that makes sense. |
Aside: I notice that the MappedRange abstraction is now almost entirely unnecessary. Will send a CL. |
Change https://go.dev/cl/645815 mentions this issue: |
Change https://go.dev/cl/645855 mentions this issue: |
It has slowly made itself entirely redundant. Updates golang/go#71489 Change-Id: Ib15128b9dc9652c1138a1372ba89c507667e7fcd Reviewed-on: https://go-review.googlesource.com/c/tools/+/645815 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Alan Donovan <adonovan@google.com> Reviewed-by: Robert Findley <rfindley@google.com>
gopls version
go env
What did you do?
I requested the folding ranges for this .go file:
What did you see happen?
The folding range returned by gopls for the
import
lines include the closing)
parenthesis.For this sample code the response returned by gopls is shown in the image (IntelliJ debugger visualization):
foldingRange response:

What did you expect to see?
The folding should end before the closing parenthesis.
I'm writing an LSP client for JetBrains IDEs.
I believe that the response returned by
textDocument/foldingRange
is off by +1, i.e. it should be one less.In the example, the import folding range has
endLine
=5
, which is the line of the closing parenthesis)
.But according to the gopls source code it's supposed to be the end of the line before the closing parenthesis:
https://github.com/golang/tools/blob/e7bd2274d184f7579a8c7a1a12d8ad0351aeee8a/gopls/internal/golang/folding_range.go#L190
As far as I understand, the line returned by
LineStart
is 1-based.But LSP's lines are 0-based.
That means that a 1-based line number is returned as the value of a 0-based line number.
AFAIK VSCode is applying some workarounds, so it's showing something else. And it's only supporting line-based folding, but my client does support all kinds of ranges.
https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocuments
Editor and settings
No response
Logs
No response
The text was updated successfully, but these errors were encountered: