Skip to content

Commit 253fce3

Browse files
committed
internal/lsp: fix formatting edge cases (36824)
One line legal code like `package x; import "os"; func f() {}` was being misformatted. In these cases the parse flag ImportsOnly loses important parts of the code, while full parsing works. Presumably all these cases are short enough that there is no appreciable penalty from the extra parsing. Fixes golang/go#36824 Change-Id: I9a4581d67c590578f8fdea5ed2a2a58e0bc3c40b Reviewed-on: https://go-review.googlesource.com/c/tools/+/234900 Run-TryBot: Peter Weinberger <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Heschi Kreinick <[email protected]>
1 parent 5c6ccfd commit 253fce3

File tree

2 files changed

+38
-8
lines changed

2 files changed

+38
-8
lines changed

internal/lsp/regtest/formatting_test.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ func f() {}
6060

6161
// Tests golang/go#36824.
6262
func TestFormattingOneLineImports36824(t *testing.T) {
63-
t.Skipf("golang/go#36824 has not been fixed yet")
6463

6564
const onelineProgramA = `
6665
-- a.go --
@@ -79,7 +78,28 @@ func f() { fmt.Println() }
7978
got := env.Editor.BufferText("a.go")
8079
want := env.ReadWorkspaceFile("a.go.imported")
8180
if got != want {
82-
t.Errorf("OneLineImports:\n%s", tests.Diff(want, got))
81+
t.Errorf("OneLineImports3824:\n%s", tests.Diff(want, got))
82+
}
83+
})
84+
}
85+
86+
func TestFormattingOneLineRmImports36824(t *testing.T) {
87+
const onelineProgramB = `
88+
-- a.go --
89+
package x; import "os"; func f() {}
90+
91+
-- a.go.imported --
92+
package x
93+
94+
func f() {}
95+
`
96+
runner.Run(t, onelineProgramB, func(t *testing.T, env *Env) {
97+
env.OpenFile("a.go")
98+
env.OrganizeImports("a.go")
99+
got := env.Editor.BufferText("a.go")
100+
want := env.ReadWorkspaceFile("a.go.imported")
101+
if got != want {
102+
t.Errorf("OneLineRmImports:\n%s", tests.Diff(want, got))
83103
}
84104
})
85105
}

internal/lsp/source/format.go

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"go/format"
1313
"go/parser"
1414
"go/token"
15+
"strings"
1516

1617
"golang.org/x/tools/internal/event"
1718
"golang.org/x/tools/internal/imports"
@@ -151,20 +152,29 @@ func computeOneImportFixEdits(ctx context.Context, view View, ph ParseGoHandle,
151152
}
152153

153154
func computeFixEdits(view View, ph ParseGoHandle, options *imports.Options, origData []byte, origMapper *protocol.ColumnMapper, fixes []*imports.ImportFix) ([]protocol.TextEdit, error) {
155+
// trim the original data to match fixedData
156+
left := importPrefix(origData)
157+
extra := strings.Index(left, "\n") == -1 // one line may have more than imports
158+
if extra {
159+
left = string(origData)
160+
}
161+
if len(left) > 0 && left[len(left)-1] != '\n' {
162+
left += "\n"
163+
}
154164
// Apply the fixes and re-parse the file so that we can locate the
155165
// new imports.
156-
fixedData, err := imports.ApplyFixes(fixes, "", origData, options, parser.ImportsOnly)
166+
flags := parser.ImportsOnly
167+
if extra {
168+
// used all of origData above, use all of it here too
169+
flags = 0
170+
}
171+
fixedData, err := imports.ApplyFixes(fixes, "", origData, options, flags)
157172
if err != nil {
158173
return nil, err
159174
}
160175
if fixedData == nil || fixedData[len(fixedData)-1] != '\n' {
161176
fixedData = append(fixedData, '\n') // ApplyFixes may miss the newline, go figure.
162177
}
163-
// trim the original data to match fixedData
164-
left := importPrefix(origData)
165-
if len(left) > 0 && left[len(left)-1] != '\n' {
166-
left += "\n"
167-
}
168178
uri := ph.File().Identity().URI
169179
edits := view.Options().ComputeEdits(uri, left, string(fixedData))
170180
return ToProtocolEdits(origMapper, edits)

0 commit comments

Comments
 (0)