// 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 ( "path" "strings" "testing" "golang.org/x/tools/internal/lsp/tests" ) const internalDefinition = ` -- go.mod -- module mod.com go 1.12 -- main.go -- package main import "fmt" func main() { fmt.Println(message) } -- const.go -- package main const message = "Hello World." ` func TestGoToInternalDefinition(t *testing.T) { runner.Run(t, internalDefinition, func(t *testing.T, env *Env) { env.OpenFile("main.go") name, pos := env.GoToDefinition("main.go", env.RegexpSearch("main.go", "message")) if want := "const.go"; name != want { t.Errorf("GoToDefinition: got file %q, want %q", name, want) } if want := env.RegexpSearch("const.go", "message"); pos != want { t.Errorf("GoToDefinition: got position %v, want %v", pos, want) } }) } const stdlibDefinition = ` -- go.mod -- module mod.com -- main.go -- package main import "fmt" func main() { fmt.Printf() }` func TestGoToStdlibDefinition_Issue37045(t *testing.T) { runner.Run(t, stdlibDefinition, func(t *testing.T, env *Env) { env.OpenFile("main.go") name, pos := env.GoToDefinition("main.go", env.RegexpSearch("main.go", `fmt.(Printf)`)) if got, want := path.Base(name), "print.go"; got != want { t.Errorf("GoToDefinition: got file %q, want %q", name, want) } // Test that we can jump to definition from outside our workspace. // See golang.org/issues/37045. newName, newPos := env.GoToDefinition(name, pos) if newName != name { t.Errorf("GoToDefinition is not idempotent: got %q, want %q", newName, name) } if newPos != pos { t.Errorf("GoToDefinition is not idempotent: got %v, want %v", newPos, pos) } }) } func TestUnexportedStdlib_Issue40809(t *testing.T) { runner.Run(t, stdlibDefinition, func(t *testing.T, env *Env) { env.OpenFile("main.go") name, _ := env.GoToDefinition("main.go", env.RegexpSearch("main.go", `fmt.(Printf)`)) env.OpenFile(name) pos := env.RegexpSearch(name, `:=\s*(newPrinter)\(\)`) // Check that we can find references on a reference refs := env.References(name, pos) if len(refs) < 5 { t.Errorf("expected 5+ references to newPrinter, found: %#v", refs) } name, pos = env.GoToDefinition(name, pos) content, _ := env.Hover(name, pos) if !strings.Contains(content.Value, "newPrinter") { t.Fatal("definition of newPrinter went to the incorrect place") } // And on the definition too. refs = env.References(name, pos) if len(refs) < 5 { t.Errorf("expected 5+ references to newPrinter, found: %#v", refs) } }) } // Test the hover on an error's Error function. // This can't be done via the marker tests because Error is a builtin. func TestHoverOnError(t *testing.T) { const mod = ` -- go.mod -- module mod.com -- main.go -- package main func main() { var err error err.Error() }` run(t, mod, func(t *testing.T, env *Env) { env.OpenFile("main.go") content, _ := env.Hover("main.go", env.RegexpSearch("main.go", "Error")) if content == nil { t.Fatalf("nil hover content for Error") } want := "```go\nfunc (error).Error() string\n```" if content.Value != want { t.Fatalf("hover failed:\n%s", tests.Diff(want, content.Value)) } }) }