mirror of https://github.com/golang/go.git
internal/lsp: render package documentation when hovering over a package import
Update FindHoverContext to retrieve & render package documentation for a hovered package. Add a regtest for this hovering feature. Updates golang/go#51848 Change-Id: If57396d59be9c4cf7e09b64e39832de6f996c7ca Reviewed-on: https://go-review.googlesource.com/c/tools/+/400820 Reviewed-by: Robert Findley <rfindley@google.com> Run-TryBot: Dylan Le <dungtuanle@google.com> gopls-CI: kokoro <noreply+kokoro@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
fa7afc95f2
commit
559469ae16
|
|
@ -5,6 +5,7 @@
|
|||
package misc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
|
|
@ -140,3 +141,83 @@ package main
|
|||
env.Editor.Hover(env.Ctx, "main.go", env.RegexpSearch("main.go", "foo"))
|
||||
})
|
||||
}
|
||||
|
||||
func TestHoverImport(t *testing.T) {
|
||||
// For Go.13 and earlier versions, Go will try to download imported but missing packages. This behavior breaks the
|
||||
// workspace as Go fails to download non-existent package "mod.com/lib4"
|
||||
testenv.NeedsGo1Point(t, 14)
|
||||
const packageDoc1 = "Package lib1 hover documentation"
|
||||
const packageDoc2 = "Package lib2 hover documentation"
|
||||
tests := []struct {
|
||||
hoverPackage string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
"mod.com/lib1",
|
||||
packageDoc1,
|
||||
},
|
||||
{
|
||||
"mod.com/lib2",
|
||||
packageDoc2,
|
||||
},
|
||||
{
|
||||
"mod.com/lib3",
|
||||
"",
|
||||
},
|
||||
}
|
||||
source := fmt.Sprintf(`
|
||||
-- go.mod --
|
||||
module mod.com
|
||||
|
||||
go 1.12
|
||||
-- lib1/a.go --
|
||||
// %s
|
||||
package lib1
|
||||
|
||||
const C = 1
|
||||
|
||||
-- lib1/b.go --
|
||||
package lib1
|
||||
|
||||
const D = 1
|
||||
|
||||
-- lib2/a.go --
|
||||
// %s
|
||||
package lib2
|
||||
|
||||
const E = 1
|
||||
|
||||
-- lib3/a.go --
|
||||
package lib3
|
||||
|
||||
const F = 1
|
||||
|
||||
-- main.go --
|
||||
package main
|
||||
|
||||
import (
|
||||
"mod.com/lib1"
|
||||
"mod.com/lib2"
|
||||
"mod.com/lib3"
|
||||
"mod.com/lib4"
|
||||
)
|
||||
|
||||
func main() {
|
||||
println("Hello")
|
||||
}
|
||||
`, packageDoc1, packageDoc2)
|
||||
Run(t, source, func(t *testing.T, env *Env) {
|
||||
env.OpenFile("main.go")
|
||||
for _, test := range tests {
|
||||
got, _ := env.Hover("main.go", env.RegexpSearch("main.go", test.hoverPackage))
|
||||
if !strings.Contains(got.Value, test.want) {
|
||||
t.Errorf("Hover: got:\n%q\nwant:\n%q", got.Value, test.want)
|
||||
}
|
||||
}
|
||||
|
||||
got, _ := env.Hover("main.go", env.RegexpSearch("main.go", "mod.com/lib4"))
|
||||
if got != nil {
|
||||
t.Errorf("Hover: got:\n%q\nwant:\n%v", got.Value, nil)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -510,21 +510,25 @@ func FindHoverContext(ctx context.Context, s Snapshot, pkg Package, obj types.Ob
|
|||
}
|
||||
case *ast.ImportSpec:
|
||||
// Try to find the package documentation for an imported package.
|
||||
if pkgName, ok := obj.(*types.PkgName); ok {
|
||||
imp, err := pkg.GetImport(pkgName.Imported().Path())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Assume that only one file will contain package documentation,
|
||||
// so pick the first file that has a doc comment.
|
||||
for _, file := range imp.GetSyntax() {
|
||||
if file.Doc != nil {
|
||||
info = &HoverContext{signatureSource: obj, Comment: file.Doc}
|
||||
break
|
||||
pkgPath, err := strconv.Unquote(node.Path.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
imp, err := pkg.GetImport(pkgPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Assume that only one file will contain package documentation,
|
||||
// so pick the first file that has a doc comment.
|
||||
for _, file := range imp.GetSyntax() {
|
||||
if file.Doc != nil {
|
||||
info = &HoverContext{Comment: file.Doc}
|
||||
if file.Name != nil {
|
||||
info.signatureSource = "package " + file.Name.Name
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
info = &HoverContext{signatureSource: node}
|
||||
case *ast.GenDecl:
|
||||
switch obj := obj.(type) {
|
||||
case *types.TypeName, *types.Var, *types.Const, *types.Func:
|
||||
|
|
|
|||
Loading…
Reference in New Issue