Permalink
Browse files

internal/code: Compute full package documentation automatically.

This replaces the temporary solution of manually hardcoding
the full package documentation for various import paths.
That doesn't scale as the number of packages grows.
  • Loading branch information...
dmitshur committed Jul 11, 2018
1 parent 0c473b6 commit 05b5de335638250d907d9bf2decb5dfc219dd76e
Showing with 41 additions and 22 deletions.
  1. +29 −17 internal/code/code.go
  2. +12 −5 internal/code/code_test.go
View
@@ -3,8 +3,12 @@ package code
import (
"bytes"
"fmt"
"go/ast"
"go/build"
"go/doc"
"go/parser"
"go/token"
"io"
"log"
"os"
@@ -13,6 +17,7 @@ import (
"strings"
"github.com/shurcooL/go/vfs/godocfs/vfsutil"
"golang.org/x/tools/go/buildutil"
"golang.org/x/tools/godoc/vfs"
"sourcegraph.com/sourcegraph/go-vcs/vcs"
"sourcegraph.com/sourcegraph/go-vcs/vcs/git"
@@ -211,7 +216,7 @@ func loadPackage(fs vfs.FileSystem, dir, importPath string) (*Package, error) {
{"linux", "amd64"},
{"darwin", "amd64"},
} {
bctx := build.Context{
bctx := &build.Context{
GOOS: env.GOOS,
GOARCH: env.GOARCH,
CgoEnabled: true,
@@ -240,26 +245,14 @@ func loadPackage(fs vfs.FileSystem, dir, importPath string) (*Package, error) {
} else if err != nil {
return nil, err
}
// TODO: Automate this.
doc := p.Doc
switch importPath {
case "dmitri.shuralyov.com/text/kebabcase", "dmitri.shuralyov.com/kebabcase":
doc += "\n\nReference: https://en.wikipedia.org/wiki/Naming_convention_(programming)#Multiple-word_identifiers."
case "dmitri.shuralyov.com/scratch/image/jpeg":
doc += "\n\nJPEG is defined in ITU-T T.81: http://www.w3.org/Graphics/JPEG/itu-t81.pdf."
case "dmitri.shuralyov.com/scratch/image/png":
doc += "\n\nThe PNG specification is at http://www.w3.org/TR/PNG/."
case "dmitri.shuralyov.com/font/woff2":
doc += "\n\nThe WOFF2 font packaging format is specified at https://www.w3.org/TR/WOFF2/."
case "dmitri.shuralyov.com/gpu/mtl":
doc += "\n\nThis package is in very early stages of development. The API will change when opportunities for improvement are discovered; it is not yet frozen. Less than 20% of the Metal API surface is implemented. Current functionality is sufficient to render very basic geometry."
case "dmitri.shuralyov.com/gpu/mtl/example/hellotriangle":
doc += " It writes the frame to a triangle.png file in current working directory."
dpkg, err := computeDoc(bctx, p)
if err != nil {
return nil, fmt.Errorf("can't get godoc of package %q: %v", importPath, err)
}
return &Package{
Name: p.Name,
Synopsis: p.Doc,
DocHTML: docHTML(doc),
DocHTML: docHTML(dpkg.Doc),
}, nil
}
// This directory doesn't contain a package.
@@ -293,6 +286,25 @@ func hasSubdir(root, dir string) (rel string, ok bool) {
return dir[len(root):], true
}
// computeDoc computes the package documentation for the given package,
// using the specified build context.
func computeDoc(bctx *build.Context, p *build.Package) (*doc.Package, error) {
fset := token.NewFileSet()
files := make(map[string]*ast.File)
for _, file := range append(p.GoFiles, p.CgoFiles...) {
f, err := buildutil.ParseFile(fset, bctx, nil, p.Dir, file, parser.ParseComments)
if err != nil {
return nil, err
}
files[file] = f
}
apkg := &ast.Package{
Name: p.Name,
Files: files,
}
return doc.New(apkg, p.ImportPath, 0), nil
}
// docHTML returns documentation comment text converted to formatted HTML.
func docHTML(text string) string {
var buf bytes.Buffer
View
@@ -23,10 +23,12 @@ func TestDiscover(t *testing.T) {
Name: "kebabcase",
Synopsis: "Package kebabcase provides a parser for identifier names using kebab-case naming convention.",
DocHTML: `<p>
Package kebabcase provides a parser for identifier names using kebab-case naming convention.
Package kebabcase provides a parser for identifier names
using kebab-case naming convention.
</p>
<p>
Reference: <a href="https://en.wikipedia.org/wiki/Naming_convention_(programming)#Multiple-word_identifiers">https://en.wikipedia.org/wiki/Naming_convention_(programming)#Multiple-word_identifiers</a>.</p>
Reference: <a href="https://en.wikipedia.org/wiki/Naming_convention_(programming)#Multiple-word_identifiers">https://en.wikipedia.org/wiki/Naming_convention_(programming)#Multiple-word_identifiers</a>.
</p>
`,
},
},
@@ -38,7 +40,10 @@ Reference: <a href="https://en.wikipedia.org/wiki/Naming_convention_(programming
Package: &code.Package{
Name: "scratch",
Synopsis: "Package scratch is used for testing.",
DocHTML: "<p>\nPackage scratch is used for testing.</p>\n",
DocHTML: `<p>
Package scratch is used for testing.
</p>
`,
},
},
{
@@ -68,7 +73,8 @@ Reference: <a href="https://en.wikipedia.org/wiki/Naming_convention_(programming
Package jpeg implements a tiny subset of a JPEG image decoder and encoder.
</p>
<p>
JPEG is defined in ITU-T T.81: <a href="http://www.w3.org/Graphics/JPEG/itu-t81.pdf">http://www.w3.org/Graphics/JPEG/itu-t81.pdf</a>.</p>
JPEG is defined in ITU-T T.81: <a href="http://www.w3.org/Graphics/JPEG/itu-t81.pdf">http://www.w3.org/Graphics/JPEG/itu-t81.pdf</a>.
</p>
`,
},
},
@@ -84,7 +90,8 @@ JPEG is defined in ITU-T T.81: <a href="http://www.w3.org/Graphics/JPEG/itu-t81.
Package png implements a tiny subset of a PNG image decoder and encoder.
</p>
<p>
The PNG specification is at <a href="http://www.w3.org/TR/PNG/">http://www.w3.org/TR/PNG/</a>.</p>
The PNG specification is at <a href="http://www.w3.org/TR/PNG/">http://www.w3.org/TR/PNG/</a>.
</p>
`,
},
},

0 comments on commit 05b5de3

Please sign in to comment.