+++ /dev/null
-// 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 (
- "fmt"
- "strings"
- "testing"
-
- "golang.org/x/tools/internal/lsp"
- "golang.org/x/tools/internal/lsp/fake"
- "golang.org/x/tools/internal/testenv"
-)
-
-const workspaceProxy = `
--- example.com@v1.2.3/go.mod --
-module example.com
-
-go 1.12
--- example.com@v1.2.3/blah/blah.go --
-package blah
-
-func SaySomething() {
- fmt.Println("something")
-}
--- random.org@v1.2.3/go.mod --
-module random.org
-
-go 1.12
--- random.org@v1.2.3/bye/bye.go --
-package bye
-
-func Goodbye() {
- println("Bye")
-}
-`
-
-// TODO: Add a replace directive.
-const workspaceModule = `
--- pkg/go.mod --
-module mod.com
-
-go 1.14
-
-require (
- example.com v1.2.3
- random.org v1.2.3
-)
--- pkg/main.go --
-package main
-
-import (
- "example.com/blah"
- "mod.com/inner"
- "random.org/bye"
-)
-
-func main() {
- blah.SaySomething()
- inner.Hi()
- bye.Goodbye()
-}
--- pkg/main2.go --
-package main
-
-import "fmt"
-
-func _() {
- fmt.Print("%s")
-}
--- pkg/inner/inner.go --
-package inner
-
-import "example.com/blah"
-
-func Hi() {
- blah.SaySomething()
-}
--- goodbye/bye/bye.go --
-package bye
-
-func Bye() {}
--- goodbye/go.mod --
-module random.org
-
-go 1.12
-`
-
-// Confirm that find references returns all of the references in the module,
-// regardless of what the workspace root is.
-func TestReferences(t *testing.T) {
- for _, tt := range []struct {
- name, rootPath string
- }{
- {
- name: "module root",
- rootPath: "pkg",
- },
- {
- name: "subdirectory",
- rootPath: "pkg/inner",
- },
- } {
- t.Run(tt.name, func(t *testing.T) {
- opts := []RunOption{WithProxyFiles(workspaceProxy)}
- if tt.rootPath != "" {
- opts = append(opts, WithRootPath(tt.rootPath))
- }
- withOptions(opts...).run(t, workspaceModule, func(t *testing.T, env *Env) {
- f := "pkg/inner/inner.go"
- env.OpenFile(f)
- locations := env.References(f, env.RegexpSearch(f, `SaySomething`))
- want := 3
- if got := len(locations); got != want {
- t.Fatalf("expected %v locations, got %v", want, got)
- }
- })
- })
- }
-}
-
-// Make sure that analysis diagnostics are cleared for the whole package when
-// the only opened file is closed. This test was inspired by the experience in
-// VS Code, where clicking on a reference result triggers a
-// textDocument/didOpen without a corresponding textDocument/didClose.
-func TestClearAnalysisDiagnostics(t *testing.T) {
- withOptions(WithProxyFiles(workspaceProxy), WithRootPath("pkg/inner")).run(t, workspaceModule, func(t *testing.T, env *Env) {
- env.OpenFile("pkg/main.go")
- env.Await(
- env.DiagnosticAtRegexp("pkg/main2.go", "fmt.Print"),
- )
- env.CloseBuffer("pkg/main.go")
- env.Await(
- EmptyDiagnostics("pkg/main2.go"),
- )
- })
-}
-
-// This test checks that gopls updates the set of files it watches when a
-// replace target is added to the go.mod.
-func TestWatchReplaceTargets(t *testing.T) {
- withOptions(WithProxyFiles(workspaceProxy), WithRootPath("pkg")).run(t, workspaceModule, func(t *testing.T, env *Env) {
- // Add a replace directive and expect the files that gopls is watching
- // to change.
- dir := env.Sandbox.Workdir.URI("goodbye").SpanURI().Filename()
- goModWithReplace := fmt.Sprintf(`%s
-replace random.org => %s
-`, env.ReadWorkspaceFile("pkg/go.mod"), dir)
- env.WriteWorkspaceFile("pkg/go.mod", goModWithReplace)
- env.Await(
- CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChangeWatchedFiles), 1),
- UnregistrationMatching("didChangeWatchedFiles"),
- RegistrationMatching("didChangeWatchedFiles"),
- )
- })
-}
-
-const workspaceModuleProxy = `
--- b.com@v1.2.3/go.mod --
-module b.com
-
-go 1.12
--- b.com@v1.2.3/b/b.go --
-package b
-
-func Hello() {}
-`
-
-func TestAutomaticWorkspaceModule_Interdependent(t *testing.T) {
- const multiModule = `
--- moda/a/go.mod --
-module a.com
-
-require b.com v1.2.3
-
--- moda/a/a.go --
-package a
-
-import (
- "b.com/b"
-)
-
-func main() {
- var x int
- _ = b.Hello()
-}
--- modb/go.mod --
-module b.com
-
--- modb/b/b.go --
-package b
-
-func Hello() int {
- var x int
-}
-`
- withOptions(
- WithProxyFiles(workspaceModuleProxy),
- WithModes(Experimental),
- ).run(t, multiModule, func(t *testing.T, env *Env) {
- env.Await(
- env.DiagnosticAtRegexp("moda/a/a.go", "x"),
- env.DiagnosticAtRegexp("modb/b/b.go", "x"),
- env.NoDiagnosticAtRegexp("moda/a/a.go", `"b.com/b"`),
- )
- })
-}
-
-// This change tests that the version of the module used changes after it has
-// been deleted from the workspace.
-func TestDeleteModule_Interdependent(t *testing.T) {
- const multiModule = `
--- moda/a/go.mod --
-module a.com
-
-require b.com v1.2.3
-
--- moda/a/a.go --
-package a
-
-import (
- "b.com/b"
-)
-
-func main() {
- var x int
- _ = b.Hello()
-}
--- modb/go.mod --
-module b.com
-
--- modb/b/b.go --
-package b
-
-func Hello() int {
- var x int
-}
-`
- withOptions(
- WithProxyFiles(workspaceModuleProxy),
- WithModes(Experimental),
- ).run(t, multiModule, func(t *testing.T, env *Env) {
- env.OpenFile("moda/a/a.go")
-
- original, _ := env.GoToDefinition("moda/a/a.go", env.RegexpSearch("moda/a/a.go", "Hello"))
- if want := "modb/b/b.go"; !strings.HasSuffix(original, want) {
- t.Errorf("expected %s, got %v", want, original)
- }
- env.CloseBuffer(original)
- env.RemoveWorkspaceFile("modb/b/b.go")
- env.RemoveWorkspaceFile("modb/go.mod")
- env.Await(
- CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChangeWatchedFiles), 2),
- )
- got, _ := env.GoToDefinition("moda/a/a.go", env.RegexpSearch("moda/a/a.go", "Hello"))
- if want := "b.com@v1.2.3/b/b.go"; !strings.HasSuffix(got, want) {
- t.Errorf("expected %s, got %v", want, got)
- }
- })
-}
-
-// Tests that the version of the module used changes after it has been added
-// to the workspace.
-func TestCreateModule_Interdependent(t *testing.T) {
- const multiModule = `
--- moda/a/go.mod --
-module a.com
-
-require b.com v1.2.3
-
--- moda/a/a.go --
-package a
-
-import (
- "b.com/b"
-)
-
-func main() {
- var x int
- _ = b.Hello()
-}
-`
- withOptions(
- WithModes(Experimental),
- WithProxyFiles(workspaceModuleProxy),
- ).run(t, multiModule, func(t *testing.T, env *Env) {
- env.OpenFile("moda/a/a.go")
- original, _ := env.GoToDefinition("moda/a/a.go", env.RegexpSearch("moda/a/a.go", "Hello"))
- if want := "b.com@v1.2.3/b/b.go"; !strings.HasSuffix(original, want) {
- t.Errorf("expected %s, got %v", want, original)
- }
- env.CloseBuffer(original)
- env.WriteWorkspaceFiles(map[string]string{
- "modb/go.mod": "module b.com",
- "modb/b/b.go": `package b
-
-func Hello() int {
- var x int
-}
-`,
- })
- env.Await(
- OnceMet(
- CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChangeWatchedFiles), 1),
- env.DiagnosticAtRegexp("modb/b/b.go", "x"),
- ),
- )
- got, _ := env.GoToDefinition("moda/a/a.go", env.RegexpSearch("moda/a/a.go", "Hello"))
- if want := "modb/b/b.go"; !strings.HasSuffix(got, want) {
- t.Errorf("expected %s, got %v", want, original)
- }
- })
-}
-
-// This test confirms that a gopls workspace can recover from initialization
-// with one invalid module.
-func TestOneBrokenModule(t *testing.T) {
- const multiModule = `
--- moda/a/go.mod --
-module a.com
-
-require b.com v1.2.3
-
--- moda/a/a.go --
-package a
-
-import (
- "b.com/b"
-)
-
-func main() {
- var x int
- _ = b.Hello()
-}
--- modb/go.mod --
-modul b.com // typo here
-
--- modb/b/b.go --
-package b
-
-func Hello() int {
- var x int
-}
-`
- withOptions(
- WithProxyFiles(workspaceModuleProxy),
- WithModes(Experimental),
- ).run(t, multiModule, func(t *testing.T, env *Env) {
- env.OpenFile("modb/go.mod")
- env.Await(
- OnceMet(
- CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidOpen), 1),
- DiagnosticAt("modb/go.mod", 0, 0),
- ),
- )
- env.RegexpReplace("modb/go.mod", "modul", "module")
- env.Editor.SaveBufferWithoutActions(env.Ctx, "modb/go.mod")
- env.Await(
- env.DiagnosticAtRegexp("modb/b/b.go", "x"),
- )
- })
-}
-
-func TestUseGoplsMod(t *testing.T) {
- const multiModule = `
--- moda/a/go.mod --
-module a.com
-
-require b.com v1.2.3
-
--- moda/a/a.go --
-package a
-
-import (
- "b.com/b"
-)
-
-func main() {
- var x int
- _ = b.Hello()
-}
--- modb/go.mod --
-module b.com
-
--- modb/b/b.go --
-package b
-
-func Hello() int {
- var x int
-}
--- gopls.mod --
-module gopls-workspace
-
-require (
- a.com v0.0.0-goplsworkspace
- b.com v1.2.3
-)
-
-replace a.com => $SANDBOX_WORKDIR/moda/a
-`
- withOptions(
- WithProxyFiles(workspaceModuleProxy),
- WithModes(Experimental),
- ).run(t, multiModule, func(t *testing.T, env *Env) {
- env.OpenFile("moda/a/a.go")
- original, _ := env.GoToDefinition("moda/a/a.go", env.RegexpSearch("moda/a/a.go", "Hello"))
- if want := "b.com@v1.2.3/b/b.go"; !strings.HasSuffix(original, want) {
- t.Errorf("expected %s, got %v", want, original)
- }
- workdir := env.Sandbox.Workdir.RootURI().SpanURI().Filename()
- env.WriteWorkspaceFile("gopls.mod", fmt.Sprintf(`module gopls-workspace
-
-require (
- a.com v0.0.0-goplsworkspace
- b.com v0.0.0-goplsworkspace
-)
-
-replace a.com => %s/moda/a
-replace b.com => %s/modb
-`, workdir, workdir))
- env.Await(
- OnceMet(
- CompletedWork(lsp.DiagnosticWorkTitle(lsp.FromDidChangeWatchedFiles), 1),
- env.DiagnosticAtRegexp("modb/b/b.go", "x"),
- ),
- )
- newLocation, _ := env.GoToDefinition("moda/a/a.go", env.RegexpSearch("moda/a/a.go", "Hello"))
- if want := "modb/b/b.go"; !strings.HasSuffix(newLocation, want) {
- t.Errorf("expected %s, got %v", want, newLocation)
- }
- })
-}
-
-func TestNonWorkspaceFileCreation(t *testing.T) {
- testenv.NeedsGo1Point(t, 13)
-
- const files = `
--- go.mod --
-module mod.com
-
--- x.go --
-package x
-`
-
- const code = `
-package foo
-import "fmt"
-var _ = fmt.Printf
-`
- run(t, files, func(t *testing.T, env *Env) {
- env.CreateBuffer("/tmp/foo.go", "")
- env.EditBuffer("/tmp/foo.go", fake.NewEdit(0, 0, 0, 0, code))
- env.GoToDefinition("/tmp/foo.go", env.RegexpSearch("/tmp/foo.go", `Printf`))
- })
-}
-
-func TestMultiModuleV2(t *testing.T) {
- const multiModule = `
--- moda/a/go.mod --
-module a.com
-
-require b.com/v2 v2.0.0
--- moda/a/a.go --
-package a
-
-import (
- "b.com/v2/b"
-)
-
-func main() {
- var x int
- _ = b.Hi()
-}
--- modb/go.mod --
-module b.com
-
--- modb/b/b.go --
-package b
-
-func Hello() int {
- var x int
-}
--- modb/v2/go.mod --
-module b.com/v2
-
--- modb/v2/b/b.go --
-package b
-
-func Hi() int {
- var x int
-}
--- modc/go.mod --
-module gopkg.in/yaml.v1 // test gopkg.in versions
--- modc/main.go --
-package main
-
-func main() {
- var x int
-}
-`
- withOptions(
- WithModes(Experimental),
- ).run(t, multiModule, func(t *testing.T, env *Env) {
- env.Await(
- env.DiagnosticAtRegexp("moda/a/a.go", "x"),
- env.DiagnosticAtRegexp("modb/b/b.go", "x"),
- env.DiagnosticAtRegexp("modb/v2/b/b.go", "x"),
- env.DiagnosticAtRegexp("modc/main.go", "x"),
- )
- })
-}