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/gopls: line offset out of range in codeAction response #37702

Closed
bstaletic opened this issue Mar 5, 2020 · 25 comments
Closed

x/tools/gopls: line offset out of range in codeAction response #37702

bstaletic opened this issue Mar 5, 2020 · 25 comments
Labels
FrozenDueToAge gopls Issues related to the Go language server, gopls. Tools This label describes issues relating to any tools in the x/tools repository. WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Milestone

Comments

@bstaletic
Copy link

What version of Go are you using (go version)?

$ go version
golang.org/x/tools/gopls v0.3.3
    golang.org/x/tools/gopls@(devel)

Does this issue reproduce with the latest release?

Version 0.3.3 is the latest gopls version. I haven't tried the latest master, to be honest.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/bstaletic/.cache/go-build"
GOENV="/home/bstaletic/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/bstaletic/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/lib/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build561996429=/tmp/go-build -gno-record-gcc-switches"

What did you do?

  1. mkdir test && cd test
  2. go mod init t
  3. echo -en 'package main\nimport ( "fmt" )' > main.go
  4. Open main.go in your favourite editor and make a textDocument/codeAction request from cursor position (0, 0).

What did you expect to see?

"Organize imports" code action, with valid Range objects.

What did you see instead?

The "range" keys in the response contain "line":2, which, considering 0-indexing of the protocol, doesn't exist for the main.go in question. This can cause a lot of troubles in some clients.

Additional info:

  • Complete log of exchanged messages:
