Skip to content

Commit

Permalink
feat: On format, apply edits to single lines instead of replacing the…
Browse files Browse the repository at this point in the history
… whole file

Otherwise, vscode will jump to the end of the file every time the user saves

Uses https://github.com/hexops/gotextdiff/ which in turn just copies the code used by the golang LSP: https://github.com/golang/tools/tree/master/internal/lsp/diff

Closes #15

Signed-off-by: Julien Duchesne <[email protected]>
  • Loading branch information
julienduchesne authored and jdbaldry committed Nov 4, 2021
1 parent 5dc8ad9 commit cda483e
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 17 deletions.
14 changes: 14 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: go test
on:
push:
branches:
- main
pull_request: {}
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v2
- run: go test ./...

24 changes: 24 additions & 0 deletions diff.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package main

import (
"github.com/hexops/gotextdiff/myers"
"github.com/hexops/gotextdiff/span"
"github.com/jdbaldry/go-language-server-protocol/lsp/protocol"
)

func getTextEdits(before, after string) []protocol.TextEdit {
edits := myers.ComputeEdits(span.URI("any"), before, after)

var result []protocol.TextEdit
for _, edit := range edits {
result = append(result, protocol.TextEdit{
Range: protocol.Range{
Start: protocol.Position{Line: uint32(edit.Span.Start().Line()) - 1, Character: uint32(edit.Span.Start().Column()) - 1},
End: protocol.Position{Line: uint32(edit.Span.End().Line()) - 1, Character: uint32(edit.Span.End().Column()) - 1},
},
NewText: edit.NewText,
})
}

return result
}
73 changes: 73 additions & 0 deletions diff_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package main

import (
"testing"

"github.com/jdbaldry/go-language-server-protocol/lsp/protocol"
"github.com/stretchr/testify/assert"
)

func TestGetTextEdits(t *testing.T) {
testCases := []struct {
name string
before, after string
expected []protocol.TextEdit
}{
{
name: "delete whole file",
before: "one\ntwo\nthree",
after: "",
expected: []protocol.TextEdit{
{
Range: protocol.Range{
Start: protocol.Position{Line: 0, Character: 0},
End: protocol.Position{Line: 3, Character: 0},
},
NewText: "",
},
},
},
{
name: "add one char (replaces the whole line)",
before: "one\ntwo\nthree",
after: "one\ntwoo\nthree",
expected: []protocol.TextEdit{
{
Range: protocol.Range{
Start: protocol.Position{Line: 1, Character: 0},
End: protocol.Position{Line: 2, Character: 0},
},
NewText: "",
},
{
Range: protocol.Range{
Start: protocol.Position{Line: 2, Character: 0},
End: protocol.Position{Line: 2, Character: 0},
},
NewText: "twoo\n",
},
},
},
{
name: "delete a line",
before: "one\ntwo\nthree",
after: "one\nthree",
expected: []protocol.TextEdit{
{
Range: protocol.Range{
Start: protocol.Position{Line: 1, Character: 0},
End: protocol.Position{Line: 2, Character: 0},
},
NewText: "",
},
},
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
got := getTextEdits(tc.before, tc.after)
assert.Equal(t, tc.expected, got)
})
}
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ go 1.16

require (
github.com/google/go-jsonnet v0.17.0
github.com/hexops/gotextdiff v1.0.3
github.com/jdbaldry/go-language-server-protocol v0.0.0-20211013214444-3022da0884b2
github.com/stretchr/testify v1.4.0
)
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,25 +1,35 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/google/go-jsonnet v0.17.0 h1:/9NIEfhK1NQRKl3sP2536b2+x5HnZMdql7x3yK/l8JY=
github.com/google/go-jsonnet v0.17.0/go.mod h1:sOcuej3UW1vpPTZOr8L7RQimqai1a57bt5j22LzGZCw=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/jdbaldry/go-language-server-protocol v0.0.0-20211013214444-3022da0884b2 h1:t0A10MAY8Z3eeBIBzlzrPpdjsag6Biuxq8iMCHmdGU8=
github.com/jdbaldry/go-language-server-protocol v0.0.0-20211013214444-3022da0884b2/go.mod h1:Hp8QDOEcdn4aDZ+DFTda+smIB0b5MvII4Q0Jo0y2VkA=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
19 changes: 2 additions & 17 deletions server.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,23 +410,8 @@ func (s *server) Formatting(ctx context.Context, params *protocol.DocumentFormat
fmt.Fprintln(os.Stderr, err)
return nil, err
}
// TODO(#15): Consider applying individual edits instead of replacing the whole file when formatting.
return []protocol.TextEdit{
{
Range: protocol.Range{
Start: protocol.Position{Line: 0, Character: 0},
End: protocol.Position{Line: 0, Character: 0},
},
NewText: formatted,
},
{
Range: protocol.Range{
Start: protocol.Position{Line: 0, Character: 0},
End: protocol.Position{Line: uint32(strings.Count(formatted+doc.item.Text, "\n")), Character: ^uint32(0)},
},
NewText: "",
},
}, nil

return getTextEdits(doc.item.Text, formatted), nil
}

func (s *server) Hover(context.Context, *protocol.HoverParams) (*protocol.Hover, error) {
Expand Down

0 comments on commit cda483e

Please sign in to comment.