diff --git a/go/packages/packages114_test.go b/go/packages/packages114_test.go deleted file mode 100644 index d2d5a904aa..0000000000 --- a/go/packages/packages114_test.go +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package packages_test - -import ( - "fmt" - "path/filepath" - "testing" - - "golang.org/x/tools/go/packages" - "golang.org/x/tools/go/packages/packagestest" - "golang.org/x/tools/internal/testenv" -) - -// These tests check fixes that are only available in Go 1.14. -// See golang/go#35973 for more information. -func TestInvalidFilesInOverlay(t *testing.T) { packagestest.TestAll(t, testInvalidFilesInOverlay) } -func testInvalidFilesInOverlay(t *testing.T, exporter packagestest.Exporter) { - testenv.NeedsGo1Point(t, 14) - exported := packagestest.Export(t, exporter, []packagestest.Module{ - { - Name: "golang.org/fake", - Files: map[string]interface{}{ - "d/d.go": `package d; import "net/http"; const d = http.MethodGet;`, - "d/util.go": ``, - "d/d_test.go": ``, - }, - }, - }) - defer exported.Cleanup() - - dir := filepath.Dir(filepath.Dir(exported.File("golang.org/fake", "d/d.go"))) - - // Additional tests for test variants. - for i, tt := range []struct { - name string - overlay map[string][]byte - want string // expected value of d.D - - }{ - // Overlay with a test variant. - {"test_variant", - map[string][]byte{ - filepath.Join(dir, "d", "d_test.go"): []byte(`package d; import "testing"; const D = d + "_test"; func TestD(t *testing.T) {};`)}, - `"GET_test"`}, - // Overlay in package. - {"second_file", - map[string][]byte{ - filepath.Join(dir, "d", "util.go"): []byte(`package d; const D = d + "_util";`)}, - `"GET_util"`}, - } { - t.Run(tt.name, func(t *testing.T) { - exported.Config.Overlay = tt.overlay - exported.Config.Mode = packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | - packages.NeedDeps | packages.NeedTypes | packages.NeedTypesSizes - exported.Config.Tests = true - - for f := range tt.overlay { - initial, err := packages.Load(exported.Config, fmt.Sprintf("file=%s", f)) - if err != nil { - t.Fatal(err) - } - d := initial[0] - var containsFile bool - for _, goFile := range d.CompiledGoFiles { - if f == goFile { - containsFile = true - break - } - } - if !containsFile { - t.Fatalf("expected %s in CompiledGoFiles, got %v", f, d.CompiledGoFiles) - } - // Check value of d.D. - dD := constant(d, "D") - if dD == nil { - t.Fatalf("%d. d.D: got nil", i) - } - got := dD.Val().String() - if got != tt.want { - t.Fatalf("%d. d.D: got %s, want %s", i, got, tt.want) - } - } - }) - } -} diff --git a/go/packages/packages115_test.go b/go/packages/packages115_test.go deleted file mode 100644 index 11d8044b54..0000000000 --- a/go/packages/packages115_test.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package packages_test - -import ( - "strings" - "testing" - - "golang.org/x/tools/go/packages" - "golang.org/x/tools/go/packages/packagestest" - "golang.org/x/tools/internal/testenv" -) - -// TestInvalidFilesInXTest checks the fix for golang/go#37971. -func TestInvalidFilesInXTest(t *testing.T) { packagestest.TestAll(t, testInvalidFilesInXTest) } -func testInvalidFilesInXTest(t *testing.T, exporter packagestest.Exporter) { - testenv.NeedsGo1Point(t, 15) - exported := packagestest.Export(t, exporter, []packagestest.Module{ - { - Name: "golang.org/fake", - Files: map[string]interface{}{ - "d/d.go": `package d; import "net/http"; const d = http.MethodGet; func Get() string { return d; }`, - "d/d2.go": ``, // invalid file - "d/d_test.go": `package d_test; import "testing"; import "golang.org/fake/d"; func TestD(t *testing.T) { d.Get(); }`, - }, - }, - }) - defer exported.Cleanup() - - exported.Config.Mode = packages.NeedName | packages.NeedFiles - exported.Config.Tests = true - - initial, err := packages.Load(exported.Config, "golang.org/fake/d") - if err != nil { - t.Fatal(err) - } - if len(initial) != 3 { - t.Errorf("expected 3 packages, got %d", len(initial)) - } -} - -func TestTypecheckCgo(t *testing.T) { packagestest.TestAll(t, testTypecheckCgo) } -func testTypecheckCgo(t *testing.T, exporter packagestest.Exporter) { - testenv.NeedsGo1Point(t, 15) - testenv.NeedsTool(t, "cgo") - - const cgo = `package cgo - import "C" - - func Example() { - C.CString("hi") - } - ` - exported := packagestest.Export(t, exporter, []packagestest.Module{ - { - Name: "golang.org/fake", - Files: map[string]interface{}{ - "cgo/cgo.go": cgo, - }, - }, - }) - defer exported.Cleanup() - - exported.Config.Mode = packages.NeedFiles | packages.NeedCompiledGoFiles | - packages.NeedSyntax | packages.NeedDeps | packages.NeedTypes | - packages.TypecheckCgo - - initial, err := packages.Load(exported.Config, "golang.org/fake/cgo") - if err != nil { - t.Fatal(err) - } - pkg := initial[0] - if len(pkg.Errors) != 0 { - t.Fatalf("package has errors: %v", pkg.Errors) - } - - expos := pkg.Types.Scope().Lookup("Example").Pos() - fname := pkg.Fset.File(expos).Name() - if !strings.HasSuffix(fname, "cgo.go") { - t.Errorf("position for cgo package was loaded from %v, wanted cgo.go", fname) - } -} diff --git a/go/packages/packages_test.go b/go/packages/packages_test.go index 8c85196387..fdd7429431 100644 --- a/go/packages/packages_test.go +++ b/go/packages/packages_test.go @@ -17,6 +17,7 @@ import ( "go/types" "io/ioutil" "os" + "os/exec" "path/filepath" "reflect" "runtime" @@ -2244,6 +2245,168 @@ const A = 4 } } +func TestLoadImportsC(t *testing.T) { + // This test checks that when a package depends on the + // test variant of "syscall", "unsafe", or "runtime/cgo", that dependency + // is not removed when those packages are added when it imports "C". + // + // For this test to work, the external test of syscall must have a dependency + // on net, and net must import "syscall" and "C". + if runtime.GOOS == "windows" { + t.Skipf("skipping on windows; packages on windows do not satisfy conditions for test.") + } + if runtime.GOOS == "plan9" { + // See https://golang.org/issue/27100. + t.Skip(`skipping on plan9; for some reason "net [syscall.test]" is not loaded`) + } + testenv.NeedsGoPackages(t) + + cfg := &packages.Config{ + Context: testCtx, + Mode: packages.LoadImports, + Tests: true, + } + initial, err := packages.Load(cfg, "syscall", "net") + if err != nil { + t.Fatalf("failed to load imports: %v", err) + } + + _, all := importGraph(initial) + + for _, test := range []struct { + pattern string + wantImport string // an import to check for + }{ + {"net", "syscall:syscall"}, + {"net [syscall.test]", "syscall:syscall [syscall.test]"}, + {"syscall_test [syscall.test]", "net:net [syscall.test]"}, + } { + // Test the import paths. + pkg := all[test.pattern] + if pkg == nil { + t.Errorf("package %q not loaded", test.pattern) + continue + } + if imports := strings.Join(imports(pkg), " "); !strings.Contains(imports, test.wantImport) { + t.Errorf("package %q: got \n%s, \nwant to have %s", test.pattern, imports, test.wantImport) + } + } +} + +func TestCgoNoSyntax(t *testing.T) { + packagestest.TestAll(t, testCgoNoSyntax) +} +func testCgoNoSyntax(t *testing.T, exporter packagestest.Exporter) { + testenv.NeedsTool(t, "cgo") + + exported := packagestest.Export(t, exporter, []packagestest.Module{{ + Name: "golang.org/fake", + Files: map[string]interface{}{ + "c/c.go": `package c; import "C"`, + }, + }}) + + // Explicitly enable cgo. + exported.Config.Env = append(exported.Config.Env, "CGO_ENABLED=1") + + modes := []packages.LoadMode{ + packages.NeedTypes, + packages.NeedName | packages.NeedTypes, + packages.NeedName | packages.NeedTypes | packages.NeedImports, + packages.NeedName | packages.NeedTypes | packages.NeedImports | packages.NeedDeps, + packages.NeedName | packages.NeedImports, + } + for _, mode := range modes { + t.Run(fmt.Sprint(mode), func(t *testing.T) { + exported.Config.Mode = mode + pkgs, err := packages.Load(exported.Config, "golang.org/fake/c") + if err != nil { + t.Fatal(err) + } + if len(pkgs) != 1 { + t.Fatalf("Expected 1 package, got %v", pkgs) + } + pkg := pkgs[0] + if len(pkg.Errors) != 0 { + t.Fatalf("Expected no errors in package, got %v", pkg.Errors) + } + }) + } +} + +func TestCgoBadPkgConfig(t *testing.T) { + packagestest.TestAll(t, testCgoBadPkgConfig) +} +func testCgoBadPkgConfig(t *testing.T, exporter packagestest.Exporter) { + testenv.NeedsTool(t, "cgo") + + exported := packagestest.Export(t, exporter, []packagestest.Module{{ + Name: "golang.org/fake", + Files: map[string]interface{}{ + "c/c.go": `package c + +// #cgo pkg-config: --cflags -- foo +import "C"`, + }, + }}) + + dir := buildFakePkgconfig(t, exported.Config.Env) + defer os.RemoveAll(dir) + env := exported.Config.Env + for i, v := range env { + if strings.HasPrefix(v, "PATH=") { + env[i] = "PATH=" + dir + string(os.PathListSeparator) + v[len("PATH="):] + } + } + + exported.Config.Env = append(exported.Config.Env, "CGO_ENABLED=1") + + exported.Config.Mode = packages.NeedName | packages.NeedCompiledGoFiles + pkgs, err := packages.Load(exported.Config, "golang.org/fake/c") + if err != nil { + t.Fatal(err) + } + if len(pkgs) != 1 { + t.Fatalf("Expected 1 package, got %v", pkgs) + } + if pkgs[0].Name != "c" { + t.Fatalf("Expected package to have name \"c\", got %q", pkgs[0].Name) + } +} + +func buildFakePkgconfig(t *testing.T, env []string) string { + tmpdir, err := ioutil.TempDir("", "fakepkgconfig") + if err != nil { + t.Fatal(err) + } + err = ioutil.WriteFile(filepath.Join(tmpdir, "pkg-config.go"), []byte(` +package main + +import "fmt" +import "os" + +func main() { + fmt.Fprintln(os.Stderr, "bad") + os.Exit(2) +} +`), 0644) + if err != nil { + os.RemoveAll(tmpdir) + t.Fatal(err) + } + cmd := exec.Command("go", "build", "-o", "pkg-config", "pkg-config.go") + cmd.Dir = tmpdir + cmd.Env = env + + if b, err := cmd.CombinedOutput(); err != nil { + os.RemoveAll(tmpdir) + fmt.Println(os.Environ()) + t.Log(string(b)) + t.Fatal(err) + } + return tmpdir +} + func TestIssue32814(t *testing.T) { packagestest.TestAll(t, testIssue32814) } func testIssue32814(t *testing.T, exporter packagestest.Exporter) { exported := packagestest.Export(t, exporter, []packagestest.Module{{ @@ -2636,6 +2799,148 @@ func testIssue37529(t *testing.T, exporter packagestest.Exporter) { } } +// Tests golang/go#35973, fixed in Go 1.14. +func TestInvalidFilesInOverlay(t *testing.T) { packagestest.TestAll(t, testInvalidFilesInOverlay) } +func testInvalidFilesInOverlay(t *testing.T, exporter packagestest.Exporter) { + testenv.NeedsGo1Point(t, 14) + exported := packagestest.Export(t, exporter, []packagestest.Module{ + { + Name: "golang.org/fake", + Files: map[string]interface{}{ + "d/d.go": `package d; import "net/http"; const d = http.MethodGet;`, + "d/util.go": ``, + "d/d_test.go": ``, + }, + }, + }) + defer exported.Cleanup() + + dir := filepath.Dir(filepath.Dir(exported.File("golang.org/fake", "d/d.go"))) + + // Additional tests for test variants. + for i, tt := range []struct { + name string + overlay map[string][]byte + want string // expected value of d.D + + }{ + // Overlay with a test variant. + {"test_variant", + map[string][]byte{ + filepath.Join(dir, "d", "d_test.go"): []byte(`package d; import "testing"; const D = d + "_test"; func TestD(t *testing.T) {};`)}, + `"GET_test"`}, + // Overlay in package. + {"second_file", + map[string][]byte{ + filepath.Join(dir, "d", "util.go"): []byte(`package d; const D = d + "_util";`)}, + `"GET_util"`}, + } { + t.Run(tt.name, func(t *testing.T) { + exported.Config.Overlay = tt.overlay + exported.Config.Mode = packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | + packages.NeedDeps | packages.NeedTypes | packages.NeedTypesSizes + exported.Config.Tests = true + + for f := range tt.overlay { + initial, err := packages.Load(exported.Config, fmt.Sprintf("file=%s", f)) + if err != nil { + t.Fatal(err) + } + d := initial[0] + var containsFile bool + for _, goFile := range d.CompiledGoFiles { + if f == goFile { + containsFile = true + break + } + } + if !containsFile { + t.Fatalf("expected %s in CompiledGoFiles, got %v", f, d.CompiledGoFiles) + } + // Check value of d.D. + dD := constant(d, "D") + if dD == nil { + t.Fatalf("%d. d.D: got nil", i) + } + got := dD.Val().String() + if got != tt.want { + t.Fatalf("%d. d.D: got %s, want %s", i, got, tt.want) + } + } + }) + } +} + +// TestInvalidFilesInXTest checks the fix for golang/go#37971 in Go 1.15. +func TestInvalidFilesInXTest(t *testing.T) { packagestest.TestAll(t, testInvalidFilesInXTest) } +func testInvalidFilesInXTest(t *testing.T, exporter packagestest.Exporter) { + testenv.NeedsGo1Point(t, 15) + exported := packagestest.Export(t, exporter, []packagestest.Module{ + { + Name: "golang.org/fake", + Files: map[string]interface{}{ + "d/d.go": `package d; import "net/http"; const d = http.MethodGet; func Get() string { return d; }`, + "d/d2.go": ``, // invalid file + "d/d_test.go": `package d_test; import "testing"; import "golang.org/fake/d"; func TestD(t *testing.T) { d.Get(); }`, + }, + }, + }) + defer exported.Cleanup() + + exported.Config.Mode = packages.NeedName | packages.NeedFiles + exported.Config.Tests = true + + initial, err := packages.Load(exported.Config, "golang.org/fake/d") + if err != nil { + t.Fatal(err) + } + if len(initial) != 3 { + t.Errorf("expected 3 packages, got %d", len(initial)) + } +} + +func TestTypecheckCgo(t *testing.T) { packagestest.TestAll(t, testTypecheckCgo) } +func testTypecheckCgo(t *testing.T, exporter packagestest.Exporter) { + testenv.NeedsGo1Point(t, 15) + testenv.NeedsTool(t, "cgo") + + const cgo = `package cgo + import "C" + + func Example() { + C.CString("hi") + } + ` + exported := packagestest.Export(t, exporter, []packagestest.Module{ + { + Name: "golang.org/fake", + Files: map[string]interface{}{ + "cgo/cgo.go": cgo, + }, + }, + }) + defer exported.Cleanup() + + exported.Config.Mode = packages.NeedFiles | packages.NeedCompiledGoFiles | + packages.NeedSyntax | packages.NeedDeps | packages.NeedTypes | + packages.TypecheckCgo + + initial, err := packages.Load(exported.Config, "golang.org/fake/cgo") + if err != nil { + t.Fatal(err) + } + pkg := initial[0] + if len(pkg.Errors) != 0 { + t.Fatalf("package has errors: %v", pkg.Errors) + } + + expos := pkg.Types.Scope().Lookup("Example").Pos() + fname := pkg.Fset.File(expos).Name() + if !strings.HasSuffix(fname, "cgo.go") { + t.Errorf("position for cgo package was loaded from %v, wanted cgo.go", fname) + } +} + func TestModule(t *testing.T) { packagestest.TestAll(t, testModule) } diff --git a/go/packages/packagescgo_test.go b/go/packages/packagescgo_test.go deleted file mode 100644 index c2879497de..0000000000 --- a/go/packages/packagescgo_test.go +++ /dev/null @@ -1,182 +0,0 @@ -// Copyright 2018 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package packages_test - -import ( - "fmt" - "io/ioutil" - "os" - "os/exec" - "path/filepath" - "runtime" - "strings" - "testing" - - "golang.org/x/tools/go/packages" - "golang.org/x/tools/go/packages/packagestest" - "golang.org/x/tools/internal/testenv" -) - -func TestLoadImportsC(t *testing.T) { - // This test checks that when a package depends on the - // test variant of "syscall", "unsafe", or "runtime/cgo", that dependency - // is not removed when those packages are added when it imports "C". - // - // For this test to work, the external test of syscall must have a dependency - // on net, and net must import "syscall" and "C". - if runtime.GOOS == "windows" { - t.Skipf("skipping on windows; packages on windows do not satisfy conditions for test.") - } - if runtime.GOOS == "plan9" { - // See https://golang.org/issue/27100. - t.Skip(`skipping on plan9; for some reason "net [syscall.test]" is not loaded`) - } - testenv.NeedsGoPackages(t) - - cfg := &packages.Config{ - Context: testCtx, - Mode: packages.LoadImports, - Tests: true, - } - initial, err := packages.Load(cfg, "syscall", "net") - if err != nil { - t.Fatalf("failed to load imports: %v", err) - } - - _, all := importGraph(initial) - - for _, test := range []struct { - pattern string - wantImport string // an import to check for - }{ - {"net", "syscall:syscall"}, - {"net [syscall.test]", "syscall:syscall [syscall.test]"}, - {"syscall_test [syscall.test]", "net:net [syscall.test]"}, - } { - // Test the import paths. - pkg := all[test.pattern] - if pkg == nil { - t.Errorf("package %q not loaded", test.pattern) - continue - } - if imports := strings.Join(imports(pkg), " "); !strings.Contains(imports, test.wantImport) { - t.Errorf("package %q: got \n%s, \nwant to have %s", test.pattern, imports, test.wantImport) - } - } -} - -func TestCgoNoSyntax(t *testing.T) { - packagestest.TestAll(t, testCgoNoSyntax) -} -func testCgoNoSyntax(t *testing.T, exporter packagestest.Exporter) { - testenv.NeedsTool(t, "cgo") - - exported := packagestest.Export(t, exporter, []packagestest.Module{{ - Name: "golang.org/fake", - Files: map[string]interface{}{ - "c/c.go": `package c; import "C"`, - }, - }}) - - // Explicitly enable cgo. - exported.Config.Env = append(exported.Config.Env, "CGO_ENABLED=1") - - modes := []packages.LoadMode{ - packages.NeedTypes, - packages.NeedName | packages.NeedTypes, - packages.NeedName | packages.NeedTypes | packages.NeedImports, - packages.NeedName | packages.NeedTypes | packages.NeedImports | packages.NeedDeps, - packages.NeedName | packages.NeedImports, - } - for _, mode := range modes { - t.Run(fmt.Sprint(mode), func(t *testing.T) { - exported.Config.Mode = mode - pkgs, err := packages.Load(exported.Config, "golang.org/fake/c") - if err != nil { - t.Fatal(err) - } - if len(pkgs) != 1 { - t.Fatalf("Expected 1 package, got %v", pkgs) - } - pkg := pkgs[0] - if len(pkg.Errors) != 0 { - t.Fatalf("Expected no errors in package, got %v", pkg.Errors) - } - }) - } -} - -func TestCgoBadPkgConfig(t *testing.T) { - packagestest.TestAll(t, testCgoBadPkgConfig) -} -func testCgoBadPkgConfig(t *testing.T, exporter packagestest.Exporter) { - testenv.NeedsTool(t, "cgo") - - exported := packagestest.Export(t, exporter, []packagestest.Module{{ - Name: "golang.org/fake", - Files: map[string]interface{}{ - "c/c.go": `package c - -// #cgo pkg-config: --cflags -- foo -import "C"`, - }, - }}) - - dir := buildFakePkgconfig(t, exported.Config.Env) - defer os.RemoveAll(dir) - env := exported.Config.Env - for i, v := range env { - if strings.HasPrefix(v, "PATH=") { - env[i] = "PATH=" + dir + string(os.PathListSeparator) + v[len("PATH="):] - } - } - - exported.Config.Env = append(exported.Config.Env, "CGO_ENABLED=1") - - exported.Config.Mode = packages.NeedName | packages.NeedCompiledGoFiles - pkgs, err := packages.Load(exported.Config, "golang.org/fake/c") - if err != nil { - t.Fatal(err) - } - if len(pkgs) != 1 { - t.Fatalf("Expected 1 package, got %v", pkgs) - } - if pkgs[0].Name != "c" { - t.Fatalf("Expected package to have name \"c\", got %q", pkgs[0].Name) - } -} - -func buildFakePkgconfig(t *testing.T, env []string) string { - tmpdir, err := ioutil.TempDir("", "fakepkgconfig") - if err != nil { - t.Fatal(err) - } - err = ioutil.WriteFile(filepath.Join(tmpdir, "pkg-config.go"), []byte(` -package main - -import "fmt" -import "os" - -func main() { - fmt.Fprintln(os.Stderr, "bad") - os.Exit(2) -} -`), 0644) - if err != nil { - os.RemoveAll(tmpdir) - t.Fatal(err) - } - cmd := exec.Command("go", "build", "-o", "pkg-config", "pkg-config.go") - cmd.Dir = tmpdir - cmd.Env = env - - if b, err := cmd.CombinedOutput(); err != nil { - os.RemoveAll(tmpdir) - fmt.Println(os.Environ()) - t.Log(string(b)) - t.Fatal(err) - } - return tmpdir -} diff --git a/internal/imports/mod_112_test.go b/internal/imports/mod_112_test.go deleted file mode 100644 index 23cca56790..0000000000 --- a/internal/imports/mod_112_test.go +++ /dev/null @@ -1,23 +0,0 @@ -package imports - -import ( - "context" - "testing" - - "golang.org/x/tools/internal/testenv" -) - -// Tests that we handle GO111MODULE=on with no go.mod file. See #30855. -func TestNoMainModule(t *testing.T) { - testenv.NeedsGo1Point(t, 12) - mt := setup(t, ` --- x.go -- -package x -`, "") - defer mt.cleanup() - if _, err := mt.env.invokeGo(context.Background(), "mod", "download", "rsc.io/quote@v1.5.1"); err != nil { - t.Fatal(err) - } - - mt.assertScanFinds("rsc.io/quote", "quote") -} diff --git a/internal/imports/mod_114_test.go b/internal/imports/mod_114_test.go deleted file mode 100644 index 2303f47a46..0000000000 --- a/internal/imports/mod_114_test.go +++ /dev/null @@ -1,12 +0,0 @@ -package imports - -import ( - "testing" - - "golang.org/x/tools/internal/testenv" -) - -func TestModVendorAuto_114(t *testing.T) { - testenv.NeedsGo1Point(t, 14) - testModVendorAuto(t, true) -} diff --git a/internal/imports/mod_pre114_test.go b/internal/imports/mod_pre114_test.go deleted file mode 100644 index 4ab7c0f7ec..0000000000 --- a/internal/imports/mod_pre114_test.go +++ /dev/null @@ -1,12 +0,0 @@ -package imports - -import ( - "testing" - - "golang.org/x/tools/internal/testenv" -) - -func TestModVendorAuto_Pre114(t *testing.T) { - testenv.SkipAfterGo1Point(t, 13) - testModVendorAuto(t, false) -} diff --git a/internal/imports/mod_test.go b/internal/imports/mod_test.go index 47868fe0b4..fa1a9c65e6 100644 --- a/internal/imports/mod_test.go +++ b/internal/imports/mod_test.go @@ -246,7 +246,7 @@ import _ "rsc.io/sampler" // Tests that -mod=vendor is auto-enabled only for go1.14 and higher. // Vaguely inspired by mod_vendor_auto.txt. -func testModVendorAuto(t *testing.T, wantEnabled bool) { +func TestModVendorAuto(t *testing.T) { mt := setup(t, ` -- go.mod -- module m @@ -264,7 +264,7 @@ import _ "rsc.io/sampler" } wantDir := `pkg.*mod.*/sampler@.*$` - if wantEnabled { + if testenv.Go1Point() >= 14 { wantDir = `/vendor/` } mt.assertModuleFoundInDir("rsc.io/sampler", "sampler", wantDir) @@ -549,6 +549,21 @@ package v mt.assertModuleFoundInDir("example.com/vv", "v", `main/v12$`) } +// Tests that we handle GO111MODULE=on with no go.mod file. See #30855. +func TestNoMainModule(t *testing.T) { + testenv.NeedsGo1Point(t, 12) + mt := setup(t, ` +-- x.go -- +package x +`, "") + defer mt.cleanup() + if _, err := mt.env.invokeGo(context.Background(), "mod", "download", "rsc.io/quote@v1.5.1"); err != nil { + t.Fatal(err) + } + + mt.assertScanFinds("rsc.io/quote", "quote") +} + // assertFound asserts that the package at importPath is found to have pkgName, // and that scanning for pkgName finds it at importPath. func (t *modTest) assertFound(importPath, pkgName string) (string, *pkg) { diff --git a/internal/lsp/regtest/diagnostics_114_test.go b/internal/lsp/regtest/diagnostics_114_test.go deleted file mode 100644 index fbb7cc67dd..0000000000 --- a/internal/lsp/regtest/diagnostics_114_test.go +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package regtest - -import ( - "testing" - - "golang.org/x/tools/internal/lsp" - "golang.org/x/tools/internal/lsp/fake" - "golang.org/x/tools/internal/lsp/protocol" - "golang.org/x/tools/internal/testenv" -) - -const ardanLabsProxy = ` --- github.com/ardanlabs/conf@v1.2.3/go.mod -- -module github.com/ardanlabs/conf - -go 1.12 --- github.com/ardanlabs/conf@v1.2.3/conf.go -- -package conf - -var ErrHelpWanted error -` - -// -modfile flag that is used to provide modfile diagnostics is only available -// with 1.14. -func Test_Issue38211(t *testing.T) { - testenv.NeedsGo1Point(t, 14) - const ardanLabs = ` --- go.mod -- -module mod.com - -go 1.14 --- main.go -- -package main - -import "github.com/ardanlabs/conf" - -func main() { - _ = conf.ErrHelpWanted -} -` - runner.Run(t, ardanLabs, func(t *testing.T, env *Env) { - // Expect a diagnostic with a suggested fix to add - // "github.com/ardanlabs/conf" to the go.mod file. - env.OpenFile("go.mod") - env.OpenFile("main.go") - metBy := env.Await( - env.DiagnosticAtRegexp("main.go", `"github.com/ardanlabs/conf"`), - ) - d, ok := metBy[0].(*protocol.PublishDiagnosticsParams) - if !ok { - t.Fatalf("unexpected type for metBy (%T)", metBy) - } - env.ApplyQuickFixes("main.go", d.Diagnostics) - env.SaveBuffer("go.mod") - env.Await( - EmptyDiagnostics("main.go"), - ) - // Comment out the line that depends on conf and expect a - // diagnostic and a fix to remove the import. - env.RegexpReplace("main.go", "_ = conf.ErrHelpWanted", "//_ = conf.ErrHelpWanted") - env.Await( - env.DiagnosticAtRegexp("main.go", `"github.com/ardanlabs/conf"`), - ) - env.SaveBuffer("main.go") - // Expect a diagnostic and fix to remove the dependency in the go.mod. - metBy = env.Await( - EmptyDiagnostics("main.go"), - env.DiagnosticAtRegexp("go.mod", "require github.com/ardanlabs/conf"), - ) - d, ok = metBy[1].(*protocol.PublishDiagnosticsParams) - if !ok { - t.Fatalf("unexpected type for metBy (%T)", metBy) - } - env.ApplyQuickFixes("go.mod", d.Diagnostics) - env.SaveBuffer("go.mod") - env.Await( - EmptyDiagnostics("go.mod"), - ) - // Uncomment the lines and expect a new diagnostic for the import. - env.RegexpReplace("main.go", "//_ = conf.ErrHelpWanted", "_ = conf.ErrHelpWanted") - env.SaveBuffer("main.go") - env.Await( - env.DiagnosticAtRegexp("main.go", `"github.com/ardanlabs/conf"`), - ) - }, WithProxy(ardanLabsProxy)) -} - -// Test for golang/go#38207. -func TestNewModule_Issue38207(t *testing.T) { - testenv.NeedsGo1Point(t, 14) - const emptyFile = ` --- go.mod -- -module mod.com - -go 1.12 --- main.go -- -` - runner.Run(t, emptyFile, func(t *testing.T, env *Env) { - env.OpenFile("main.go") - env.OpenFile("go.mod") - env.EditBuffer("main.go", fake.NewEdit(0, 0, 0, 0, `package main - -import "github.com/ardanlabs/conf" - -func main() { - _ = conf.ErrHelpWanted -} -`)) - env.SaveBuffer("main.go") - metBy := env.Await( - env.DiagnosticAtRegexp("main.go", `"github.com/ardanlabs/conf"`), - ) - d, ok := metBy[0].(*protocol.PublishDiagnosticsParams) - if !ok { - t.Fatalf("unexpected type for diagnostics (%T)", d) - } - env.ApplyQuickFixes("main.go", d.Diagnostics) - env.Await( - EmptyDiagnostics("main.go"), - ) - }, WithProxy(ardanLabsProxy)) -} - -func TestNewFileBadImports_Issue36960(t *testing.T) { - testenv.NeedsGo1Point(t, 14) - const simplePackage = ` --- go.mod -- -module mod.com - -go 1.14 --- a/a1.go -- -package a - -import "fmt" - -func _() { - fmt.Println("hi") -} -` - runner.Run(t, simplePackage, func(t *testing.T, env *Env) { - env.OpenFile("a/a1.go") - env.CreateBuffer("a/a2.go", ``) - if err := env.Editor.SaveBufferWithoutActions(env.Ctx, "a/a2.go"); err != nil { - t.Fatal(err) - } - env.Await( - OnceMet( - CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidSave), 1), - NoDiagnostics("a/a1.go"), - ), - ) - env.EditBuffer("a/a2.go", fake.NewEdit(0, 0, 0, 0, `package a`)) - env.Await( - OnceMet( - CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChange), 1), - NoDiagnostics("a/a1.go"), - ), - ) - }) -} diff --git a/internal/lsp/regtest/diagnostics_test.go b/internal/lsp/regtest/diagnostics_test.go index 6c77725bdf..aff0c9e25e 100644 --- a/internal/lsp/regtest/diagnostics_test.go +++ b/internal/lsp/regtest/diagnostics_test.go @@ -13,6 +13,7 @@ import ( "golang.org/x/tools/internal/lsp/fake" "golang.org/x/tools/internal/lsp/protocol" "golang.org/x/tools/internal/lsp/tests" + "golang.org/x/tools/internal/testenv" ) // Use mod.com for all go.mod files due to golang/go#35230. @@ -530,3 +531,153 @@ func main() { ) }, InGOPATH()) } + +const ardanLabsProxy = ` +-- github.com/ardanlabs/conf@v1.2.3/go.mod -- +module github.com/ardanlabs/conf + +go 1.12 +-- github.com/ardanlabs/conf@v1.2.3/conf.go -- +package conf + +var ErrHelpWanted error +` + +// Test for golang/go#38211. +func Test_Issue38211(t *testing.T) { + testenv.NeedsGo1Point(t, 14) + const ardanLabs = ` +-- go.mod -- +module mod.com + +go 1.14 +-- main.go -- +package main + +import "github.com/ardanlabs/conf" + +func main() { + _ = conf.ErrHelpWanted +} +` + runner.Run(t, ardanLabs, func(t *testing.T, env *Env) { + // Expect a diagnostic with a suggested fix to add + // "github.com/ardanlabs/conf" to the go.mod file. + env.OpenFile("go.mod") + env.OpenFile("main.go") + metBy := env.Await( + env.DiagnosticAtRegexp("main.go", `"github.com/ardanlabs/conf"`), + ) + d, ok := metBy[0].(*protocol.PublishDiagnosticsParams) + if !ok { + t.Fatalf("unexpected type for metBy (%T)", metBy) + } + env.ApplyQuickFixes("main.go", d.Diagnostics) + env.SaveBuffer("go.mod") + env.Await( + EmptyDiagnostics("main.go"), + ) + // Comment out the line that depends on conf and expect a + // diagnostic and a fix to remove the import. + env.RegexpReplace("main.go", "_ = conf.ErrHelpWanted", "//_ = conf.ErrHelpWanted") + env.Await( + env.DiagnosticAtRegexp("main.go", `"github.com/ardanlabs/conf"`), + ) + env.SaveBuffer("main.go") + // Expect a diagnostic and fix to remove the dependency in the go.mod. + metBy = env.Await( + EmptyDiagnostics("main.go"), + env.DiagnosticAtRegexp("go.mod", "require github.com/ardanlabs/conf"), + ) + d, ok = metBy[1].(*protocol.PublishDiagnosticsParams) + if !ok { + t.Fatalf("unexpected type for metBy (%T)", metBy) + } + env.ApplyQuickFixes("go.mod", d.Diagnostics) + env.SaveBuffer("go.mod") + env.Await( + EmptyDiagnostics("go.mod"), + ) + // Uncomment the lines and expect a new diagnostic for the import. + env.RegexpReplace("main.go", "//_ = conf.ErrHelpWanted", "_ = conf.ErrHelpWanted") + env.SaveBuffer("main.go") + env.Await( + env.DiagnosticAtRegexp("main.go", `"github.com/ardanlabs/conf"`), + ) + }, WithProxy(ardanLabsProxy)) +} + +// Test for golang/go#38207. +func TestNewModule_Issue38207(t *testing.T) { + testenv.NeedsGo1Point(t, 14) + const emptyFile = ` +-- go.mod -- +module mod.com + +go 1.12 +-- main.go -- +` + runner.Run(t, emptyFile, func(t *testing.T, env *Env) { + env.OpenFile("main.go") + env.OpenFile("go.mod") + env.EditBuffer("main.go", fake.NewEdit(0, 0, 0, 0, `package main + +import "github.com/ardanlabs/conf" + +func main() { + _ = conf.ErrHelpWanted +} +`)) + env.SaveBuffer("main.go") + metBy := env.Await( + env.DiagnosticAtRegexp("main.go", `"github.com/ardanlabs/conf"`), + ) + d, ok := metBy[0].(*protocol.PublishDiagnosticsParams) + if !ok { + t.Fatalf("unexpected type for diagnostics (%T)", d) + } + env.ApplyQuickFixes("main.go", d.Diagnostics) + env.Await( + EmptyDiagnostics("main.go"), + ) + }, WithProxy(ardanLabsProxy)) +} + +// Test for golang/go#36960. +func TestNewFileBadImports_Issue36960(t *testing.T) { + testenv.NeedsGo1Point(t, 14) + const simplePackage = ` +-- go.mod -- +module mod.com + +go 1.14 +-- a/a1.go -- +package a + +import "fmt" + +func _() { + fmt.Println("hi") +} +` + runner.Run(t, simplePackage, func(t *testing.T, env *Env) { + env.OpenFile("a/a1.go") + env.CreateBuffer("a/a2.go", ``) + if err := env.Editor.SaveBufferWithoutActions(env.Ctx, "a/a2.go"); err != nil { + t.Fatal(err) + } + env.Await( + OnceMet( + CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidSave), 1), + NoDiagnostics("a/a1.go"), + ), + ) + env.EditBuffer("a/a2.go", fake.NewEdit(0, 0, 0, 0, `package a`)) + env.Await( + OnceMet( + CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChange), 1), + NoDiagnostics("a/a1.go"), + ), + ) + }) +} diff --git a/internal/proxydir/proxydir.go b/internal/proxydir/proxydir.go index 52e5b586f4..5180204064 100644 --- a/internal/proxydir/proxydir.go +++ b/internal/proxydir/proxydir.go @@ -14,6 +14,9 @@ import ( "io/ioutil" "os" "path/filepath" + "strings" + + "golang.org/x/tools/internal/testenv" ) // WriteModuleVersion creates a directory in the proxy dir for a module. @@ -77,3 +80,21 @@ func checkClose(name string, closer io.Closer, err *error) { *err = fmt.Errorf("closing %s: %v", name, cerr) } } + +// ToURL returns the file uri for a proxy directory. +func ToURL(dir string) string { + if testenv.Go1Point() >= 13 { + // file URLs on Windows must start with file:///. See golang.org/issue/6027. + path := filepath.ToSlash(dir) + if !strings.HasPrefix(path, "/") { + path = "/" + path + } + return "file://" + path + } else { + // Prior to go1.13, the Go command on Windows only accepted GOPROXY file URLs + // of the form file://C:/path/to/proxy. This was incorrect: when parsed, "C:" + // is interpreted as the host. See golang.org/issue/6027. This has been + // fixed in go1.13, but we emit the old format for old releases. + return "file://" + filepath.ToSlash(dir) + } +} diff --git a/internal/proxydir/proxydir_113.go b/internal/proxydir/proxydir_113.go deleted file mode 100644 index d67544709d..0000000000 --- a/internal/proxydir/proxydir_113.go +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2020 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package proxydir - -import ( - "path/filepath" - "strings" - - "golang.org/x/tools/internal/testenv" -) - -// ToURL returns the file uri for a proxy directory. -func ToURL(dir string) string { - if testenv.Go1Point() >= 13 { - // file URLs on Windows must start with file:///. See golang.org/issue/6027. - path := filepath.ToSlash(dir) - if !strings.HasPrefix(path, "/") { - path = "/" + path - } - return "file://" + path - } else { - // Prior to go1.13, the Go command on Windows only accepted GOPROXY file URLs - // of the form file://C:/path/to/proxy. This was incorrect: when parsed, "C:" - // is interpreted as the host. See golang.org/issue/6027. This has been - // fixed in go1.13, but we emit the old format for old releases. - return "file://" + filepath.ToSlash(dir) - } -}