Skip to content

x/tools/gopls: FoldingRange omitempty causes EndCharacter=0 to be omitted, changing its semantics in clients that distinguish 0 from missing #71489

Closed
@jansorg

Description

@jansorg

gopls version

Build info
----------
golang.org/x/tools/gopls (devel)
    golang.org/x/tools/gopls@(devel)
    github.com/BurntSushi/[email protected] h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs=
    github.com/google/[email protected] h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
    golang.org/x/exp/[email protected] h1:1P7xPZEwZMoBoz0Yze5Nx2/4pxj6nw9ZqHWXqP0iRgQ=
    golang.org/x/[email protected] h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
    golang.org/x/[email protected] h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
    golang.org/x/[email protected] h1:TCDqnvbBsFapViksHcHySl/sW4+rTGNIAoJJesHRuMM=
    golang.org/x/[email protected] h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
    golang.org/x/[email protected] h1:kgwdasJRsdDWYgWcEgMF424DiXwwXHSb3V8xVTi//i8=
    golang.org/x/[email protected] h1:SP0mPeg2PmGCu03V+61EcQiOjmpri2XijexKdzv8Z1I=
    honnef.co/go/[email protected] h1:4bH5o3b5ZULQ4UrBmP+63W9r7qIkqJClEA9ko5YKx+I=
    mvdan.cc/[email protected] h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU=
    mvdan.cc/xurls/[email protected] h1:lyBNOm8Wo71UknhUs4QTFUNNMyxy2JEIaKKo0RWOh+8=
go: go1.23.4

go env

GO111MODULE=''
GOARCH='amd64'
GOBIN=''
GOCACHE='/home/jansorg/.cache/go-build'
GOENV='/home/jansorg/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMODCACHE='/home/jansorg/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/jansorg/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/lib/go'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/lib/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.23.5'
GODEBUG=''
GOTELEMETRY='local'
GOTELEMETRYDIR='/home/jansorg/.config/go/telemetry'
GCCGO='gccgo'
GOAMD64='v1'
AR='ar'
CC='gcc'
CXX='g++'
CGO_ENABLED='1'
GOMOD='/dev/null'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build2443791054=/tmp/go-build -gno-record-gcc-switches'

What did you do?

I requested the folding ranges for this .go file:

package main

import (
	"flag"
	"fmt"
)

func foo() {
}

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:
Image

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.

// LineStart returns the [Pos] value of the start of the specified line.
// It ignores any alternative positions set using [File.AddLineColumnInfo].
// LineStart panics if the 1-based line number is invalid.
func (f *File) LineStart(line int) Pos {

https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocuments

A position inside a document (see Position definition below) is expressed as a zero-based line and character offset.

Editor and settings

No response

Logs

No response

Metadata

Metadata

Assignees

Labels

BugReportIssues describing a possible bug in the Go implementation.DocumentationIssues describing a change to documentation.ToolsThis label describes issues relating to any tools in the x/tools repository.goplsIssues related to the Go language server, gopls.

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions