Skip to content

Commit 475d9e8

Browse files
committed
[gopls-release-branch.0.5] internal/lsp, go/packages: fix Go 1.15-related overlay bug
Something about the ordering of `go list` results must have changed in Go 1.15, so overlays with test variants were failing to get the correct imports. Technically, the correct solution would have been to support overlays for a package *and* its test variant, but for the purposes of gopls, it's actually more important that the overlays apply to the package itself (rather than its test variant). Fixes golang/go#40685 Change-Id: I3282557502f7f30bf484e1e6c17b90db824bc7d0 Reviewed-on: https://go-review.googlesource.com/c/tools/+/253800 Run-TryBot: Rebecca Stambler <[email protected]> Reviewed-by: Michael Matloob <[email protected]> Reviewed-by: Heschi Kreinick <[email protected]>
1 parent 7296358 commit 475d9e8

File tree

3 files changed

+132
-1
lines changed

3 files changed

+132
-1
lines changed

go/packages/golist_overlay.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,19 @@ func (state *golistState) processGolistOverlay(response *responseDeduper) (modif
8989
// because the file is generated in another directory.
9090
testVariantOf = p
9191
continue nextPackage
92+
} else if !isTestFile && hasTestFiles(p) {
93+
// We're examining a test variant, but the overlaid file is
94+
// a non-test file. Because the overlay implementation
95+
// (currently) only adds a file to one package, skip this
96+
// package, so that we can add the file to the production
97+
// variant of the package. (https://golang.org/issue/36857
98+
// tracks handling overlays on both the production and test
99+
// variant of a package).
100+
continue nextPackage
92101
}
93-
// We must have already seen the package of which this is a test variant.
94102
if pkg != nil && p != pkg && pkg.PkgPath == p.PkgPath {
103+
// We have already seen the production version of the
104+
// for which p is a test variant.
95105
if hasTestFiles(p) {
96106
testVariantOf = pkg
97107
}

go/packages/overlay_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,3 +863,72 @@ func testInvalidXTestInGOPATH(t *testing.T, exporter packagestest.Exporter) {
863863
t.Fatalf("expected at least 2 CompiledGoFiles for %s, got %v", pkg.PkgPath, len(pkg.CompiledGoFiles))
864864
}
865865
}
866+
867+
// Reproduces golang/go#40685.
868+
func TestAddImportInOverlay(t *testing.T) {
869+
packagestest.TestAll(t, testAddImportInOverlay)
870+
}
871+
func testAddImportInOverlay(t *testing.T, exporter packagestest.Exporter) {
872+
exported := packagestest.Export(t, exporter, []packagestest.Module{
873+
{
874+
Name: "golang.org/fake",
875+
Files: map[string]interface{}{
876+
"a/a.go": `package a
877+
878+
import (
879+
"fmt"
880+
)
881+
882+
func _() {
883+
fmt.Println("")
884+
os.Stat("")
885+
}`,
886+
"a/a_test.go": `package a
887+
888+
import (
889+
"os"
890+
"testing"
891+
)
892+
893+
func TestA(t *testing.T) {
894+
os.Stat("")
895+
}`,
896+
},
897+
},
898+
})
899+
defer exported.Cleanup()
900+
901+
exported.Config.Mode = everythingMode
902+
exported.Config.Tests = true
903+
904+
dir := filepath.Dir(exported.File("golang.org/fake", "a/a.go"))
905+
exported.Config.Overlay = map[string][]byte{
906+
filepath.Join(dir, "a.go"): []byte(`package a
907+
908+
import (
909+
"fmt"
910+
"os"
911+
)
912+
913+
func _() {
914+
fmt.Println("")
915+
os.Stat("")
916+
}
917+
`),
918+
}
919+
initial, err := packages.Load(exported.Config, "golang.org/fake/a")
920+
if err != nil {
921+
t.Fatal(err)
922+
}
923+
pkg := initial[0]
924+
var foundOs bool
925+
for _, imp := range pkg.Imports {
926+
if imp.PkgPath == "os" {
927+
foundOs = true
928+
break
929+
}
930+
}
931+
if !foundOs {
932+
t.Fatalf(`expected import "os", found none: %v`, pkg.Imports)
933+
}
934+
}

gopls/internal/regtest/imports_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,13 @@ import (
77
"strings"
88
"testing"
99

10+
"golang.org/x/tools/internal/lsp"
1011
"golang.org/x/tools/internal/lsp/fake"
12+
"golang.org/x/tools/internal/lsp/protocol"
1113
"golang.org/x/tools/internal/testenv"
1214
)
1315

16+
// Tests golang/go#38815.
1417
func TestIssue38815(t *testing.T) {
1518
const needs = `
1619
-- go.mod --
@@ -156,3 +159,52 @@ var _, _ = x.X, y.Y
156159
}
157160
})
158161
}
162+
163+
// Tests golang/go#40685.
164+
func TestAcceptImportsQuickFixTestVariant(t *testing.T) {
165+
const pkg = `
166+
-- go.mod --
167+
module mod.com
168+
169+
go 1.12
170+
-- a/a.go --
171+
package a
172+
173+
import (
174+
"fmt"
175+
)
176+
177+
func _() {
178+
fmt.Println("")
179+
os.Stat("")
180+
}
181+
-- a/a_test.go --
182+
package a
183+
184+
import (
185+
"os"
186+
"testing"
187+
)
188+
189+
func TestA(t *testing.T) {
190+
os.Stat("")
191+
}
192+
`
193+
run(t, pkg, func(t *testing.T, env *Env) {
194+
env.Await(
195+
CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromInitialWorkspaceLoad), 1),
196+
)
197+
env.OpenFile("a/a.go")
198+
metBy := env.Await(
199+
env.DiagnosticAtRegexp("a/a.go", "os.Stat"),
200+
)
201+
d, ok := metBy[0].(*protocol.PublishDiagnosticsParams)
202+
if !ok {
203+
t.Fatalf("expected *protocol.PublishDiagnosticsParams, got %v (%T)", d, d)
204+
}
205+
env.ApplyQuickFixes("a/a.go", d.Diagnostics)
206+
env.Await(
207+
EmptyDiagnostics("a/a.go"),
208+
)
209+
})
210+
}

0 commit comments

Comments
 (0)