From 9b156eeb91eecde0cd0a78688c0697605c288ba1 Mon Sep 17 00:00:00 2001 From: fzipp Date: Sun, 6 Feb 2022 14:59:06 +0100 Subject: [PATCH] internal/lsp/source: provide full documentation of builtin types This change adds support for full documentation of builtin types in the hover info, consisting of the type declaration, a link to pkg.go.dev, and the text of the doc comments in the `builtin` pseudo-package. Full documentation for builtin functions was already supported. Removes the special case for the `error` interface, which is not needed and didn't provide the full documentation anyway, only the type declaration. The code has to determine the parent ast.GenDecl (which holds the doc comments) for the ast.TypeSpec of a builtin type. Fixes golang/go#50196 Change-Id: I51a054cd7e864300ba2e51152311744b7bcf3e0c Reviewed-on: https://go-review.googlesource.com/c/tools/+/383614 Trust: Robert Findley Run-TryBot: Robert Findley gopls-CI: kokoro TryBot-Result: Gopher Robot Reviewed-by: Robert Findley Trust: Hyang-Ah Hana Kim --- internal/lsp/source/hover.go | 9 ++++----- internal/lsp/source/identifier.go | 16 ++++++++++++++++ internal/lsp/testdata/godef/a/a.go.golden | 6 +++++- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/internal/lsp/source/hover.go b/internal/lsp/source/hover.go index e8db266f88..a4d3c77830 100644 --- a/internal/lsp/source/hover.go +++ b/internal/lsp/source/hover.go @@ -309,7 +309,8 @@ func HoverIdentifier(ctx context.Context, i *IdentifierInfo) (*HoverInformation, h.LinkPath = strings.Replace(h.LinkPath, mod, mod+"@"+version, 1) } return h, nil - case *types.Builtin: + } + if obj.Parent() == types.Universe { h.importPath = "builtin" h.LinkPath = h.importPath h.LinkAnchor = obj.Name() @@ -520,10 +521,8 @@ func HoverInfo(ctx context.Context, s Snapshot, pkg Package, obj types.Object, p } case *ast.TypeSpec: if obj.Parent() == types.Universe { - if obj.Name() == "error" { - info = &HoverInformation{source: node} - } else { - info = &HoverInformation{source: node.Name} // comments not needed for builtins + if genDecl, ok := fullDecl.(*ast.GenDecl); ok { + info = formatTypeSpec(node, genDecl) } } case *ast.FuncDecl: diff --git a/internal/lsp/source/identifier.go b/internal/lsp/source/identifier.go index f8fddac1ec..e845b906fb 100644 --- a/internal/lsp/source/identifier.go +++ b/internal/lsp/source/identifier.go @@ -217,6 +217,10 @@ func findIdentifier(ctx context.Context, snapshot Snapshot, pkg Package, pgf *Pa return nil, errors.Errorf("no declaration for %s", result.Name) } result.Declaration.node = decl + if typeSpec, ok := decl.(*ast.TypeSpec); ok { + // Find the GenDecl (which has the doc comments) for the TypeSpec. + result.Declaration.fullDecl = findGenDecl(builtin.File, typeSpec) + } // The builtin package isn't in the dependency graph, so the usual // utilities won't work here. @@ -314,6 +318,18 @@ func findIdentifier(ctx context.Context, snapshot Snapshot, pkg Package, pgf *Pa return result, nil } +// findGenDecl determines the parent ast.GenDecl for a given ast.Spec. +func findGenDecl(f *ast.File, spec ast.Spec) *ast.GenDecl { + for _, decl := range f.Decls { + if genDecl, ok := decl.(*ast.GenDecl); ok { + if genDecl.Pos() <= spec.Pos() && genDecl.End() >= spec.End() { + return genDecl + } + } + } + return nil +} + // fullNode tries to extract the full spec corresponding to obj's declaration. // If the package was not parsed in full, the declaration file will be // re-parsed to ensure it has complete syntax. diff --git a/internal/lsp/testdata/godef/a/a.go.golden b/internal/lsp/testdata/godef/a/a.go.golden index 182928eebb..e8ce9079a9 100644 --- a/internal/lsp/testdata/godef/a/a.go.golden +++ b/internal/lsp/testdata/godef/a/a.go.golden @@ -164,8 +164,12 @@ func(t Type, size ...IntegerType) Type The make built\-in function allocates and initializes an object of type slice, map, or chan \(only\)\. -- string-hoverdef -- ```go -string +type string string ``` + +[`string` on pkg.go.dev](https://pkg.go.dev/builtin?utm_source=gopls#string) + +string is the set of all strings of 8\-bit bytes, conventionally but not necessarily representing UTF\-8\-encoded text\. -- typesImport-hoverdef -- ```go package types ("go/types")