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
|
package misc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
|
@ -140,3 +141,83 @@ package main
|
||||||
env.Editor.Hover(env.Ctx, "main.go", env.RegexpSearch("main.go", "foo"))
|
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:
|
case *ast.ImportSpec:
|
||||||
// Try to find the package documentation for an imported package.
|
// Try to find the package documentation for an imported package.
|
||||||
if pkgName, ok := obj.(*types.PkgName); ok {
|
pkgPath, err := strconv.Unquote(node.Path.Value)
|
||||||
imp, err := pkg.GetImport(pkgName.Imported().Path())
|
if err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
return nil, err
|
}
|
||||||
}
|
imp, err := pkg.GetImport(pkgPath)
|
||||||
// Assume that only one file will contain package documentation,
|
if err != nil {
|
||||||
// so pick the first file that has a doc comment.
|
return nil, err
|
||||||
for _, file := range imp.GetSyntax() {
|
}
|
||||||
if file.Doc != nil {
|
// Assume that only one file will contain package documentation,
|
||||||
info = &HoverContext{signatureSource: obj, Comment: file.Doc}
|
// so pick the first file that has a doc comment.
|
||||||
break
|
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:
|
case *ast.GenDecl:
|
||||||
switch obj := obj.(type) {
|
switch obj := obj.(type) {
|
||||||
case *types.TypeName, *types.Var, *types.Const, *types.Func:
|
case *types.TypeName, *types.Var, *types.Const, *types.Func:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue