Skip to content

Commit

Permalink
feat(internal/godocfx): add status to packages and TOCs (#4547)
Browse files Browse the repository at this point in the history
  • Loading branch information
tbpg committed Aug 3, 2021
1 parent 653b82b commit c6de69c
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 19 deletions.
34 changes: 17 additions & 17 deletions internal/godocfx/parse.go
Expand Up @@ -49,10 +49,11 @@ type tableOfContents []*tocItem

// tocItem is an item in a TOC.
type tocItem struct {
UID string `yaml:"uid,omitempty"`
Name string `yaml:"name,omitempty"`
Items []*tocItem `yaml:"items,omitempty"`
Href string `yaml:"href,omitempty"`
UID string `yaml:"uid,omitempty"`
Name string `yaml:"name,omitempty"`
Items []*tocItem `yaml:"items,omitempty"`
Href string `yaml:"href,omitempty"`
Status string `yaml:"status,omitempty"`
}

func (t *tocItem) addItem(i *tocItem) {
Expand Down Expand Up @@ -169,6 +170,7 @@ func parse(glob string, workingDir string, optionalExtraFiles []string, filter [
Type: "package",
Examples: processExamples(pi.Doc.Examples, pi.Fset),
AltLink: "https://pkg.go.dev/" + pi.Doc.ImportPath,
Status: pi.Status,
}
pkgPage := &page{Items: []*item{pkgItem}}
pages[pi.Doc.ImportPath] = pkgPage
Expand Down Expand Up @@ -545,12 +547,6 @@ func buildTOC(mod string, pis []pkgload.Info, extraFiles []extraFile) tableOfCon
Name: mod,
}

// Assume the module root has a package.
modTOC.addItem(&tocItem{
UID: mod,
Name: mod,
})

for _, ef := range extraFiles {
modTOC.addItem(&tocItem{
Href: ef.dstRelativePath,
Expand All @@ -560,31 +556,35 @@ func buildTOC(mod string, pis []pkgload.Info, extraFiles []extraFile) tableOfCon

toc = append(toc, modTOC)

if len(pis) == 1 {
// The module only has one package.
return toc
}

trimmedPkgs := []string{}
statuses := map[string]string{}
for _, pi := range pis {
importPath := pi.Doc.ImportPath
if importPath == mod {
// Add the module root package immediately with the full name.
modTOC.addItem(&tocItem{
UID: mod,
Name: mod,
Status: pi.Status,
})
continue
}
if !strings.HasPrefix(importPath, mod) {
panic(fmt.Sprintf("Package %q does not start with %q, should never happen", importPath, mod))
}
trimmed := strings.TrimPrefix(importPath, mod+"/")
trimmedPkgs = append(trimmedPkgs, trimmed)
statuses[trimmed] = pi.Status
}

sort.Strings(trimmedPkgs)

for _, trimmed := range trimmedPkgs {
uid := mod + "/" + trimmed
pkgTOCItem := &tocItem{
UID: uid,
Name: trimmed,
UID: uid,
Name: trimmed,
Status: statuses[trimmed],
}
modTOC.addItem(pkgTOCItem)
}
Expand Down
25 changes: 25 additions & 0 deletions internal/godocfx/pkgload/load.go
Expand Up @@ -34,6 +34,7 @@ type Info struct {
Fset *token.FileSet
// ImportRenames is a map from package path to local name or "".
ImportRenames map[string]string
Status string
}

// Load parses the given glob and returns info for the matching packages.
Expand Down Expand Up @@ -157,12 +158,36 @@ func Load(glob, workingDir string, filter []string) ([]Info, error) {
Doc: docPkg,
Fset: fset,
ImportRenames: imports,
Status: pkgStatus(pkgPath, docPkg.Doc),
})
}

return result, nil
}

// pkgStatus returns the status of the given package with the
// given GoDoc.
//
// pkgStatus does not use repo-metadata-full.json because it's
// not available for all modules nor all versions.
func pkgStatus(importPath, doc string) string {
switch {
case strings.Contains(doc, "\nDeprecated:"):
return "deprecated"
case strings.Contains(doc, "This package is in alpha"):
return "alpha"
case strings.Contains(doc, "This package is in beta"):
return "beta"

case strings.Contains(importPath, "alpha"):
return "alpha"
case strings.Contains(importPath, "beta"):
return "beta"
}

return ""
}

func hasPrefix(s string, prefixes []string) bool {
for _, prefix := range prefixes {
if strings.HasPrefix(s, prefix) {
Expand Down
65 changes: 65 additions & 0 deletions internal/godocfx/pkgload/load_test.go
@@ -0,0 +1,65 @@
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package pkgload

import "testing"

func TestPkgStatus(t *testing.T) {
tests := []struct {
importPath string
doc string
want string
}{
{
importPath: "cloud.google.com/go",
want: "",
},
{
importPath: "cloud.google.com/go/storage/v1alpha1",
want: "alpha",
},
{
importPath: "cloud.google.com/go/storage/v2beta2",
want: "beta",
},
{
doc: "NOTE: This package is in beta. It is not stable, and may be subject to changes.",
want: "beta",
},
{
doc: "NOTE: This package is in alpha. It is not stable, and is likely to change.",
want: "alpha",
},
{
doc: "Package foo is great\nDeprecated: not anymore",
want: "deprecated",
},
{
importPath: "cloud.google.com/go/storage/v1alpha1",
doc: "Package foo is great\nDeprecated: not anymore",
want: "deprecated", // Deprecated comes before alpha and beta.
},
{
importPath: "cloud.google.com/go/storage/v1beta1",
doc: "Package foo is great\nDeprecated: not anymore",
want: "deprecated", // Deprecated comes before alpha and beta.
},
}
for _, test := range tests {
if got := pkgStatus(test.importPath, test.doc); got != test.want {
t.Errorf("pkgStatus(%q, %q) got %q, want %q", test.importPath, test.doc, got, test.want)
}
}
}
4 changes: 2 additions & 2 deletions internal/godocfx/testdata/golden/toc.yml
Expand Up @@ -2,7 +2,7 @@
- uid: cloud.google.com/go/storage
name: cloud.google.com/go/storage
items:
- uid: cloud.google.com/go/storage
name: cloud.google.com/go/storage
- name: README
href: pkg-readme.md
- uid: cloud.google.com/go/storage
name: cloud.google.com/go/storage

0 comments on commit c6de69c

Please sign in to comment.