gopls/internal/golang: provide version info for stdlib in pkgdoc The available versions are provided for functions and methods. Same as https://pkg.go.dev/ 1. The std lib version is only available for FUNC, METHOD, TYPE. Not available for CONST, VAR & FIELD. Because those types do not have dedicated HTML element, declarations are shown only as source code. 2. Introduce css element stdlibVersion which contains the styles needed. For golang/go#67159 Change-Id: I4b4f469a858a1aca6598f2abed6f990ab1931b00 Reviewed-on: https://go-review.googlesource.com/c/tools/+/595855 Reviewed-by: Robert Findley <rfindley@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/gopls/internal/golang/pkgdoc.go b/gopls/internal/golang/pkgdoc.go index d0e9ffc..8f6b636 100644 --- a/gopls/internal/golang/pkgdoc.go +++ b/gopls/internal/golang/pkgdoc.go
@@ -51,6 +51,7 @@ "golang.org/x/tools/gopls/internal/util/safetoken" "golang.org/x/tools/gopls/internal/util/slices" "golang.org/x/tools/gopls/internal/util/typesutil" + "golang.org/x/tools/internal/stdlib" "golang.org/x/tools/internal/typesinternal" ) @@ -415,6 +416,12 @@ padding: 0.3em; } +.Documentation-sinceVersion { + font-weight: normal; + color: #808080; + float: right; +} + #pkgsite { height: 1.5em; } #hdr-Selector { @@ -782,6 +789,15 @@ values(docpkg.Vars) } + // addedInHTML returns an HTML division containing the Go release version at + // which this obj became available. + addedInHTML := func(obj types.Object) string { + if sym := StdSymbolOf(obj); sym != nil && sym.Version != stdlib.Version(0) { + return fmt.Sprintf("<span class='Documentation-sinceVersion'>added in %v</span>", sym.Version) + } + return "" + } + // package-level functions fmt.Fprintf(&buf, "<h2 id='hdr-Functions'>Functions</h2>\n") // funcs emits a list of package-level functions, @@ -789,8 +805,9 @@ funcs := func(funcs []*doc.Func) { for _, docfn := range funcs { obj := scope.Lookup(docfn.Name).(*types.Func) - fmt.Fprintf(&buf, "<h3 id='%s'>func %s</h3>\n", - docfn.Name, objHTML(pkg.FileSet(), web, obj)) + + fmt.Fprintf(&buf, "<h3 id='%s'>func %s %s</h3>\n", + docfn.Name, objHTML(pkg.FileSet(), web, obj), addedInHTML(obj)) // decl: func F(params) results fmt.Fprintf(&buf, "<pre class='code'>%s</pre>\n", @@ -808,8 +825,8 @@ tname := scope.Lookup(doctype.Name).(*types.TypeName) // title and source link - fmt.Fprintf(&buf, "<h3 id='%s'>type %s</a></h3>\n", - doctype.Name, objHTML(pkg.FileSet(), web, tname)) + fmt.Fprintf(&buf, "<h3 id='%s'>type %s %s</h3>\n", + doctype.Name, objHTML(pkg.FileSet(), web, tname), addedInHTML(tname)) // declaration // TODO(adonovan): excise non-exported struct fields somehow. @@ -828,10 +845,10 @@ // methods on T for _, docmethod := range doctype.Methods { method, _, _ := types.LookupFieldOrMethod(tname.Type(), true, tname.Pkg(), docmethod.Name) - fmt.Fprintf(&buf, "<h4 id='%s.%s'>func (%s) %s</h4>\n", + fmt.Fprintf(&buf, "<h4 id='%s.%s'>func (%s) %s %s</h4>\n", doctype.Name, docmethod.Name, docmethod.Orig, // T or *T - objHTML(pkg.FileSet(), web, method)) + objHTML(pkg.FileSet(), web, method), addedInHTML(method)) // decl: func (x T) M(params) results fmt.Fprintf(&buf, "<pre class='code'>%s</pre>\n",