1
0
mirror of https://github.com/golang/go synced 2024-11-18 16:14:46 -07:00

internal/lsp: don't show links in hover for test functions

source.Identifier previously was used for references and rename, so it
needed to take a package policy. Now, it's only used for definition and
hover, so it should always be the narrowest package handle. We can use
this fact to determine if the identifier is located in its declaring
package, and if that package is a test variant, we don't link to the
documentation on pkg.go.dev, since it doesn't exist.

Change-Id: I5686828858a3feafb8ff2e4c5964b562f66db9fa
Reviewed-on: https://go-review.googlesource.com/c/tools/+/217137
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
This commit is contained in:
Rebecca Stambler 2020-01-30 19:24:33 -05:00
parent 33212cd6a0
commit ab391d50b5
13 changed files with 94 additions and 12 deletions

View File

@ -256,6 +256,7 @@ func typeCheck(ctx context.Context, fset *token.FileSet, m *metadata, mode sourc
Selections: make(map[*ast.SelectorExpr]*types.Selection), Selections: make(map[*ast.SelectorExpr]*types.Selection),
Scopes: make(map[ast.Node]*types.Scope), Scopes: make(map[ast.Node]*types.Scope),
}, },
forTest: m.forTest,
} }
var ( var (
files = make([]*ast.File, len(pkg.compiledGoFiles)) files = make([]*ast.File, len(pkg.compiledGoFiles))

View File

@ -18,10 +18,10 @@ import (
// pkg contains the type information needed by the source package. // pkg contains the type information needed by the source package.
type pkg struct { type pkg struct {
// ID and package path have their own types to avoid being used interchangeably. // ID and package path have their own types to avoid being used interchangeably.
id packageID id packageID
pkgPath packagePath pkgPath packagePath
mode source.ParseMode mode source.ParseMode
forTest packagePath
goFiles []source.ParseGoHandle goFiles []source.ParseGoHandle
compiledGoFiles []source.ParseGoHandle compiledGoFiles []source.ParseGoHandle
errors []*source.Error errors []*source.Error
@ -99,6 +99,10 @@ func (p *pkg) IsIllTyped() bool {
return p.types == nil || p.typesInfo == nil || p.typesSizes == nil return p.types == nil || p.typesInfo == nil || p.typesSizes == nil
} }
func (p *pkg) ForTest() string {
return string(p.forTest)
}
func (p *pkg) GetImport(pkgPath string) (source.Package, error) { func (p *pkg) GetImport(pkgPath string) (source.Package, error) {
if imp := p.imports[packagePath(pkgPath)]; imp != nil { if imp := p.imports[packagePath(pkgPath)]; imp != nil {
return imp, nil return imp, nil

View File

@ -26,7 +26,7 @@ func (s *Server) definition(ctx context.Context, params *protocol.DefinitionPara
if fh.Identity().Kind != source.Go { if fh.Identity().Kind != source.Go {
return nil, nil return nil, nil
} }
ident, err := source.Identifier(ctx, snapshot, fh, params.Position, source.WidestPackageHandle) ident, err := source.Identifier(ctx, snapshot, fh, params.Position)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -56,7 +56,7 @@ func (s *Server) typeDefinition(ctx context.Context, params *protocol.TypeDefini
if fh.Identity().Kind != source.Go { if fh.Identity().Kind != source.Go {
return nil, nil return nil, nil
} }
ident, err := source.Identifier(ctx, snapshot, fh, params.Position, source.WidestPackageHandle) ident, err := source.Identifier(ctx, snapshot, fh, params.Position)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -26,7 +26,7 @@ func (s *Server) hover(ctx context.Context, params *protocol.HoverParams) (*prot
if fh.Identity().Kind != source.Go { if fh.Identity().Kind != source.Go {
return nil, nil return nil, nil
} }
ident, err := source.Identifier(ctx, snapshot, fh, params.Position, source.WidestPackageHandle) ident, err := source.Identifier(ctx, snapshot, fh, params.Position)
if err != nil { if err != nil {
return nil, nil return nil, nil
} }

View File

@ -85,6 +85,14 @@ func (i *IdentifierInfo) linkAndSymbolName() (string, string) {
case *types.Builtin: case *types.Builtin:
return fmt.Sprintf("builtin#%s", obj.Name()), obj.Name() return fmt.Sprintf("builtin#%s", obj.Name()), obj.Name()
} }
// Check if the identifier is test-only (and is therefore not part of a
// package's API). This is true if the request originated in a test package,
// and if the declaration is also found in the same test package.
if i.pkg != nil && obj.Pkg() != nil && i.pkg.ForTest() != "" {
if _, pkg, _ := findFileInPackage(i.pkg, i.Declaration.URI()); i.pkg == pkg {
return "", ""
}
}
// Don't return links for other unexported types. // Don't return links for other unexported types.
if !obj.Exported() { if !obj.Exported() {
return "", "" return "", ""

View File

@ -48,11 +48,11 @@ type Declaration struct {
// Identifier returns identifier information for a position // Identifier returns identifier information for a position
// in a file, accounting for a potentially incomplete selector. // in a file, accounting for a potentially incomplete selector.
func Identifier(ctx context.Context, snapshot Snapshot, fh FileHandle, pos protocol.Position, selectPackage PackagePolicy) (*IdentifierInfo, error) { func Identifier(ctx context.Context, snapshot Snapshot, fh FileHandle, pos protocol.Position) (*IdentifierInfo, error) {
ctx, done := trace.StartSpan(ctx, "source.Identifier") ctx, done := trace.StartSpan(ctx, "source.Identifier")
defer done() defer done()
pkg, pgh, err := getParsedFile(ctx, snapshot, fh, selectPackage) pkg, pgh, err := getParsedFile(ctx, snapshot, fh, NarrowestPackageHandle)
if err != nil { if err != nil {
return nil, fmt.Errorf("getting file for Identifier: %v", err) return nil, fmt.Errorf("getting file for Identifier: %v", err)
} }

View File

@ -484,7 +484,7 @@ func (r *runner) Definition(t *testing.T, spn span.Span, d tests.Definition) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
ident, err := source.Identifier(r.ctx, r.view.Snapshot(), fh, srcRng.Start, source.WidestPackageHandle) ident, err := source.Identifier(r.ctx, r.view.Snapshot(), fh, srcRng.Start)
if err != nil { if err != nil {
t.Fatalf("failed for %v: %v", d.Src, err) t.Fatalf("failed for %v: %v", d.Src, err)
} }
@ -768,7 +768,7 @@ func (r *runner) PrepareRename(t *testing.T, src span.Span, want *source.Prepare
} }
return return
} }
if want.Text == "" && item != nil { if want.Text == "" {
t.Errorf("prepare rename failed for %v: expected nil, got %v", src, item) t.Errorf("prepare rename failed for %v: expected nil, got %v", src, item)
return return
} }

View File

@ -341,6 +341,7 @@ type Package interface {
GetTypesInfo() *types.Info GetTypesInfo() *types.Info
GetTypesSizes() types.Sizes GetTypesSizes() types.Sizes
IsIllTyped() bool IsIllTyped() bool
ForTest() string
GetImport(pkgPath string) (Package, error) GetImport(pkgPath string) (Package, error)
Imports() []Package Imports() []Package
} }

View File

@ -0,0 +1,8 @@
package a
import (
"testing"
)
func TestA(t *testing.T) { //@TestA,godef(TestA, TestA)
}

View File

@ -0,0 +1,26 @@
-- TestA-definition --
godef/a/a_test.go:7:6-11: defined here as ```go
func TestA(t *testing.T)
```
-- TestA-definition-json --
{
"span": {
"uri": "file://godef/a/a_test.go",
"start": {
"line": 7,
"column": 6,
"offset": 39
},
"end": {
"line": 7,
"column": 11,
"offset": 44
}
},
"description": "```go\nfunc TestA(t *testing.T)\n```"
}
-- TestA-hover --
```go
func TestA(t *testing.T)
```

View File

@ -0,0 +1,8 @@
package a_test
import (
"testing"
)
func TestA2(t *testing.T) { //@TestA2,godef(TestA2, TestA2)
}

View File

@ -0,0 +1,26 @@
-- TestA2-definition --
godef/a/a_x_test.go:7:6-12: defined here as ```go
func TestA2(t *testing.T)
```
-- TestA2-definition-json --
{
"span": {
"uri": "file://godef/a/a_x_test.go",
"start": {
"line": 7,
"column": 6,
"offset": 44
},
"end": {
"line": 7,
"column": 12,
"offset": 50
}
},
"description": "```go\nfunc TestA2(t *testing.T)\n```"
}
-- TestA2-hover --
```go
func TestA2(t *testing.T)
```

View File

@ -11,7 +11,7 @@ FoldingRangesCount = 2
FormatCount = 6 FormatCount = 6
ImportCount = 7 ImportCount = 7
SuggestedFixCount = 1 SuggestedFixCount = 1
DefinitionsCount = 43 DefinitionsCount = 45
TypeDefinitionsCount = 2 TypeDefinitionsCount = 2
HighlightsCount = 52 HighlightsCount = 52
ReferencesCount = 8 ReferencesCount = 8