2020-03-05 23:34:43,116 - DEBUG - TX: Sending message: b'Content-Length: 887\r\n\r\n{"id":1,"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{"textDocument":{"codeAction":{"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["","quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]}}},"completion":{"completionItem":{"documentationFormat":["plaintext","markdown"]},"completionItemKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]}},"hover":{"contentFormat":["plaintext","markdown"]},"signatureHelp":{"signatureInformation":{"documentationFormat":["plaintext","markdown"],"parameterInformation":{"labelOffsetSupport":false}}}},"workspace":{"applyEdit":true,"documentChanges":true}},"initializationOptions":{"fuzzyMatching":false,"hoverKind":"Structured"},"processId":25006,"rootPath":"/home/bstaletic/work/test","rootUri":"file:///home/bstaletic/work/test"}}'
2020-03-05 23:34:43,141 - DEBUG - RX: Received message: b'{"jsonrpc":"2.0","result":{"capabilities":{"textDocumentSync":{"openClose":true,"change":2,"save":{}},"completionProvider":{"triggerCharacters":["."]},"hoverProvider":true,"signatureHelpProvider":{"triggerCharacters":["(",","]},"definitionProvider":true,"typeDefinitionProvider":true,"implementationProvider":true,"referencesProvider":true,"documentHighlightProvider":true,"documentSymbolProvider":true,"codeActionProvider":{"codeActionKinds":["quickfix","source.organizeImports"]},"codeLensProvider":{},"documentLinkProvider":{},"workspaceSymbolProvider":true,"documentFormattingProvider":true,"documentOnTypeFormattingProvider":{"firstTriggerCharacter":""},"renameProvider":true,"foldingRangeProvider":true,"executeCommandProvider":{"commands":["tidy","upgrade.dependency"]},"workspace":{"workspaceFolders":{"supported":true,"changeNotifications":"workspace/didChangeWorkspaceFolders"}}},"serverInfo":{"name":""}},"id":1}'
2020-03-05 23:34:43,142 - DEBUG - TX: Sending notification: b'Content-Length: 52\r\n\r\n{"jsonrpc":"2.0","method":"initialized","params":{}}'
2020-03-05 23:34:43,142 - DEBUG - TX: Sending notification: b'Content-Length: 132\r\n\r\n{"jsonrpc":"2.0","method":"workspace/didChangeConfiguration","params":{"settings":{"fuzzyMatching":false,"hoverKind":"Structured"}}}'
2020-03-05 23:34:43,143 - DEBUG - TX: Sending notification: b'Content-Length: 200\r\n\r\n{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"languageId":"go","text":"package main\\nimport ( \\"fmt\\" )\\n","uri":"file:///home/bstaletic/work/test/main.go","version":1}}}'
2020-03-05 23:34:43,215 - DEBUG - RX: Received message: b'{"jsonrpc":"2.0","method":"window/logMessage","params":{"type":3,"message":"2020/03/05 23:34:43 Build info\\n----------\\ngolang.org/x/tools/gopls v0.3.3\\n    golang.org/x/tools/gopls@(devel)\\n    github.com/BurntSushi/toml@v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=\\n    github.com/sergi/go-diff@v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=\\n    golang.org/x/mod@v0.1.1-0.20191105210325-c90efee705ee h1:WG0RUwxtNT4qqaXX3DPA8zHFNm/D9xaBpxzHt1WcA/E=\\n    golang.org/x/sync@v0.0.0-20190423024810-112230192c58\\n    golang.org/x/tools@v0.0.0-20200227200655-6862ededa516 =\\u003e ../\\n    golang.org/x/xerrors@v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=\\n    honnef.co/go/tools@v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U=\\n    mvdan.cc/xurls/v2@v2.1.0 h1:KaMb5GLhlcSX+e+qhbRJODnUUBvlw01jt4yrjFIHAuA=\\n\\nGo info\\n-------\\ngo version go1.14 linux/amd64\\n\\nGO111MODULE=\\"\\"\\nGOARCH=\\"amd64\\"\\nGOBIN=\\"\\"\\nGOCACHE=\\"/home/bstaletic/.cache/go-build\\"\\nGOENV=\\"/home/bstaletic/.config/go/env\\"\\nGOEXE=\\"\\"\\nGOFLAGS=\\"\\"\\nGOHOSTARCH=\\"amd64\\"\\nGOHOSTOS=\\"linux\\"\\nGOINSECURE=\\"\\"\\nGONOPROXY=\\"\\"\\nGONOSUMDB=\\"\\"\\nGOOS=\\"linux\\"\\nGOPATH=\\"/home/bstaletic/go\\"\\nGOPRIVATE=\\"\\"\\nGOPROXY=\\"https://proxy.golang.org,direct\\"\\nGOROOT=\\"/usr/lib/go\\"\\nGOSUMDB=\\"sum.golang.org\\"\\nGOTMPDIR=\\"\\"\\nGOTOOLDIR=\\"/usr/lib/go/pkg/tool/linux_amd64\\"\\nGCCGO=\\"gccgo\\"\\nAR=\\"ar\\"\\nCC=\\"gcc\\"\\nCXX=\\"g++\\"\\nCGO_ENABLED=\\"1\\"\\nGOMOD=\\"/home/bstaletic/work/test/go.mod\\"\\nCGO_CFLAGS=\\"-g -O2\\"\\nCGO_CPPFLAGS=\\"\\"\\nCGO_CXXFLAGS=\\"-g -O2\\"\\nCGO_FFLAGS=\\"-g -O2\\"\\nCGO_LDFLAGS=\\"-g -O2\\"\\nPKG_CONFIG=\\"pkg-config\\"\\nGOGCCFLAGS=\\"-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build349430410=/tmp/go-build -gno-record-gcc-switches\\"\\n"}}'
2020-03-05 23:34:43,455 - DEBUG - RX: Received message: b'{"jsonrpc":"2.0","method":"window/logMessage","params":{"type":3,"message":"2020/03/05 23:34:43 go/packages.Load\\n\\tsnapshot = 0\\n\\tquery = [./... builtin]\\n\\tpackages = 2"}}'
2020-03-05 23:34:43,730 - DEBUG - RX: Received message: b'{"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///home/bstaletic/work/test/main.go","diagnostics":[{"range":{"start":{"line":1,"character":9},"end":{"line":1,"character":14}},"severity":1,"source":"compiler","message":"\\"fmt\\" imported but not used"}]}}'
2020-03-05 23:34:46,225 - DEBUG - TX: Sending message: b'Content-Length: 240\r\n\r\n{"id":2,"jsonrpc":"2.0","method":"textDocument/codeAction","params":{"context":{"diagnostics":[]},"range":{"end":{"character":12,"line":0},"start":{"character":0,"line":0}},"textDocument":{"uri":"file:///home/bstaletic/work/test/main.go"}}}'
2020-03-05 23:34:46,239 - DEBUG - RX: Received message: b'{"jsonrpc":"2.0","method":"window/logMessage","params":{"type":3,"message":"2020/03/05 23:34:46 12.784925ms for GOROOT= GOPATH=/home/bstaletic/go GO111MODULE= GOPROXY= PWD=/home/bstaletic/work/test go [go env GOMOD]"}}'
2020-03-05 23:34:46,253 - DEBUG - RX: Received message: b'{"jsonrpc":"2.0","method":"window/logMessage","params":{"type":3,"message":"2020/03/05 23:34:46 13.457413ms for GOROOT= GOPATH=/home/bstaletic/go GO111MODULE= GOPROXY= PWD=/home/bstaletic/work/test go [go list -modfile=/tmp/go.test.907449470.mod -m -f {{.Path}}\\n{{.Dir}}\\n{{.GoMod}}\\n{{.GoVersion}}\\n{{range context.ReleaseTags}}{{if eq . \\"go1.14\\"}}{{.}}{{end}}{{end}}\\n]"}}'
2020-03-05 23:34:46,259 - DEBUG - RX: Received message: b'{"jsonrpc":"2.0","method":"window/logMessage","params":{"type":3,"message":"2020/03/05 23:34:46 5.742742ms for GOROOT= GOPATH=/home/bstaletic/go GO111MODULE= GOPROXY= PWD=/home/bstaletic/work/test go [go list -modfile=/tmp/go.test.907449470.mod -m -json ...]"}}'
2020-03-05 23:34:46,259 - DEBUG - RX: Received message: b'{"jsonrpc":"2.0","result":[{"title":"Organize Imports","kind":"source.organizeImports","edit":{"documentChanges":[{"textDocument":{"version":1,"uri":"file:///home/bstaletic/work/test/main.go"},"edits":[{"range":{"start":{"line":0,"character":0},"end":{"line":2,"character":0}},"newText":""},{"range":{"start":{"line":2,"character":0},"end":{"line":2,"character":0}},"newText":"package main"}]}]}}],"id":2}'
  • Just the edit:
