From 2bdbb87a682d799cf5e262a61a3ef1faf41151af Mon Sep 17 00:00:00 2001 From: Tyler Bui-Palsulich <26876514+tbpg@users.noreply.github.com> Date: Wed, 27 Jan 2021 08:34:02 -0500 Subject: [PATCH] feat(internal/godocfx): xref function declarations (#3615) Type declarations are handled differently. So, I'll handle them in a future PR. There are some TODOs at the top of parse.go with additional ways we can improve. I chose to define linkify in parse.go rather than pkgsite because (1) we need the package/import name logic and (2) I want to keep changes to a minimum in the third_party code. --- internal/godocfx/parse.go | 137 ++++++++++- internal/godocfx/testdata/golden/index.yml | 270 +++++++++++++-------- third_party/pkgsite/synopsis.go | 65 +++-- 3 files changed, 329 insertions(+), 143 deletions(-) diff --git a/internal/godocfx/parse.go b/internal/godocfx/parse.go index 64628591e0d..33932edd7f9 100644 --- a/internal/godocfx/parse.go +++ b/internal/godocfx/parse.go @@ -14,6 +14,13 @@ // +build go1.15 +// TODO: +// pkgsite.PrintType doesn't linkify. +// IDs for const/var groups have every name, not just the one to link to. +// Preserve IDs when sanitizing then use the right ID for linking. +// Link to different domains by pattern (e.g. for cloud.google.com/go). +// Make sure dot imports work (those identifiers aren't in the current package). + package main import ( @@ -148,7 +155,7 @@ func parse(glob string, workingDir string, optionalExtraFiles []string) (*result // Once the files are grouped by package, process each package // independently. for _, pi := range pkgInfos { - + link := newLinker(pi.pkg.Imports, pi.importRenames) pkgItem := &item{ UID: pi.doc.ImportPath, Name: pi.doc.ImportPath, @@ -255,7 +262,7 @@ func parse(glob string, workingDir string, optionalExtraFiles []string) (*result Type: "function", Summary: fn.Doc, Langs: onlyGo, - Syntax: syntax{Content: pkgsite.Synopsis(pi.fset, fn.Decl)}, + Syntax: syntax{Content: pkgsite.Synopsis(pi.fset, fn.Decl, link.linkify)}, Examples: processExamples(fn.Examples, pi.fset), }) } @@ -270,7 +277,7 @@ func parse(glob string, workingDir string, optionalExtraFiles []string) (*result Type: "method", Summary: fn.Doc, Langs: onlyGo, - Syntax: syntax{Content: pkgsite.Synopsis(pi.fset, fn.Decl)}, + Syntax: syntax{Content: pkgsite.Synopsis(pi.fset, fn.Decl, link.linkify)}, Examples: processExamples(fn.Examples, pi.fset), }) } @@ -286,7 +293,7 @@ func parse(glob string, workingDir string, optionalExtraFiles []string) (*result Type: "function", Summary: fn.Doc, Langs: onlyGo, - Syntax: syntax{Content: pkgsite.Synopsis(pi.fset, fn.Decl)}, + Syntax: syntax{Content: pkgsite.Synopsis(pi.fset, fn.Decl, link.linkify)}, Examples: processExamples(fn.Examples, pi.fset), }) } @@ -300,6 +307,66 @@ func parse(glob string, workingDir string, optionalExtraFiles []string) (*result }, nil } +type linker struct { + // imports is a map from local package name to import path. + // Behavior is undefined when a single import has different names in + // different files. + imports map[string]string +} + +func newLinker(rawImports map[string]*packages.Package, importSyntax map[string]string) *linker { + imports := map[string]string{} + for path, pkg := range rawImports { + name := pkg.Name + if rename := importSyntax[path]; rename != "" { + name = rename + } + imports[name] = path + } + return &linker{imports: imports} +} + +func (l *linker) linkify(s string) string { + prefix := "" + if strings.HasPrefix(s, "...") { + s = s[3:] + prefix = "..." + } + if s[0] == '*' { + s = s[1:] + prefix += "*" + } + + // If s does not have a dot, it's in this package. + if !strings.Contains(s, ".") { + // If s is not exported, it's probably a builtin. + if !token.IsExported(s) { + if builtins[s] { + return fmt.Sprintf(`%s%s`, prefix, strings.ToLower(s), s) + } + return fmt.Sprintf("%s%s", prefix, s) + } + return fmt.Sprintf(`%s%s`, prefix, strings.ToLower(s), s) + } + // Otherwise, it's in another package. + split := strings.Split(s, ".") + if len(split) != 2 { + // Don't know how to link this. + return fmt.Sprintf("%s%s", prefix, s) + } + + pkg := split[0] + pkgPath, ok := l.imports[pkg] + if !ok { + // Don't know how to link this. + return fmt.Sprintf("%s%s", prefix, s) + } + name := split[1] + pkgLink := fmt.Sprintf("http://pkg.go.dev/%s", pkgPath) + link := fmt.Sprintf("%s#%s", pkgLink, name) + return fmt.Sprintf("%s%s.%s", prefix, pkgLink, pkg, link, name) +} + // processExamples converts the examples to []example. // // Surrounding braces and indentation is removed. @@ -400,11 +467,13 @@ type pkgInfo struct { pkg *packages.Package doc *doc.Package fset *token.FileSet + // importRenames is a map from package path to local name or "". + importRenames map[string]string } func loadPackages(glob, workingDir string) ([]pkgInfo, error) { config := &packages.Config{ - Mode: packages.NeedName | packages.NeedSyntax | packages.NeedTypes | packages.NeedTypesInfo | packages.NeedModule, + Mode: packages.NeedName | packages.NeedSyntax | packages.NeedTypes | packages.NeedTypesInfo | packages.NeedModule | packages.NeedImports, Tests: true, Dir: workingDir, } @@ -494,12 +563,64 @@ func loadPackages(glob, workingDir string) ([]pkgInfo, error) { continue } + imports := map[string]string{} + for _, f := range parsedFiles { + for _, i := range f.Imports { + name := "" + // i.Name is nil for imports that aren't renamed. + if i.Name != nil { + name = i.Name.Name + } + iPath := strings.Trim(i.Path.Value, `"`) + imports[iPath] = name + } + } + result = append(result, pkgInfo{ - pkg: idToPkg[pkgPath], - doc: docPkg, - fset: fset, + pkg: idToPkg[pkgPath], + doc: docPkg, + fset: fset, + importRenames: imports, }) } return result, nil } + +var builtins = map[string]bool{ + "append": true, + "cap": true, + "close": true, + "complex": true, + "copy": true, + "delete": true, + "imag": true, + "len": true, + "make": true, + "new": true, + "panic": true, + "print": true, + "println": true, + "real": true, + "recover": true, + "bool": true, + "byte": true, + "complex128": true, + "complex64": true, + "error": true, + "float32": true, + "float64": true, + "int": true, + "int16": true, + "int32": true, + "int64": true, + "int8": true, + "rune": true, + "string": true, + "uint": true, + "uint16": true, + "uint32": true, + "uint64": true, + "uint8": true, + "uintptr": true, +} diff --git a/internal/godocfx/testdata/golden/index.yml b/internal/godocfx/testdata/golden/index.yml index 018b540eaad..73c6c15cf0f 100644 --- a/internal/godocfx/testdata/golden/index.yml +++ b/internal/godocfx/testdata/golden/index.yml @@ -348,8 +348,9 @@ items: langs: - go syntax: - content: func (a *ACLHandle) Delete(ctx context.Context, entity ACLEntity) (err - error) + content: func (a *ACLHandle) Delete(ctx context.Context, entity ACLEntity) + (err error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -367,7 +368,9 @@ items: langs: - go syntax: - content: func (a *ACLHandle) List(ctx context.Context) (rules []ACLRule, err error) + content: func (a *ACLHandle) List(ctx context.Context) (rules []ACLRule, + err error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n\t\"fmt\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -385,8 +388,9 @@ items: langs: - go syntax: - content: func (a *ACLHandle) Set(ctx context.Context, entity ACLEntity, role ACLRole) - (err error) + content: func (a *ACLHandle) Set(ctx context.Context, entity ACLEntity, + role ACLRole) (err error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -540,7 +544,8 @@ items: langs: - go syntax: - content: func (ua *BucketAttrsToUpdate) DeleteLabel(name string) + content: func (ua *BucketAttrsToUpdate) DeleteLabel(name + string) - uid: cloud.google.com/go/storage.BucketAttrsToUpdate.SetLabel name: | func (*BucketAttrsToUpdate) SetLabel @@ -553,7 +558,8 @@ items: langs: - go syntax: - content: func (ua *BucketAttrsToUpdate) SetLabel(name, value string) + content: func (ua *BucketAttrsToUpdate) SetLabel(name, + value string) - uid: cloud.google.com/go/storage.BucketConditions name: BucketConditions id: BucketConditions @@ -619,7 +625,7 @@ items: langs: - go syntax: - content: func (b *BucketHandle) ACL() *ACLHandle + content: func (b *BucketHandle) ACL() *ACLHandle - uid: cloud.google.com/go/storage.BucketHandle.AddNotification name: | func (*BucketHandle) AddNotification @@ -633,8 +639,10 @@ items: langs: - go syntax: - content: func (b *BucketHandle) AddNotification(ctx context.Context, n *Notification) - (ret *Notification, err error) + content: func (b *BucketHandle) AddNotification(ctx + context.Context, + n *Notification) (ret *Notification, + err error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n\t\"fmt\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -653,8 +661,9 @@ items: langs: - go syntax: - content: func (b *BucketHandle) Attrs(ctx context.Context) (attrs *BucketAttrs, - err error) + content: func (b *BucketHandle) Attrs(ctx context.Context) (attrs *BucketAttrs, + err error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n\t\"fmt\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -672,8 +681,9 @@ items: langs: - go syntax: - content: func (b *BucketHandle) Create(ctx context.Context, projectID string, - attrs *BucketAttrs) (err error) + content: func (b *BucketHandle) Create(ctx context.Context, projectID string, + attrs *BucketAttrs) (err error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -692,7 +702,8 @@ items: langs: - go syntax: - content: func (b *BucketHandle) DefaultObjectACL() *ACLHandle + content: func (b *BucketHandle) DefaultObjectACL() + *ACLHandle - uid: cloud.google.com/go/storage.BucketHandle.Delete name: | func (*BucketHandle) Delete @@ -704,7 +715,8 @@ items: langs: - go syntax: - content: func (b *BucketHandle) Delete(ctx context.Context) (err error) + content: func (b *BucketHandle) Delete(ctx context.Context) (err error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -721,8 +733,9 @@ items: langs: - go syntax: - content: func (b *BucketHandle) DeleteNotification(ctx context.Context, id string) - (err error) + content: func (b *BucketHandle) DeleteNotification(ctx + context.Context, + id string) (err error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n)\n\nvar notificationID string\n\nfunc main() {\n\tctx := context.Background()\n\tclient, @@ -741,7 +754,8 @@ items: langs: - go syntax: - content: func (b *BucketHandle) IAM() *iam.Handle + content: func (b *BucketHandle) IAM() *iam.Handle - uid: cloud.google.com/go/storage.BucketHandle.If name: | func (*BucketHandle) If @@ -757,7 +771,8 @@ items: langs: - go syntax: - content: func (b *BucketHandle) If(conds BucketConditions) *BucketHandle + content: func (b *BucketHandle) If(conds BucketConditions) + *BucketHandle - uid: cloud.google.com/go/storage.BucketHandle.LockRetentionPolicy name: | func (*BucketHandle) LockRetentionPolicy @@ -777,7 +792,9 @@ items: langs: - go syntax: - content: func (b *BucketHandle) LockRetentionPolicy(ctx context.Context) error + content: func (b *BucketHandle) LockRetentionPolicy(ctx + context.Context) + error codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -799,8 +816,10 @@ items: langs: - go syntax: - content: func (b *BucketHandle) Notifications(ctx context.Context) (n map[string]*Notification, - err error) + content: func (b *BucketHandle) Notifications(ctx + context.Context) + (n map[string]*Notification, + err error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n\t\"fmt\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -823,7 +842,8 @@ items: langs: - go syntax: - content: func (b *BucketHandle) Object(name string) *ObjectHandle + content: func (b *BucketHandle) Object(name string) + *ObjectHandle - uid: cloud.google.com/go/storage.BucketHandle.Objects name: | func (*BucketHandle) Objects @@ -838,7 +858,9 @@ items: langs: - go syntax: - content: func (b *BucketHandle) Objects(ctx context.Context, q *Query) *ObjectIterator + content: func (b *BucketHandle) Objects(ctx context.Context, q *Query) + *ObjectIterator codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -855,8 +877,9 @@ items: langs: - go syntax: - content: func (b *BucketHandle) Update(ctx context.Context, uattrs BucketAttrsToUpdate) - (attrs *BucketAttrs, err error) + content: func (b *BucketHandle) Update(ctx context.Context, uattrs BucketAttrsToUpdate) + (attrs *BucketAttrs, err error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n\t\"fmt\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -887,7 +910,8 @@ items: langs: - go syntax: - content: func (b *BucketHandle) UserProject(projectID string) *BucketHandle + content: func (b *BucketHandle) UserProject(projectID + string) *BucketHandle - uid: cloud.google.com/go/storage.BucketIterator name: BucketIterator id: BucketIterator @@ -918,7 +942,8 @@ items: langs: - go syntax: - content: func (it *BucketIterator) Next() (*BucketAttrs, error) + content: func (it *BucketIterator) Next() (*BucketAttrs, + error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n\t\"fmt\"\n\t\"google.golang.org/api/iterator\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -938,7 +963,8 @@ items: langs: - go syntax: - content: func (it *BucketIterator) PageInfo() *iterator.PageInfo + content: func (it *BucketIterator) PageInfo() *iterator.PageInfo - uid: cloud.google.com/go/storage.BucketLogging name: BucketLogging id: BucketLogging @@ -1039,8 +1065,10 @@ items: langs: - go syntax: - content: func NewClient(ctx context.Context, opts ...option.ClientOption) (*Client, - error) + content: func NewClient(ctx context.Context, opts ...option.ClientOption) + (*Client, error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\t// Use Google Application Default @@ -1072,7 +1100,8 @@ items: langs: - go syntax: - content: func (c *Client) Bucket(name string) *BucketHandle + content: func (c *Client) Bucket(name string) + *BucketHandle - uid: cloud.google.com/go/storage.Client.Buckets name: | func (*Client) Buckets @@ -1089,7 +1118,9 @@ items: langs: - go syntax: - content: func (c *Client) Buckets(ctx context.Context, projectID string) *BucketIterator + content: func (c *Client) Buckets(ctx context.Context, projectID string) + *BucketIterator codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -1108,7 +1139,7 @@ items: langs: - go syntax: - content: func (c *Client) Close() error + content: func (c *Client) Close() error - uid: cloud.google.com/go/storage.Client.CreateHMACKey name: | func (*Client) CreateHMACKey @@ -1122,8 +1153,10 @@ items: langs: - go syntax: - content: func (c *Client) CreateHMACKey(ctx context.Context, projectID, serviceAccountEmail - string, ...) (*HMACKey, error) + content: func (c *Client) CreateHMACKey(ctx context.Context, projectID, serviceAccountEmail + string, opts ...HMACKeyOption) + (*HMACKey, error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -1143,7 +1176,8 @@ items: langs: - go syntax: - content: func (c *Client) HMACKeyHandle(projectID, accessID string) *HMACKeyHandle + content: func (c *Client) HMACKeyHandle(projectID, accessID + string) *HMACKeyHandle - uid: cloud.google.com/go/storage.Client.ListHMACKeys name: | func (*Client) ListHMACKeys @@ -1159,8 +1193,9 @@ items: langs: - go syntax: - content: func (c *Client) ListHMACKeys(ctx context.Context, projectID string, - opts ...HMACKeyOption) *HMACKeysIterator + content: func (c *Client) ListHMACKeys(ctx context.Context, projectID string, + opts ...HMACKeyOption) *HMACKeysIterator codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n\t\"google.golang.org/api/iterator\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -1194,8 +1229,9 @@ items: langs: - go syntax: - content: func (c *Client) ServiceAccount(ctx context.Context, projectID string) - (string, error) + content: func (c *Client) ServiceAccount(ctx context.Context, projectID string) + (string, error) - uid: cloud.google.com/go/storage.Composer name: Composer id: Composer @@ -1228,8 +1264,9 @@ items: langs: - go syntax: - content: func (c *Composer) Run(ctx context.Context) (attrs *ObjectAttrs, err - error) + content: func (c *Composer) Run(ctx context.Context) (attrs *ObjectAttrs, + err error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n\t\"fmt\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -1313,7 +1350,9 @@ items: langs: - go syntax: - content: func (c *Copier) Run(ctx context.Context) (attrs *ObjectAttrs, err error) + content: func (c *Copier) Run(ctx context.Context) (attrs *ObjectAttrs, + err error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n\t\"fmt\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -1401,8 +1440,9 @@ items: langs: - go syntax: - content: func (hkh *HMACKeyHandle) Delete(ctx context.Context, opts ...HMACKeyOption) - error + content: func (hkh *HMACKeyHandle) Delete(ctx context.Context, + opts ...HMACKeyOption) error codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -1427,8 +1467,9 @@ items: langs: - go syntax: - content: func (hkh *HMACKeyHandle) Get(ctx context.Context, opts ...HMACKeyOption) - (*HMACKey, error) + content: func (hkh *HMACKeyHandle) Get(ctx context.Context, opts ...HMACKeyOption) + (*HMACKey, error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -1448,8 +1489,10 @@ items: langs: - go syntax: - content: func (h *HMACKeyHandle) Update(ctx context.Context, au HMACKeyAttrsToUpdate, - opts ...HMACKeyOption) (*HMACKey, error) + content: func (h *HMACKeyHandle) Update(ctx context.Context, au HMACKeyAttrsToUpdate, + opts ...HMACKeyOption) (*HMACKey, + error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -1488,7 +1531,8 @@ items: langs: - go syntax: - content: func ForHMACKeyServiceAccountEmail(serviceAccountEmail string) HMACKeyOption + content: func ForHMACKeyServiceAccountEmail(serviceAccountEmail string) + HMACKeyOption - uid: cloud.google.com/go/storage.HMACKeyOption.ShowDeletedHMACKeys name: | func ShowDeletedHMACKeys @@ -1502,7 +1546,7 @@ items: langs: - go syntax: - content: func ShowDeletedHMACKeys() HMACKeyOption + content: func ShowDeletedHMACKeys() HMACKeyOption - uid: cloud.google.com/go/storage.HMACKeyOption.UserProjectForHMACKeys name: | func UserProjectForHMACKeys @@ -1519,7 +1563,8 @@ items: langs: - go syntax: - content: func UserProjectForHMACKeys(userProjectID string) HMACKeyOption + content: func UserProjectForHMACKeys(userProjectID string) + HMACKeyOption - uid: cloud.google.com/go/storage.HMACKeysIterator name: HMACKeysIterator id: HMACKeysIterator @@ -1553,7 +1598,8 @@ items: langs: - go syntax: - content: func (it *HMACKeysIterator) Next() (*HMACKey, error) + content: func (it *HMACKeysIterator) Next() (*HMACKey, error) - uid: cloud.google.com/go/storage.HMACKeysIterator.PageInfo name: | func (*HMACKeysIterator) PageInfo @@ -1569,7 +1615,9 @@ items: langs: - go syntax: - content: func (it *HMACKeysIterator) PageInfo() *iterator.PageInfo + content: func (it *HMACKeysIterator) PageInfo() + *iterator.PageInfo - uid: cloud.google.com/go/storage.HMACState name: HMACState id: HMACState @@ -1865,7 +1913,7 @@ items: langs: - go syntax: - content: func (o *ObjectHandle) ACL() *ACLHandle + content: func (o *ObjectHandle) ACL() *ACLHandle - uid: cloud.google.com/go/storage.ObjectHandle.Attrs name: | func (*ObjectHandle) Attrs @@ -1878,8 +1926,9 @@ items: langs: - go syntax: - content: func (o *ObjectHandle) Attrs(ctx context.Context) (attrs *ObjectAttrs, - err error) + content: func (o *ObjectHandle) Attrs(ctx context.Context) (attrs *ObjectAttrs, + err error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n\t\"fmt\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -1905,7 +1954,7 @@ items: langs: - go syntax: - content: func (o *ObjectHandle) BucketName() string + content: func (o *ObjectHandle) BucketName() string - uid: cloud.google.com/go/storage.ObjectHandle.ComposerFrom name: | func (*ObjectHandle) ComposerFrom @@ -1923,7 +1972,8 @@ items: langs: - go syntax: - content: func (dst *ObjectHandle) ComposerFrom(srcs ...*ObjectHandle) *Composer + content: func (dst *ObjectHandle) ComposerFrom(srcs + ...*ObjectHandle) *Composer - uid: cloud.google.com/go/storage.ObjectHandle.CopierFrom name: | func (*ObjectHandle) CopierFrom @@ -1940,7 +1990,8 @@ items: langs: - go syntax: - content: func (dst *ObjectHandle) CopierFrom(src *ObjectHandle) *Copier + content: func (dst *ObjectHandle) CopierFrom(src *ObjectHandle) *Copier codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n)\n\nvar key1, key2 []byte\n\nfunc main() {\n\t// To rotate the encryption key on an @@ -1961,7 +2012,8 @@ items: langs: - go syntax: - content: func (o *ObjectHandle) Delete(ctx context.Context) error + content: func (o *ObjectHandle) Delete(ctx context.Context) error codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n\t\"fmt\"\n\t\"google.golang.org/api/iterator\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -1990,7 +2042,8 @@ items: langs: - go syntax: - content: func (o *ObjectHandle) Generation(gen int64) *ObjectHandle + content: func (o *ObjectHandle) Generation(gen int64) *ObjectHandle codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n\t\"io\"\n\t\"os\"\n)\n\nvar gen int64\n\nfunc main() {\n\t// Read an object's contents from generation gen, @@ -2014,7 +2067,8 @@ items: langs: - go syntax: - content: func (o *ObjectHandle) If(conds Conditions) *ObjectHandle + content: func (o *ObjectHandle) If(conds Conditions) + *ObjectHandle codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n\t\"google.golang.org/api/googleapi\"\n\t\"io\"\n\t\"net/http\"\n\t\"os\"\n)\n\nvar gen int64\n\nfunc main() {\n\t// Read from an object only if the current generation @@ -2042,7 +2096,8 @@ items: langs: - go syntax: - content: func (o *ObjectHandle) Key(encryptionKey []byte) *ObjectHandle + content: func (o *ObjectHandle) Key(encryptionKey + []byte) *ObjectHandle codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n)\n\nvar secretKey []byte\n\nfunc main() {\n\tctx := context.Background()\n\tclient, @@ -2071,8 +2126,10 @@ items: langs: - go syntax: - content: func (o *ObjectHandle) NewRangeReader(ctx context.Context, offset, length - int64) (r *Reader, err error) + content: func (o *ObjectHandle) NewRangeReader(ctx + context.Context, + offset, length int64) (r *Reader, err error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n\t\"fmt\"\n\t\"io/ioutil\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -2112,7 +2169,9 @@ items: langs: - go syntax: - content: func (o *ObjectHandle) NewReader(ctx context.Context) (*Reader, error) + content: func (o *ObjectHandle) NewReader(ctx context.Context) (*Reader, + error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n\t\"fmt\"\n\t\"io/ioutil\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -2145,7 +2204,8 @@ items: langs: - go syntax: - content: func (o *ObjectHandle) NewWriter(ctx context.Context) *Writer + content: func (o *ObjectHandle) NewWriter(ctx context.Context) *Writer codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -2162,7 +2222,7 @@ items: langs: - go syntax: - content: func (o *ObjectHandle) ObjectName() string + content: func (o *ObjectHandle) ObjectName() string - uid: cloud.google.com/go/storage.ObjectHandle.ReadCompressed name: | func (*ObjectHandle) ReadCompressed @@ -2174,7 +2234,8 @@ items: langs: - go syntax: - content: func (o *ObjectHandle) ReadCompressed(compressed bool) *ObjectHandle + content: func (o *ObjectHandle) ReadCompressed(compressed + bool) *ObjectHandle - uid: cloud.google.com/go/storage.ObjectHandle.Update name: | func (*ObjectHandle) Update @@ -2188,8 +2249,9 @@ items: langs: - go syntax: - content: func (o *ObjectHandle) Update(ctx context.Context, uattrs ObjectAttrsToUpdate) - (oa *ObjectAttrs, err error) + content: func (o *ObjectHandle) Update(ctx context.Context, uattrs ObjectAttrsToUpdate) + (oa *ObjectAttrs, err error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n\t\"fmt\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -2230,7 +2292,8 @@ items: langs: - go syntax: - content: func (it *ObjectIterator) Next() (*ObjectAttrs, error) + content: func (it *ObjectIterator) Next() (*ObjectAttrs, + error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n\t\"fmt\"\n\t\"google.golang.org/api/iterator\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -2250,7 +2313,8 @@ items: langs: - go syntax: - content: func (it *ObjectIterator) PageInfo() *iterator.PageInfo + content: func (it *ObjectIterator) PageInfo() *iterator.PageInfo - uid: cloud.google.com/go/storage.PolicyV4Fields name: PolicyV4Fields id: PolicyV4Fields @@ -2303,8 +2367,9 @@ items: langs: - go syntax: - content: func GenerateSignedPostPolicyV4(bucket, object string, opts *PostPolicyV4Options) - (*PostPolicyV4, error) + content: func GenerateSignedPostPolicyV4(bucket, object string, + opts *PostPolicyV4Options) (*PostPolicyV4, + error) codeexamples: - content: "package main\n\nimport (\n\t\"bytes\"\n\t\"cloud.google.com/go/storage\"\n\t\"io\"\n\t\"mime/multipart\"\n\t\"net/http\"\n\t\"time\"\n)\n\nfunc main() {\n\tpv4, err := storage.GenerateSignedPostPolicyV4(\"my-bucket\", \"my-object.txt\", @@ -2354,7 +2419,8 @@ items: langs: - go syntax: - content: func ConditionContentLengthRange(start, end uint64) PostPolicyV4Condition + content: func ConditionContentLengthRange(start, end uint64) + PostPolicyV4Condition - uid: cloud.google.com/go/storage.PostPolicyV4Condition.ConditionStartsWith name: | func ConditionStartsWith @@ -2367,7 +2433,8 @@ items: langs: - go syntax: - content: func ConditionStartsWith(key, value string) PostPolicyV4Condition + content: func ConditionStartsWith(key, value string) + PostPolicyV4Condition - uid: cloud.google.com/go/storage.PostPolicyV4Options name: PostPolicyV4Options id: PostPolicyV4Options @@ -2469,7 +2536,8 @@ items: langs: - go syntax: - content: func (q *Query) SetAttrSelection(attrs []string) error + content: func (q *Query) SetAttrSelection(attrs []string) + error - uid: cloud.google.com/go/storage.Reader name: Reader id: Reader @@ -2500,7 +2568,7 @@ items: langs: - go syntax: - content: func (r *Reader) CacheControl() string + content: func (r *Reader) CacheControl() string - uid: cloud.google.com/go/storage.Reader.Close name: | func (*Reader) Close @@ -2512,7 +2580,7 @@ items: langs: - go syntax: - content: func (r *Reader) Close() error + content: func (r *Reader) Close() error - uid: cloud.google.com/go/storage.Reader.ContentEncoding name: | func (*Reader) ContentEncoding @@ -2526,7 +2594,7 @@ items: langs: - go syntax: - content: func (r *Reader) ContentEncoding() string + content: func (r *Reader) ContentEncoding() string - uid: cloud.google.com/go/storage.Reader.ContentType name: | func (*Reader) ContentType @@ -2540,7 +2608,7 @@ items: langs: - go syntax: - content: func (r *Reader) ContentType() string + content: func (r *Reader) ContentType() string - uid: cloud.google.com/go/storage.Reader.LastModified name: | func (*Reader) LastModified @@ -2554,7 +2622,8 @@ items: langs: - go syntax: - content: func (r *Reader) LastModified() (time.Time, error) + content: func (r *Reader) LastModified() (time.Time, error) - uid: cloud.google.com/go/storage.Reader.Read name: | func (*Reader) Read @@ -2564,7 +2633,8 @@ items: langs: - go syntax: - content: func (r *Reader) Read(p []byte) (int, error) + content: func (r *Reader) Read(p []byte) + (int, error) - uid: cloud.google.com/go/storage.Reader.Remain name: | func (*Reader) Remain @@ -2576,7 +2646,7 @@ items: langs: - go syntax: - content: func (r *Reader) Remain() int64 + content: func (r *Reader) Remain() int64 - uid: cloud.google.com/go/storage.Reader.Size name: | func (*Reader) Size @@ -2592,7 +2662,7 @@ items: langs: - go syntax: - content: func (r *Reader) Size() int64 + content: func (r *Reader) Size() int64 - uid: cloud.google.com/go/storage.ReaderObjectAttrs name: ReaderObjectAttrs id: ReaderObjectAttrs @@ -2758,7 +2828,8 @@ items: langs: - go syntax: - content: func BucketBoundHostname(hostname string) URLStyle + content: func BucketBoundHostname(hostname string) + URLStyle - uid: cloud.google.com/go/storage.URLStyle.PathStyle name: | func PathStyle @@ -2771,7 +2842,7 @@ items: langs: - go syntax: - content: func PathStyle() URLStyle + content: func PathStyle() URLStyle - uid: cloud.google.com/go/storage.URLStyle.VirtualHostedStyle name: | func VirtualHostedStyle @@ -2784,7 +2855,7 @@ items: langs: - go syntax: - content: func VirtualHostedStyle() URLStyle + content: func VirtualHostedStyle() URLStyle - uid: cloud.google.com/go/storage.UniformBucketLevelAccess name: UniformBucketLevelAccess id: UniformBucketLevelAccess @@ -2852,7 +2923,7 @@ items: langs: - go syntax: - content: func (w *Writer) Attrs() *ObjectAttrs + content: func (w *Writer) Attrs() *ObjectAttrs - uid: cloud.google.com/go/storage.Writer.Close name: | func (*Writer) Close @@ -2866,7 +2937,7 @@ items: langs: - go syntax: - content: func (w *Writer) Close() error + content: func (w *Writer) Close() error - uid: cloud.google.com/go/storage.Writer.CloseWithError name: | func (*Writer) CloseWithError @@ -2881,7 +2952,8 @@ items: langs: - go syntax: - content: func (w *Writer) CloseWithError(err error) error + content: func (w *Writer) CloseWithError(err error) + error - uid: cloud.google.com/go/storage.Writer.Write name: | func (*Writer) Write @@ -2901,7 +2973,8 @@ items: langs: - go syntax: - content: func (w *Writer) Write(p []byte) (n int, err error) + content: func (w *Writer) Write(p []byte) + (n int, err error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"context\"\n\t\"fmt\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\tclient, err := storage.NewClient(ctx)\n\tif @@ -2948,8 +3021,9 @@ items: langs: - go syntax: - content: func SignedURL(bucket, name string, opts *SignedURLOptions) (string, - error) + content: func SignedURL(bucket, name string, + opts *SignedURLOptions) (string, + error) codeexamples: - content: "package main\n\nimport (\n\t\"cloud.google.com/go/storage\"\n\t\"fmt\"\n\t\"io/ioutil\"\n\t\"time\"\n)\n\nfunc main() {\n\tpkey, err := ioutil.ReadFile(\"my-private-key.pem\")\n\tif err != diff --git a/third_party/pkgsite/synopsis.go b/third_party/pkgsite/synopsis.go index 84d29d37aca..bfe10cc71d3 100644 --- a/third_party/pkgsite/synopsis.go +++ b/third_party/pkgsite/synopsis.go @@ -16,14 +16,14 @@ import ( const maxSynopsisNodeDepth = 10 // Synopsis returns a one-line summary of the given input node. -func Synopsis(fset *token.FileSet, n ast.Node) string { - return oneLineNodeDepth(fset, n, 0) +func Synopsis(fset *token.FileSet, n ast.Node, linkify func(string) string) string { + return oneLineNodeDepth(fset, n, 0, linkify) } // oneLineNodeDepth returns a one-line summary of the given input node. // The depth specifies the current depth when traversing the AST and the // function will stop traversing once depth reaches maxSynopsisNodeDepth. -func oneLineNodeDepth(fset *token.FileSet, node ast.Node, depth int) string { +func oneLineNodeDepth(fset *token.FileSet, node ast.Node, depth int, linkify func(string) string) string { const dotDotDot = "..." if depth == maxSynopsisNodeDepth { return dotDotDot @@ -52,20 +52,20 @@ func oneLineNodeDepth(fset *token.FileSet, node ast.Node, depth int) string { // The type name may carry over from a previous specification in the // case of constants and iota. if valueSpec.Type != nil { - typ = fmt.Sprintf(" %s", oneLineNodeDepth(fset, valueSpec.Type, depth)) + typ = fmt.Sprintf(" %s", oneLineNodeDepth(fset, valueSpec.Type, depth, linkify)) } else if len(valueSpec.Values) > 0 { typ = "" } val := "" if i < len(valueSpec.Values) && valueSpec.Values[i] != nil { - val = fmt.Sprintf(" = %s", oneLineNodeDepth(fset, valueSpec.Values[i], depth)) + val = fmt.Sprintf(" = %s", oneLineNodeDepth(fset, valueSpec.Values[i], depth, linkify)) } return fmt.Sprintf("%s %s%s%s%s", n.Tok, valueSpec.Names[0], typ, val, trailer) } case token.TYPE: if len(n.Specs) > 0 { - return oneLineNodeDepth(fset, n.Specs[0], depth) + trailer + return oneLineNodeDepth(fset, n.Specs[0], depth, linkify) + trailer } case token.IMPORT: if len(n.Specs) > 0 { @@ -78,11 +78,11 @@ func oneLineNodeDepth(fset *token.FileSet, node ast.Node, depth int) string { case *ast.FuncDecl: // Formats func declarations. name := n.Name.Name - recv := oneLineNodeDepth(fset, n.Recv, depth) + recv := oneLineNodeDepth(fset, n.Recv, depth, linkify) if len(recv) > 0 { recv = "(" + recv + ") " } - fnc := oneLineNodeDepth(fset, n.Type, depth) + fnc := oneLineNodeDepth(fset, n.Type, depth, linkify) if strings.Index(fnc, "func") == 0 { fnc = fnc[4:] } @@ -93,13 +93,13 @@ func oneLineNodeDepth(fset *token.FileSet, node ast.Node, depth int) string { if n.Assign.IsValid() { sep = " = " } - return fmt.Sprintf("type %s%s%s", n.Name.Name, sep, oneLineNodeDepth(fset, n.Type, depth)) + return fmt.Sprintf("type %s%s%s", n.Name.Name, sep, oneLineNodeDepth(fset, n.Type, depth, linkify)) case *ast.FuncType: var params []string if n.Params != nil { for _, field := range n.Params.List { - params = append(params, oneLineField(fset, field, depth)) + params = append(params, oneLineField(fset, field, depth, linkify)) } } needParens := false @@ -108,7 +108,7 @@ func oneLineNodeDepth(fset *token.FileSet, node ast.Node, depth int) string { needParens = needParens || len(n.Results.List) > 1 for _, field := range n.Results.List { needParens = needParens || len(field.Names) > 0 - results = append(results, oneLineField(fset, field, depth)) + results = append(results, oneLineField(fset, field, depth, linkify)) } } @@ -139,43 +139,43 @@ func oneLineNodeDepth(fset *token.FileSet, node ast.Node, depth int) string { return "" } if len(n.List) == 1 { - return oneLineField(fset, n.List[0], depth) + return oneLineField(fset, n.List[0], depth, linkify) } return dotDotDot case *ast.FuncLit: - return oneLineNodeDepth(fset, n.Type, depth) + " { ... }" + return oneLineNodeDepth(fset, n.Type, depth, linkify) + " { ... }" case *ast.CompositeLit: - typ := oneLineNodeDepth(fset, n.Type, depth) + typ := oneLineNodeDepth(fset, n.Type, depth, linkify) if len(n.Elts) == 0 { return fmt.Sprintf("%s{}", typ) } return fmt.Sprintf("%s{ %s }", typ, dotDotDot) case *ast.ArrayType: - length := oneLineNodeDepth(fset, n.Len, depth) - element := oneLineNodeDepth(fset, n.Elt, depth) + length := oneLineNodeDepth(fset, n.Len, depth, linkify) + element := oneLineNodeDepth(fset, n.Elt, depth, linkify) return fmt.Sprintf("[%s]%s", length, element) case *ast.MapType: - key := oneLineNodeDepth(fset, n.Key, depth) - value := oneLineNodeDepth(fset, n.Value, depth) + key := oneLineNodeDepth(fset, n.Key, depth, linkify) + value := oneLineNodeDepth(fset, n.Value, depth, linkify) return fmt.Sprintf("map[%s]%s", key, value) case *ast.CallExpr: - fnc := oneLineNodeDepth(fset, n.Fun, depth) + fnc := oneLineNodeDepth(fset, n.Fun, depth, linkify) var args []string for _, arg := range n.Args { - args = append(args, oneLineNodeDepth(fset, arg, depth)) + args = append(args, oneLineNodeDepth(fset, arg, depth, linkify)) } return fmt.Sprintf("%s(%s)", fnc, joinStrings(args)) case *ast.UnaryExpr: - return fmt.Sprintf("%s%s", n.Op, oneLineNodeDepth(fset, n.X, depth)) + return fmt.Sprintf("%s%s", n.Op, oneLineNodeDepth(fset, n.X, depth, linkify)) case *ast.Ident: - return n.Name + return linkify(n.Name) default: // As a fallback, use default formatter for all unknown node types. @@ -185,33 +185,24 @@ func oneLineNodeDepth(fset *token.FileSet, node ast.Node, depth int) string { if strings.Contains(s, "\n") { return dotDotDot } - return s + return linkify(s) } } // oneLineField returns a one-line summary of the field. -func oneLineField(fset *token.FileSet, field *ast.Field, depth int) string { +func oneLineField(fset *token.FileSet, field *ast.Field, depth int, linkify func(string) string) string { var names []string for _, name := range field.Names { names = append(names, name.Name) } + t := oneLineNodeDepth(fset, field.Type, depth, linkify) if len(names) == 0 { - return oneLineNodeDepth(fset, field.Type, depth) + return t } - return joinStrings(names) + " " + oneLineNodeDepth(fset, field.Type, depth) + return joinStrings(names) + " " + t } -// joinStrings formats the input as a comma-separated list, -// but truncates the list at some reasonable length if necessary. +// joinStrings formats the input as a comma-separated list. func joinStrings(ss []string) string { - const widthLimit = 80 - var n int - for i, s := range ss { - n += len(s) + len(", ") - if n > widthLimit { - ss = append(ss[:i:i], "...") - break - } - } return strings.Join(ss, ", ") }