[
  {
    "range": {
      "start": {
        "line": 0,
        "character": 0
      },
      "end": {
        "line": 2,
        "character": 0
      }
    },
    "newText": ""
  },
  {
    "range": {
      "start": {
        "line": 2,
        "character": 0
      },
      "end": {
        "line": 2,
        "character": 0
      }
    },
    "newText": "package main"
  }
]

In case the 3rd line exists in the file (actually 1st line after import - not necessarily 3rd), the line offset of 2 is valid and doesn't cause issues.

For reference, this was noticed during the review of a ycmd pull request.

@gopherbot gopherbot added this to the Unreleased milestone Mar 5, 2020
@gopherbot gopherbot added Tools This label describes issues relating to any tools in the x/tools repository. gopls Issues related to the Go language server, gopls. labels Mar 5, 2020
@gopherbot
Copy link
Contributor

Thank you for filing a gopls issue! Please take a look at the Troubleshooting guide, and make sure that you have provided all of the relevant information here.

@stamblerre stamblerre modified the milestones: Unreleased, gopls/v0.4.0 Mar 5, 2020
@stamblerre stamblerre changed the title x/tools/gopls: Line offset out of range in codeAction response x/tools/gopls: line offset out of range in codeAction response Mar 5, 2020
@bstaletic
Copy link
Author

I tried to git bisect gopls.

  • Last known good: gopls/v0.3.0-pre1~397
  • First known bad: gopls/v0.3.0-pre1~299

I couldn't check what's going on with the remaining ~100 commits, because, for the minimal repro, they all hit this line and then gopls just dies.

@stamblerre stamblerre modified the milestones: gopls/v0.4.0, gopls/v0.5.0 Apr 2, 2020
@stamblerre
Copy link
Contributor

Thanks for the report. This actually looks related to #33717, which I had just closed. This does actually seem like a bug though because here there is never a terminal newline on L2.

@ianthehat: This is unexpected behavior, right? I want to confirm with you first because of your comment here: #33717 (comment).

@bstaletic
Copy link
Author

For reference, the way we protect users from this bug is by dropping every code action that has the end of range out of bounds.

@stamblerre
Copy link
Contributor

I would suggest the approach that sublimelsp took: sublimelsp/LSP#717 - that way users still get the correct formatting and code actions applied. The out of bounds line always seems to be an off-by-one.

@stamblerre stamblerre added the NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. label Apr 17, 2020
@puremourning
Copy link

@stamblerre I'm not sure that's the right approach. I mean in the sense that sublime have (regrettably) now made themselves bug-compatible with VSCode. The only eventual result of that is a de facto standard outside of the actual protocol. I don't feel that it's appropriate for all client authors to have to work around issues in servers just because they don't affect VScode.

Unfortunately there seems to be a growing trend amongst language server vendors that the only thing that matters is that it works in vscode, and the protocol is secondary. Of course, that's not compatible with the stated goal of solving the matrix problem.

Of course we realise that gopls is in an experimental state and so accept that there are issues, and that everyone has a backlog/prioirities, etc.. So, can can confirm that this behaviour is incorrect and that solving it in gopls is probably the right approach, rather all client authors working around it? If so, then we'll either just wait for a resolution or perhaps do the fix/investigation ourselves. I'd rather spend time doing that than working around it in my client.

@stamblerre
Copy link
Contributor

@puremourning: I absolutely agree that we should focus on matching the spec rather than the behavior of VS Code. I closed the original issue (#33717) because it was out of date and had a workaround, but this issue does indicate that the edits gopls produces are not incorrect.

I suggest using Sublime's workaround in the meantime because it seems like dropping code actions would be a pretty negative experience for the user.

@bstaletic
Copy link
Author

but this issue does indicate that the edits gopls produces are not incorrect.

Emphasis mine. I'm guessing that was a typo.

I suggest using Sublime's workaround in the meantime because it seems like dropping code actions would be a pretty negative experience for the user.

In my opinion, dropping malformed code actions is a safer bet for client implementers, since it makes fewer assumptions. Specifically, doing a -1 on the range additionally assumes that the error is always off-by-one. That's not an assumption a client can assert on in a unit test. I'm not sure we want to make that assumption, despite the alternative being simply dropping code actions.

@myitcv
Copy link
Member

myitcv commented Apr 17, 2020

Is this definitely still a problem? Because given the steps in the initial description I can't reproduce this (using govim) and c07e33e. The response I get back is:

[]protocol.CodeAction{
     {
         Title:       "Organize Imports",
         Kind:        "source.organizeImports",
         Diagnostics: nil,
         IsPreferred: false,
         Edit:        protocol.WorkspaceEdit{
             Changes:         {},
             DocumentChanges: {
                 {
                     TextDocument: protocol.VersionedTextDocumentIdentifier{
                         Version:                1,
                         TextDocumentIdentifier: protocol.TextDocumentIdentifier{URI:"file:///home/myitcv/gostuff/src/github.com/myitcv/playground/main.go"},
                     },
                     Edits: {
                         {
                             Range: protocol.Range{
                                 Start: protocol.Position{Line:0, Character:12},
                                 End:   protocol.Position{Line:1, Character:16},
                             },
                             NewText: "",
                         },
                     },
                 },
             },
         },
         Command: (*protocol.Command)(nil),
     },
 }

@bstaletic
Copy link
Author

The bug is definitely there on v0.4.0. I'll give it a try with the git HEAD.

@myitcv
Copy link
Member

myitcv commented Apr 17, 2020

My guess is that this has to do with how editors deal (or don't deal) with non-zero-length files with no \n at the end of file. Vim, by default, fixes such files to add the missing \n. Hence the file contents as seen by gopls (via govim) are actually "package main\nimport ( "fmt" )\n".

@bstaletic
Copy link
Author

I still see this bug, both on the current HEAD and on c07e33e.

The file contents as seen by gopls are in the original post.

2020-03-05 23:34:43,143 - DEBUG - TX: Sending notification: b'Content-Length: 200\r\n\r\n{"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"languageId":"go","text":"package main\\nimport ( \\"fmt\\" )\\n","uri":"file:///home/bstaletic/work/test/main.go","version":1}}}'

Yes, the file ends with a new line, but that still doesn't mean there are 3 lines.

@myitcv
Copy link
Member

myitcv commented Apr 17, 2020

Then I think we need to focus on why we are seeing different responses from gopls; because I'm only seeing one edit.

@myitcv
Copy link
Member

myitcv commented Apr 17, 2020

Can you post the gopls log for such a session?

@puremourning
Copy link

@myitcv do you have the full log of messages to-from gopls ? I think Boris posted our logs in the OP

@bstaletic
Copy link
Author

@myitcv

Here's the gopls log:

[Trace - 21:54:18.577 PM] Sending request 'initialize - (1)'.
Params: {"capabilities":{"textDocument":{"codeAction":{"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["","quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]}}},"completion":{"completionItem":{"documentationFormat":["plaintext","markdown"]},"completionItemKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]}},"hover":{"contentFormat":["plaintext","markdown"]},"signatureHelp":{"signatureInformation":{"documentationFormat":["plaintext","markdown"],"parameterInformation":{"labelOffsetSupport":false}}}},"workspace":{"applyEdit":true,"didChangeWatchedFiles":{"dynamicRegistration":true},"documentChanges":true}},"initializationOptions":{"fuzzyMatching":false,"hoverKind":"Structured"},"processId":13952,"rootPath":"/home/bstaletic/work/ycmd/ycmd/tests/go/go_module","rootUri":"file:///home/bstaletic/work/ycmd/ycmd/tests/go/go_module"}


[Trace - 21:54:18.583 PM] Received response 'initialize - (1)' in 6ms.
Result: {"capabilities":{"textDocumentSync":{"openClose":true,"change":2,"save":{}},"completionProvider":{"triggerCharacters":["."]},"hoverProvider":true,"signatureHelpProvider":{"triggerCharacters":["(",","]},"definitionProvider":true,"typeDefinitionProvider":true,"implementationProvider":true,"referencesProvider":true,"documentHighlightProvider":true,"documentSymbolProvider":true,"codeActionProvider":{"codeActionKinds":["quickfix","source.fixAll","source.organizeImports"]},"codeLensProvider":{},"documentLinkProvider":{},"workspaceSymbolProvider":true,"documentFormattingProvider":true,"documentOnTypeFormattingProvider":{"firstTriggerCharacter":""},"renameProvider":true,"foldingRangeProvider":true,"executeCommandProvider":{"commands":["tidy","upgrade.dependency","generate"]},"workspace":{"workspaceFolders":{"supported":true,"changeNotifications":"workspace/didChangeWorkspaceFolders"}}},"serverInfo":{"name":"gopls","version":"Build info\n----------\ngolang.org/x/tools/gopls master\n    golang.org/x/tools/gopls@(devel)\n    github.com/BurntSushi/toml@v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=\n    github.com/sergi/go-diff@v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=\n    golang.org/x/mod@v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=\n    golang.org/x/sync@v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=\n    golang.org/x/tools@v0.0.0-20191130070609-6e064ea0cf2d =\u003e ../\n    golang.org/x/xerrors@v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=\n    honnef.co/go/tools@v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U=\n    mvdan.cc/xurls/v2@v2.1.0 h1:KaMb5GLhlcSX+e+qhbRJODnUUBvlw01jt4yrjFIHAuA=\n\nGo info\n-------\ngo version go1.14.2 linux/amd64\n\n"}}


[Trace - 21:54:18.584 PM] Sending notification 'initialized'.
Params: {}


[Trace - 21:54:18.585 PM] Sending notification 'workspace/didChangeConfiguration'.
Params: {"settings":{"fuzzyMatching":false,"hoverKind":"Structured"}}


[Trace - 21:54:18.585 PM] Received request 'client/registerCapability - (1)'.
Params: {"registrations":[{"id":"workspace/didChangeWatchedFiles","method":"workspace/didChangeWatchedFiles","registerOptions":{"watchers":[{"globPattern":"**/*.go","kind":7}]}}]}


[Trace - 21:54:18.585 PM] Sending notification 'textDocument/didOpen'.
Params: {"textDocument":{"languageId":"go","text":"package main\nimport ( \"fmt\" )\n","uri":"file:///home/bstaletic/work/ycmd/ycmd/tests/go/go_module/fixit_goplsbug.go","version":1}}


[Trace - 21:54:18.588 PM] Sending response 'client/registerCapability - (1)' took 2ms.
Result: {}


[Trace - 21:54:18.594 PM] Received notification 'window/logMessage'.
Params: {"type":3,"message":"2020/04/17 21:54:18 Build info\n----------\ngolang.org/x/tools/gopls master\n    golang.org/x/tools/gopls@(devel)\n    github.com/BurntSushi/toml@v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=\n    github.com/sergi/go-diff@v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=\n    golang.org/x/mod@v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=\n    golang.org/x/sync@v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=\n    golang.org/x/tools@v0.0.0-20191130070609-6e064ea0cf2d =\u003e ../\n    golang.org/x/xerrors@v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=\n    honnef.co/go/tools@v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U=\n    mvdan.cc/xurls/v2@v2.1.0 h1:KaMb5GLhlcSX+e+qhbRJODnUUBvlw01jt4yrjFIHAuA=\n\nGo info\n-------\ngo version go1.14.2 linux/amd64\n\n"}


[Trace - 21:54:18.805 PM] Received notification 'window/logMessage'.
Params: {"type":3,"message":"2020/04/17 21:54:18 go env for /home/bstaletic/work/ycmd/ycmd/tests/go/go_module\n(valid build configuration = true)\n(build flags: [-modfile=/tmp/go.go_module.011613249.mod])\nGO111MODULE=\"\"\nGOARCH=\"amd64\"\nGOBIN=\"\"\nGOCACHE=\"/home/bstaletic/.cache/go-build\"\nGOENV=\"/home/bstaletic/.config/go/env\"\nGOEXE=\"\"\nGOFLAGS=\"\"\nGOHOSTARCH=\"amd64\"\nGOHOSTOS=\"linux\"\nGOINSECURE=\"\"\nGONOPROXY=\"\"\nGONOSUMDB=\"\"\nGOOS=\"linux\"\nGOPATH=\"/home/bstaletic/go\"\nGOPRIVATE=\"\"\nGOPROXY=\"https://proxy.golang.org,direct\"\nGOROOT=\"/usr/lib/go\"\nGOSUMDB=\"sum.golang.org\"\nGOTMPDIR=\"\"\nGOTOOLDIR=\"/usr/lib/go/pkg/tool/linux_amd64\"\nGCCGO=\"gccgo\"\nAR=\"ar\"\nCC=\"gcc\"\nCXX=\"g++\"\nCGO_ENABLED=\"1\"\nGOMOD=\"/home/bstaletic/work/ycmd/ycmd/tests/go/go_module/go.mod\"\nCGO_CFLAGS=\"-g -O2\"\nCGO_CPPFLAGS=\"\"\nCGO_CXXFLAGS=\"-g -O2\"\nCGO_FFLAGS=\"-g -O2\"\nCGO_LDFLAGS=\"-g -O2\"\nPKG_CONFIG=\"pkg-config\"\nGOGCCFLAGS=\"-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build541351741=/tmp/go-build -gno-record-gcc-switches\"\n"}


[Trace - 21:54:18.852 PM] Received notification 'window/logMessage'.
Params: {"type":3,"message":"2020/04/17 21:54:18 go/packages.Load\n\tsnapshot=0\n\tdirectory=/home/bstaletic/work/ycmd/ycmd/tests/go/go_module\n\tquery=[./... builtin]\n\tpackages=4"}


[Trace - 21:54:19.131 PM] Received notification 'textDocument/publishDiagnostics'.
Params: {"uri":"file:///home/bstaletic/work/ycmd/ycmd/tests/go/go_module/td/signature_help.go","diagnostics":[{"range":{"start":{"line":11,"character":0},"end":{"line":11,"character":0}},"severity":1,"source":"syntax","message":"expected operand, found '}'"}]}


[Trace - 21:54:19.131 PM] Received notification 'textDocument/publishDiagnostics'.
Params: {"uri":"file:///home/bstaletic/work/ycmd/ycmd/tests/go/go_module/td/test.go","diagnostics":[{"range":{"start":{"line":9,"character":5},"end":{"line":9,"character":8}},"severity":1,"source":"compiler","message":"Log not declared by package log"}]}


[Trace - 21:54:19.132 PM] Received notification 'textDocument/publishDiagnostics'.
Params: {"uri":"file:///home/bstaletic/work/ycmd/ycmd/tests/go/go_module/unicode/unicode.go","diagnostics":[{"range":{"start":{"line":12,"character":12},"end":{"line":12,"character":12}},"severity":1,"source":"syntax","message":"expected selector or type assertion, found '}'"}]}


[Trace - 21:54:19.132 PM] Received notification 'textDocument/publishDiagnostics'.
Params: {"uri":"file:///home/bstaletic/work/ycmd/ycmd/tests/go/go_module/fixit.go","diagnostics":[{"range":{"start":{"line":1,"character":9},"end":{"line":1,"character":14}},"severity":1,"source":"compiler","message":"\"fmt\" imported but not used"}]}


[Trace - 21:54:19.132 PM] Received notification 'textDocument/publishDiagnostics'.
Params: {"uri":"file:///home/bstaletic/work/ycmd/ycmd/tests/go/go_module/fixit_goplsbug.go","diagnostics":[{"range":{"start":{"line":1,"character":9},"end":{"line":1,"character":14}},"severity":1,"source":"compiler","message":"\"fmt\" imported but not used"}]}


[Trace - 21:54:19.132 PM] Received notification 'textDocument/publishDiagnostics'.
Params: {"uri":"file:///home/bstaletic/work/ycmd/ycmd/tests/go/go_module/goto.go","diagnostics":[{"range":{"start":{"line":11,"character":4},"end":{"line":11,"character":20}},"severity":1,"source":"compiler","message":"undeclared name: diagnostics_test"}]}


[Trace - 21:55:03.691 PM] Sending request 'textDocument/codeAction - (2)'.
Params: {"context":{"diagnostics":[{"message":"\"fmt\" imported but not used","range":{"end":{"character":14,"line":1},"start":{"character":9,"line":1}},"severity":1,"source":"compiler"}]},"range":{"end":{"character":14,"line":1},"start":{"character":9,"line":1}},"textDocument":{"uri":"file:///home/bstaletic/work/ycmd/ycmd/tests/go/go_module/fixit_goplsbug.go"}}


[Trace - 21:55:03.717 PM] Received response 'textDocument/codeAction - (2)' in 26ms.
Result: [{"title":"Delete import:  \"fmt\"","kind":"quickfix","diagnostics":[{"range":{"start":{"line":1,"character":9},"end":{"line":1,"character":14}},"severity":1,"source":"compiler","message":"\"fmt\" imported but not used"}],"edit":{"documentChanges":[{"textDocument":{"version":1,"uri":"file:///home/bstaletic/work/ycmd/ycmd/tests/go/go_module/fixit_goplsbug.go"},"edits":[{"range":{"start":{"line":0,"character":0},"end":{"line":2,"character":0}},"newText":""},{"range":{"start":{"line":2,"character":0},"end":{"line":2,"character":0}},"newText":"package main"}]}]}},{"title":"Organize Imports","kind":"source.organizeImports","edit":{"documentChanges":[{"textDocument":{"version":1,"uri":"file:///home/bstaletic/work/ycmd/ycmd/tests/go/go_module/fixit_goplsbug.go"},"edits":[{"range":{"start":{"line":0,"character":0},"end":{"line":2,"character":0}},"newText":""},{"range":{"start":{"line":2,"character":0},"end":{"line":2,"character":0}},"newText":"package main"}]}]}}]


That's with -rpc.trace.

@myitcv
Copy link
Member

myitcv commented Apr 17, 2020

Here is my log: govim.log

@myitcv
Copy link
Member

myitcv commented Apr 17, 2020

It might make comparison a bit easier if you're able to provide a log from a minimal repo; there appear to be diagnostics sent for a whole load of unrelated files.

@bstaletic
Copy link
Author

Here's the log with a minimal repo.

[Trace - 23:41:52.201 PM] Sending request 'initialize - (1)'.
Params: {"capabilities":{"textDocument":{"codeAction":{"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["","quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]}}},"completion":{"completionItem":{"documentationFormat":["plaintext","markdown"]},"completionItemKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]}},"hover":{"contentFormat":["plaintext","markdown"]},"signatureHelp":{"signatureInformation":{"documentationFormat":["plaintext","markdown"],"parameterInformation":{"labelOffsetSupport":false}}}},"workspace":{"applyEdit":true,"didChangeWatchedFiles":{"dynamicRegistration":true},"documentChanges":true}},"initializationOptions":{"fuzzyMatching":false,"hoverKind":"Structured"},"processId":3160,"rootPath":"/home/bstaletic/work/test/go_test","rootUri":"file:///home/bstaletic/work/test/go_test"}


[Trace - 23:41:52.208 PM] Received response 'initialize - (1)' in 6ms.
Result: {"capabilities":{"textDocumentSync":{"openClose":true,"change":2,"save":{}},"completionProvider":{"triggerCharacters":["."]},"hoverProvider":true,"signatureHelpProvider":{"triggerCharacters":["(",","]},"definitionProvider":true,"typeDefinitionProvider":true,"implementationProvider":true,"referencesProvider":true,"documentHighlightProvider":true,"documentSymbolProvider":true,"codeActionProvider":{"codeActionKinds":["quickfix","source.fixAll","source.organizeImports"]},"codeLensProvider":{},"documentLinkProvider":{},"workspaceSymbolProvider":true,"documentFormattingProvider":true,"documentOnTypeFormattingProvider":{"firstTriggerCharacter":""},"renameProvider":true,"foldingRangeProvider":true,"executeCommandProvider":{"commands":["tidy","upgrade.dependency","generate"]},"workspace":{"workspaceFolders":{"supported":true,"changeNotifications":"workspace/didChangeWorkspaceFolders"}}},"serverInfo":{"name":"gopls","version":"Build info\n----------\ngolang.org/x/tools/gopls master\n    golang.org/x/tools/gopls@(devel)\n    github.com/BurntSushi/toml@v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=\n    github.com/sergi/go-diff@v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=\n    golang.org/x/mod@v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=\n    golang.org/x/sync@v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=\n    golang.org/x/tools@v0.0.0-20191130070609-6e064ea0cf2d =\u003e ../\n    golang.org/x/xerrors@v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=\n    honnef.co/go/tools@v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U=\n    mvdan.cc/xurls/v2@v2.1.0 h1:KaMb5GLhlcSX+e+qhbRJODnUUBvlw01jt4yrjFIHAuA=\n\nGo info\n-------\ngo version go1.14.2 linux/amd64\n\n"}}


[Trace - 23:41:52.210 PM] Sending notification 'initialized'.
Params: {}


[Trace - 23:41:52.210 PM] Sending notification 'workspace/didChangeConfiguration'.
Params: {"settings":{"fuzzyMatching":false,"hoverKind":"Structured"}}


[Trace - 23:41:52.210 PM] Received request 'client/registerCapability - (1)'.
Params: {"registrations":[{"id":"workspace/didChangeWatchedFiles","method":"workspace/didChangeWatchedFiles","registerOptions":{"watchers":[{"globPattern":"**/*.go","kind":7}]}}]}


[Trace - 23:41:52.211 PM] Sending notification 'textDocument/didOpen'.
Params: {"textDocument":{"languageId":"go","text":"package main\nimport ( \"fmt\" )\n","uri":"file:///home/bstaletic/work/test/go_test/main.go","version":1}}


[Trace - 23:41:52.213 PM] Sending response 'client/registerCapability - (1)' took 2ms.
Result: {}


[Trace - 23:41:52.218 PM] Received notification 'window/logMessage'.
Params: {"type":3,"message":"2020/04/17 23:41:52 Build info\n----------\ngolang.org/x/tools/gopls master\n    golang.org/x/tools/gopls@(devel)\n    github.com/BurntSushi/toml@v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=\n    github.com/sergi/go-diff@v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=\n    golang.org/x/mod@v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=\n    golang.org/x/sync@v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=\n    golang.org/x/tools@v0.0.0-20191130070609-6e064ea0cf2d =\u003e ../\n    golang.org/x/xerrors@v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=\n    honnef.co/go/tools@v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U=\n    mvdan.cc/xurls/v2@v2.1.0 h1:KaMb5GLhlcSX+e+qhbRJODnUUBvlw01jt4yrjFIHAuA=\n\nGo info\n-------\ngo version go1.14.2 linux/amd64\n\n"}


[Trace - 23:41:52.427 PM] Received notification 'window/logMessage'.
Params: {"type":3,"message":"2020/04/17 23:41:52 go env for /home/bstaletic/work/test/go_test\n(valid build configuration = true)\n(build flags: [-modfile=/tmp/go.go_test.285886661.mod])\nGO111MODULE=\"\"\nGOARCH=\"amd64\"\nGOBIN=\"\"\nGOCACHE=\"/home/bstaletic/.cache/go-build\"\nGOENV=\"/home/bstaletic/.config/go/env\"\nGOEXE=\"\"\nGOFLAGS=\"\"\nGOHOSTARCH=\"amd64\"\nGOHOSTOS=\"linux\"\nGOINSECURE=\"\"\nGONOPROXY=\"\"\nGONOSUMDB=\"\"\nGOOS=\"linux\"\nGOPATH=\"/home/bstaletic/go\"\nGOPRIVATE=\"\"\nGOPROXY=\"https://proxy.golang.org,direct\"\nGOROOT=\"/usr/lib/go\"\nGOSUMDB=\"sum.golang.org\"\nGOTMPDIR=\"\"\nGOTOOLDIR=\"/usr/lib/go/pkg/tool/linux_amd64\"\nGCCGO=\"gccgo\"\nAR=\"ar\"\nCC=\"gcc\"\nCXX=\"g++\"\nCGO_ENABLED=\"1\"\nGOMOD=\"/home/bstaletic/work/test/go_test/go.mod\"\nCGO_CFLAGS=\"-g -O2\"\nCGO_CPPFLAGS=\"\"\nCGO_CXXFLAGS=\"-g -O2\"\nCGO_FFLAGS=\"-g -O2\"\nCGO_LDFLAGS=\"-g -O2\"\nPKG_CONFIG=\"pkg-config\"\nGOGCCFLAGS=\"-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build482885742=/tmp/go-build -gno-record-gcc-switches\"\n"}


[Trace - 23:41:52.477 PM] Received notification 'window/logMessage'.
Params: {"type":3,"message":"2020/04/17 23:41:52 go/packages.Load\n\tsnapshot=0\n\tdirectory=/home/bstaletic/work/test/go_test\n\tquery=[./... builtin]\n\tpackages=2"}


[Trace - 23:41:52.736 PM] Received notification 'textDocument/publishDiagnostics'.
Params: {"uri":"file:///home/bstaletic/work/test/go_test/main.go","diagnostics":[{"range":{"start":{"line":1,"character":9},"end":{"line":1,"character":14}},"severity":1,"source":"compiler","message":"\"fmt\" imported but not used"}]}


[Trace - 23:41:57.923 PM] Sending request 'textDocument/codeAction - (2)'.
Params: {"context":{"diagnostics":[{"message":"\"fmt\" imported but not used","range":{"end":{"character":14,"line":1},"start":{"character":9,"line":1}},"severity":1,"source":"compiler"}]},"range":{"end":{"character":14,"line":1},"start":{"character":9,"line":1}},"textDocument":{"uri":"file:///home/bstaletic/work/test/go_test/main.go"}}


[Trace - 23:41:57.966 PM] Received response 'textDocument/codeAction - (2)' in 42ms.
Result: [{"title":"Delete import:  \"fmt\"","kind":"quickfix","diagnostics":[{"range":{"start":{"line":1,"character":9},"end":{"line":1,"character":14}},"severity":1,"source":"compiler","message":"\"fmt\" imported but not used"}],"edit":{"documentChanges":[{"textDocument":{"version":1,"uri":"file:///home/bstaletic/work/test/go_test/main.go"},"edits":[{"range":{"start":{"line":0,"character":0},"end":{"line":2,"character":0}},"newText":""},{"range":{"start":{"line":2,"character":0},"end":{"line":2,"character":0}},"newText":"package main"}]}]}},{"title":"Organize Imports","kind":"source.organizeImports","edit":{"documentChanges":[{"textDocument":{"version":1,"uri":"file:///home/bstaletic/work/test/go_test/main.go"},"edits":[{"range":{"start":{"line":0,"character":0},"end":{"line":2,"character":0}},"newText":""},{"range":{"start":{"line":2,"character":0},"end":{"line":2,"character":0}},"newText":"package main"}]}]}}]


@gopherbot
Copy link
Contributor

Change https://golang.org/cl/244762 mentions this issue: internal/lsp/regtest: add a failing test for golang/go#37702

@findleyr
Copy link
Contributor

Ok, after bringing myself up to speed on this a bit, I'm not sure I fully understand the problem. Per the spec:

Positions are line end character agnostic. So you can not specify a position that denotes \r|\n or \n| where | represents the character offset

So if we have a file A\nB\n, and want to remove the final line, how exactly are we supposed to do this, without specifying a position on the third line? It is not possible to find a position on the second line that includes the newline. Using | to denote a zero-width position, we could instead delete from A|\nB\n to A\nB|\n, but then that is inconsistent with this (also from the spec):

If you want to specify a range that contains a line including the line ending character(s) then use an end position denoting the start of the next line.

Also, what are we supposed to specify if we want to append C\n to the file? Again, we could insert \nC at A\nB|\n, but it seems silly to do all of this newline juggling.

So what exactly is correct here, per the spec? I can't say that what Gopls is doing is definitely correct, but it also doesn't seem to be incontrovertibly wrong. I can do some research to see what other servers do, but thought I'd first comment to see if anyone had additional evidence on hand.

@myitcv
Copy link
Member

myitcv commented Jul 25, 2020

@findleyr - per our offline conversation, from my perspective (FWIW) gopls is doing the right thing with respect to the spec. It also feels intuitively right, and coincides somewhat with the way that Vim handles this sort of stuff (it is also line-oriented).

So if we have a file A\nB\n, and want to remove the final line, how exactly are we supposed to do this, without specifying a position on the third line?

You can't - I think it's intended you specify an edit that (in your example) is equivalent to setting the range 1:0-2:0 to "" (everything being zero-indexed)

#38274 and microsoft/language-server-protocol#376 are obviously relevant here.

@stamblerre
Copy link
Contributor

Thanks for looking into this, @findleyr and @myitcv. I agree that, based on the spec, it seems like gopls is doing the correct thing. I'll leave this issue open for @bstaletic or @puremourning to weigh in, but I don't think we will change the behavior in gopls.

@stamblerre stamblerre added WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided. and removed NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. labels Jul 26, 2020
@puremourning
Copy link

I think you’re right. The new line is right there in the message. Embarrassingly we can no longer repro the problem anymore so pls feel free to close with our thanks for your input and support.

@stamblerre
Copy link
Contributor

Sounds good - glad this has been resolved!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
FrozenDueToAge gopls Issues related to the Go language server, gopls. Tools This label describes issues relating to any tools in the x/tools repository. WaitingForInfo Issue is not actionable because of missing required information, which needs to be provided.
Projects
None yet
Development

No branches or pull requests

6 participants