cmd/godoc: use go/build to determine package and example files

Also:
- faster code for example extraction
- simplify handling of command documentation:
  all "main" packages are treated as commands
- various minor cleanups along the way

For commands written in Go, any doc.go file containing
documentation must now be part of package main (rather
then package documentation), otherwise the documentation
won't show up in godoc (it will still build, though).

For commands written in C, documentation may still be
in doc.go files defining package documentation, but the
recommended way is to explicitly ignore those files with
a +build ignore constraint to define package main.

Fixes #4806.

R=adg, rsc, dave, bradfitz
CC=golang-dev
https://golang.org/cl/7333046
This commit is contained in:
Robert Griesemer 2013-02-19 11:19:58 -08:00
parent 0456729977
commit 3ee87d02b0
36 changed files with 192 additions and 236 deletions

View file

@ -10,7 +10,7 @@
correspond to Go identifiers).
-->
{{with .PDoc}}
{{if $.IsPkg}}
{{if not $.IsMain}}
<div id="short-nav">
<dl>
<dd><code>import "{{html .ImportPath}}"</code></dd>

View file

@ -2,7 +2,7 @@
---------------------------------------
*/}}{{with .PDoc}}{{if $.IsPkg}}PACKAGE
*/}}{{with .PDoc}}{{if not $.IsMain}}PACKAGE
package {{.Name}}
import "{{.ImportPath}}"

View file

@ -55,4 +55,4 @@ If the Google Code credentials are not provided the archival step
will be skipped.
*/
package documentation
package main

View file

@ -20,4 +20,4 @@
// security mechanisms. Do not deploy it in untrusted environments.
// By default, goplay listens only on localhost. This can be overridden with
// the -http parameter. Do so at your own risk.
package documentation
package main

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
5a is a version of the Plan 9 assembler. The original is documented at
@ -11,4 +13,4 @@
Its target architecture is the ARM, referred to by these tools as arm.
*/
package documentation
package main

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
5c is a version of the Plan 9 C compiler. The original is documented at
@ -11,4 +13,4 @@
Its target architecture is the ARM, referred to by these tools as arm.
*/
package documentation
package main

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
5g is the version of the gc compiler for the ARM.
@ -10,4 +12,4 @@ The $GOARCH for these tools is arm.
It reads .go files and outputs .5 files. The flags are documented in ../gc/doc.go.
*/
package documentation
package main

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
5l is the linker for the ARM.
@ -10,4 +12,4 @@ The $GOARCH for these tools is arm.
The flags are documented in ../ld/doc.go.
*/
package documentation
package main

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
6a is a version of the Plan 9 assembler. The original is documented at
@ -11,4 +13,4 @@
Its target architecture is the x86-64, referred to by these tools as amd64.
*/
package documentation
package main

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
6c is a version of the Plan 9 C compiler. The original is documented at
@ -11,4 +13,4 @@
Its target architecture is the x86-64, referred to by these tools as amd64.
*/
package documentation
package main

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
6g is the version of the gc compiler for the x86-64.
@ -10,4 +12,4 @@ The $GOARCH for these tools is amd64.
It reads .go files and outputs .6 files. The flags are documented in ../gc/doc.go.
*/
package documentation
package main

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
6l is the linker for the x86-64.
@ -10,4 +12,4 @@ The $GOARCH for these tools is amd64.
The flags are documented in ../ld/doc.go.
*/
package documentation
package main

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
8a is a version of the Plan 9 assembler. The original is documented at
@ -11,4 +13,4 @@
Its target architecture is the x86, referred to by these tools for historical reasons as 386.
*/
package documentation
package main

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
8c is a version of the Plan 9 C compiler. The original is documented at
@ -11,4 +13,4 @@
Its target architecture is the x86, referred to by these tools for historical reasons as 386.
*/
package documentation
package main

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
8g is the version of the gc compiler for the x86.
@ -10,4 +12,4 @@ The $GOARCH for these tools is 386.
It reads .go files and outputs .8 files. The flags are documented in ../gc/doc.go.
*/
package documentation
package main

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
8l is the linker for the 32-bit x86.
@ -10,4 +12,4 @@ The $GOARCH for these tools is 386.
The flags are documented in ../ld/doc.go.
*/
package documentation
package main

View file

@ -2,10 +2,12 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
This directory contains the portable section of the Plan 9 C compilers.
See ../6c, ../8c, and ../5c for more information.
*/
package documentation
package main

View file

@ -133,4 +133,4 @@ Cgo does not yet work with gccgo.
See "C? Go? Cgo!" for an introduction to using cgo:
http://golang.org/doc/articles/c_go_cgo.html
*/
package documentation
package main

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
Cov is a rudimentary code coverage tool.
@ -31,4 +33,4 @@ The options are:
The program is the same for all architectures: 386, amd64, and arm.
*/
package documentation
package main

View file

@ -33,4 +33,4 @@ Fix does not make backup copies of the files that it edits.
Instead, use a version control system's ``diff'' functionality to inspect
the changes that fix makes before committing them.
*/
package documentation
package main

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
Gc is the generic label for the family of Go compilers
@ -86,4 +88,4 @@ in Go) does not allow any of the pointers passed as arguments to escape into the
heap or into the values returned from the function. This information can be used as
during the compiler's escape analysis of Go code calling the function.
*/
package documentation
package main

View file

@ -812,6 +812,6 @@ See the documentation of the testing package for more information.
*/
package documentation
package main
// NOTE: cmdDoc is in fmt.go.

View file

@ -200,7 +200,7 @@ var documentationTemplate = `// Copyright 2011 The Go Authors. All rights reser
{{end}}*/
package documentation
package main
// NOTE: cmdDoc is in fmt.go.
`

View file

@ -74,7 +74,7 @@ func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth i
// determine number of subdirectories and if there are package files
ndirs := 0
hasPkgFiles := false
var synopses [4]string // prioritized package documentation (0 == highest priority)
var synopses [3]string // prioritized package documentation (0 == highest priority)
for _, d := range list {
switch {
case isPkgDir(d):
@ -95,12 +95,10 @@ func (b *treeBuilder) newDirTree(fset *token.FileSet, path, name string, depth i
switch file.Name.Name {
case name:
i = 0 // normal case: directory name matches package name
case fakePkgName:
i = 1 // synopses for commands
case "main":
i = 2 // directory contains a main package
i = 1 // directory contains a main package
default:
i = 3 // none of the above
i = 2 // none of the above
}
if 0 <= i && i < len(synopses) && synopses[i] == "" {
synopses[i] = doc.Synopsis(file.Doc.Text())

View file

@ -127,4 +127,4 @@ See "Godoc: documenting Go code" for how to write good comments for godoc:
http://golang.org/doc/articles/godoc_documenting_go_code.html
*/
package documentation
package main

View file

@ -86,8 +86,8 @@ var (
func initHandlers() {
fileServer = http.FileServer(&httpFS{fs})
cmdHandler = docServer{"/cmd/", "/src/cmd", false}
pkgHandler = docServer{"/pkg/", "/src/pkg", true}
cmdHandler = docServer{"/cmd/", "/src/cmd"}
pkgHandler = docServer{"/pkg/", "/src/pkg"}
}
func registerPublicHandlers(mux *http.ServeMux) {
@ -794,10 +794,6 @@ func serveSearchDesc(w http.ResponseWriter, r *http.Request) {
// ----------------------------------------------------------------------------
// Packages
// Fake package file and name for commands. Contains the command documentation.
const fakePkgFile = "doc.go"
const fakePkgName = "documentation"
// Fake relative package path for built-ins. Documentation for all globals
// (not just exported ones) will be shown for packages in this directory.
const builtinPkgPath = "builtin"
@ -854,16 +850,20 @@ func remoteSearchURL(query string, html bool) string {
}
type PageInfo struct {
Dirname string // directory containing the package
FSet *token.FileSet // corresponding file set
PAst *ast.File // nil if no single AST with package exports
PDoc *doc.Package // nil if no single package documentation
Dirname string // directory containing the package
Err error // error or nil
// package info
FSet *token.FileSet // nil if no package documentation
PDoc *doc.Package // nil if no package documentation
Examples []*doc.Example // nil if no example code
Dirs *DirList // nil if no directory information
DirTime time.Time // directory time stamp
DirFlat bool // if set, show directory in a flat (non-indented) manner
IsPkg bool // false if this is not documenting a real package
Err error // I/O error or nil
PAst *ast.File // nil if no AST with package exports
IsMain bool // true for package main
// directory info
Dirs *DirList // nil if no directory information
DirTime time.Time // directory time stamp
DirFlat bool // if set, show directory in a flat (non-indented) manner
}
func (info *PageInfo) IsEmpty() bool {
@ -873,7 +873,6 @@ func (info *PageInfo) IsEmpty() bool {
type docServer struct {
pattern string // url pattern; e.g. "/pkg/"
fsRoot string // file system root to which the pattern is mapped
isPkg bool // true if this handler serves real package documentation (as opposed to command documentation)
}
// fsReadDir implements ReadDir for the go/build package.
@ -890,15 +889,6 @@ func fsOpenFile(name string) (r io.ReadCloser, err error) {
return ioutil.NopCloser(bytes.NewReader(data)), nil
}
func inList(name string, list []string) bool {
for _, l := range list {
if name == l {
return true
}
}
return false
}
// packageExports is a local implementation of ast.PackageExports
// which correctly updates each package file's comment list.
// (The ast.PackageExports signature is frozen, hence the local
@ -912,9 +902,9 @@ func packageExports(fset *token.FileSet, pkg *ast.Package) {
}
}
// declNames returns the names declared by decl.
// Method names are returned in the form Receiver_Method.
func declNames(decl ast.Decl) (names []string) {
// addNames adds the names declared by decl to the names set.
// Method names are added in the form ReceiverTypeName_Method.
func addNames(names map[string]bool, decl ast.Decl) {
switch d := decl.(type) {
case *ast.FuncDecl:
name := d.Name.Name
@ -928,64 +918,52 @@ func declNames(decl ast.Decl) (names []string) {
}
name = typeName + "_" + name
}
names = []string{name}
names[name] = true
case *ast.GenDecl:
for _, spec := range d.Specs {
switch s := spec.(type) {
case *ast.TypeSpec:
names = append(names, s.Name.Name)
names[s.Name.Name] = true
case *ast.ValueSpec:
for _, id := range s.Names {
names = append(names, id.Name)
names[id.Name] = true
}
}
}
}
return
}
// globalNames finds all top-level declarations in pkgs and returns a map
// with the identifier names as keys.
func globalNames(pkgs map[string]*ast.Package) map[string]bool {
// globalNames returns a set of the names declared by all package-level
// declarations. Method names are returned in the form Receiver_Method.
func globalNames(pkg *ast.Package) map[string]bool {
names := make(map[string]bool)
for _, pkg := range pkgs {
for _, file := range pkg.Files {
for _, decl := range file.Decls {
for _, name := range declNames(decl) {
names[name] = true
}
}
for _, file := range pkg.Files {
for _, decl := range file.Decls {
addNames(names, decl)
}
}
return names
}
// parseExamples gets examples for packages in pkgs from *_test.go files in dir.
func parseExamples(fset *token.FileSet, pkgs map[string]*ast.Package, dir string) ([]*doc.Example, error) {
// collectExamples collects examples for pkg from testfiles.
func collectExamples(pkg *ast.Package, testfiles map[string]*ast.File) []*doc.Example {
var files []*ast.File
for _, f := range testfiles {
files = append(files, f)
}
var examples []*doc.Example
filter := func(d os.FileInfo) bool {
return isGoFile(d) && strings.HasSuffix(d.Name(), "_test.go")
}
testpkgs, err := parseDir(fset, dir, filter)
if err != nil {
return nil, err
}
globals := globalNames(pkgs)
for _, testpkg := range testpkgs {
var files []*ast.File
for _, f := range testpkg.Files {
files = append(files, f)
}
for _, e := range doc.Examples(files...) {
name := stripExampleSuffix(e.Name)
if name == "" || globals[name] {
examples = append(examples, e)
} else {
log.Printf("skipping example Example%s: refers to unknown function or type", e.Name)
}
globals := globalNames(pkg)
for _, e := range doc.Examples(files...) {
name := stripExampleSuffix(e.Name)
if name == "" || globals[name] {
examples = append(examples, e)
} else {
log.Printf("skipping example Example%s: refers to unknown function or type", e.Name)
}
}
return examples, nil
return examples
}
// getPageInfo returns the PageInfo for a package directory abspath. If the
@ -993,83 +971,56 @@ func parseExamples(fset *token.FileSet, pkgs map[string]*ast.Package, dir string
// computed (PageInfo.PAst), otherwise package documentation (PageInfo.Doc)
// is extracted from the AST. If there is no corresponding package in the
// directory, PageInfo.PAst and PageInfo.PDoc are nil. If there are no sub-
// directories, PageInfo.Dirs is nil. If a directory read error occurred,
// PageInfo.Err is set to the respective error but the error is not logged.
// directories, PageInfo.Dirs is nil. If an error occurred, PageInfo.Err is
// set to the respective error but the error is not logged.
//
func (h *docServer) getPageInfo(abspath, relpath string, mode PageInfoMode) PageInfo {
var pkgFiles []string
func (h *docServer) getPageInfo(abspath, relpath string, mode PageInfoMode) (info PageInfo) {
info.Dirname = abspath
// Restrict to the package files
// that would be used when building the package on this
// system. This makes sure that if there are separate
// implementations for, say, Windows vs Unix, we don't
// Restrict to the package files that would be used when building
// the package on this system. This makes sure that if there are
// separate implementations for, say, Windows vs Unix, we don't
// jumble them all together.
// Note: Uses current binary's GOOS/GOARCH.
// To use different pair, such as if we allowed the user
// to choose, set ctxt.GOOS and ctxt.GOARCH before
// calling ctxt.ScanDir.
// To use different pair, such as if we allowed the user to choose,
// set ctxt.GOOS and ctxt.GOARCH before calling ctxt.ImportDir.
ctxt := build.Default
ctxt.IsAbsPath = pathpkg.IsAbs
ctxt.ReadDir = fsReadDir
ctxt.OpenFile = fsOpenFile
if dir, err := ctxt.ImportDir(abspath, 0); err == nil {
pkgFiles = append(dir.GoFiles, dir.CgoFiles...)
pkginfo, err := ctxt.ImportDir(abspath, 0)
// continue if there are no Go source files; we still want the directory info
if _, nogo := err.(*build.NoGoError); err != nil && !nogo {
info.Err = err
return
}
// filter function to select the desired .go files
filter := func(d os.FileInfo) bool {
// Only Go files.
if !isPkgFile(d) {
return false
}
// If we are looking at cmd documentation, only accept
// the special fakePkgFile containing the documentation.
if !h.isPkg {
return d.Name() == fakePkgFile
}
// Also restrict file list to pkgFiles.
return pkgFiles == nil || inList(d.Name(), pkgFiles)
// collect package files
pkgname := pkginfo.Name
pkgfiles := append(pkginfo.GoFiles, pkginfo.CgoFiles...)
if len(pkgfiles) == 0 {
// Commands written in C have no .go files in the build.
// Instead, documentation may be found in an ignored file.
// The file may be ignored via an explicit +build ignore
// constraint (recommended), or by defining the package
// documentation (historic).
pkgname = "main" // assume package main since pkginfo.Name == ""
pkgfiles = pkginfo.IgnoredGoFiles
}
// get package ASTs
fset := token.NewFileSet()
pkgs, err := parseDir(fset, abspath, filter)
if err != nil {
return PageInfo{Dirname: abspath, Err: err}
}
// select package
var pkg *ast.Package // selected package
if len(pkgs) == 1 {
// Exactly one package - select it.
for _, p := range pkgs {
pkg = p
// get package information, if any
if len(pkgfiles) > 0 {
// build package AST
fset := token.NewFileSet()
files, err := parseFiles(fset, abspath, pkgfiles)
if err != nil {
info.Err = err
return
}
pkg := &ast.Package{Name: pkgname, Files: files}
} else if len(pkgs) > 1 {
// More than one package - report an error.
var buf bytes.Buffer
for _, p := range pkgs {
if buf.Len() > 0 {
fmt.Fprintf(&buf, ", ")
}
fmt.Fprintf(&buf, p.Name)
}
return PageInfo{
Dirname: abspath,
Err: fmt.Errorf("%s contains more than one package: %s", abspath, buf.Bytes()),
}
}
examples, err := parseExamples(fset, pkgs, abspath)
if err != nil {
log.Println("parsing examples:", err)
}
// compute package documentation
var past *ast.File
var pdoc *doc.Package
if pkg != nil {
// extract package documentation
info.FSet = fset
if mode&showSource == 0 {
// show extracted documentation
var m doc.Mode
@ -1079,7 +1030,15 @@ func (h *docServer) getPageInfo(abspath, relpath string, mode PageInfoMode) Page
if mode&allMethods != 0 {
m |= doc.AllMethods
}
pdoc = doc.New(pkg, pathpkg.Clean(relpath), m) // no trailing '/' in importpath
info.PDoc = doc.New(pkg, pathpkg.Clean(relpath), m) // no trailing '/' in importpath
// collect examples
testfiles := append(pkginfo.TestGoFiles, pkginfo.XTestGoFiles...)
files, err = parseFiles(fset, abspath, testfiles)
if err != nil {
log.Println("parsing examples:", err)
}
info.Examples = collectExamples(pkg, files)
} else {
// show source code
// TODO(gri) Consider eliminating export filtering in this mode,
@ -1087,11 +1046,12 @@ func (h *docServer) getPageInfo(abspath, relpath string, mode PageInfoMode) Page
if mode&noFiltering == 0 {
packageExports(fset, pkg)
}
past = ast.MergePackageFiles(pkg, 0)
info.PAst = ast.MergePackageFiles(pkg, 0)
}
info.IsMain = pkgname == "main"
}
// get directory information
// get directory information, if any
var dir *Directory
var timestamp time.Time
if tree, ts := fsTree.get(); tree != nil && tree.(*Directory) != nil {
@ -1109,19 +1069,11 @@ func (h *docServer) getPageInfo(abspath, relpath string, mode PageInfoMode) Page
dir = newDirectory(abspath, 1)
timestamp = time.Now()
}
info.Dirs = dir.listing(true)
info.DirTime = timestamp
info.DirFlat = mode&flatDir != 0
return PageInfo{
Dirname: abspath,
FSet: fset,
PAst: past,
PDoc: pdoc,
Examples: examples,
Dirs: dir.listing(true),
DirTime: timestamp,
DirFlat: mode&flatDir != 0,
IsPkg: h.isPkg,
Err: nil,
}
return
}
func (h *docServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
@ -1151,26 +1103,25 @@ func (h *docServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
switch {
case info.PAst != nil:
tabtitle = info.PAst.Name.Name
title = "Package " + tabtitle
case info.PDoc != nil:
if info.PDoc.Name == fakePkgName {
// assume that the directory name is the command name
_, tabtitle = pathpkg.Split(relpath)
} else {
tabtitle = info.PDoc.Name
}
if info.IsPkg {
title = "Package " + tabtitle
} else {
title = "Command " + tabtitle
}
tabtitle = info.PDoc.Name
default:
tabtitle = info.Dirname
title = "Directory " + tabtitle
title = "Directory "
if *showTimestamps {
subtitle = "Last update: " + info.DirTime.String()
}
}
if title == "" {
if info.IsMain {
// assume that the directory name is the command name
_, tabtitle = pathpkg.Split(relpath)
title = "Command "
} else {
title = "Package "
}
}
title += tabtitle
// special cases for top-level package/command directories
switch tabtitle {

View file

@ -2,10 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This file contains support functions for parsing .go files.
// Similar functionality is found in package go/parser but the
// functions here operate using godoc's file system fs instead
// of calling the OS's file operations directly.
// This file contains support functions for parsing .go files
// accessed via godoc's file system fs.
package main
@ -13,7 +11,6 @@ import (
"go/ast"
"go/parser"
"go/token"
"os"
pathpkg "path"
)
@ -25,44 +22,16 @@ func parseFile(fset *token.FileSet, filename string, mode parser.Mode) (*ast.Fil
return parser.ParseFile(fset, filename, src, mode)
}
func parseFiles(fset *token.FileSet, filenames []string) (pkgs map[string]*ast.Package, first error) {
pkgs = make(map[string]*ast.Package)
for _, filename := range filenames {
file, err := parseFile(fset, filename, parser.ParseComments)
func parseFiles(fset *token.FileSet, abspath string, localnames []string) (map[string]*ast.File, error) {
files := make(map[string]*ast.File)
for _, f := range localnames {
absname := pathpkg.Join(abspath, f)
file, err := parseFile(fset, absname, parser.ParseComments)
if err != nil {
if first == nil {
first = err
}
continue
return nil, err
}
name := file.Name.Name
pkg, found := pkgs[name]
if !found {
// TODO(gri) Use NewPackage here; reconsider ParseFiles API.
pkg = &ast.Package{Name: name, Files: make(map[string]*ast.File)}
pkgs[name] = pkg
}
pkg.Files[filename] = file
files[absname] = file
}
return
}
func parseDir(fset *token.FileSet, path string, filter func(os.FileInfo) bool) (map[string]*ast.Package, error) {
list, err := fs.ReadDir(path)
if err != nil {
return nil, err
}
filenames := make([]string, len(list))
i := 0
for _, d := range list {
if filter == nil || filter(d) {
filenames[i] = pathpkg.Join(path, d.Name())
i++
}
}
filenames = filenames[0:i]
return parseFiles(fset, filenames)
return files, nil
}

View file

@ -72,6 +72,6 @@ To convert the package tree from explicit slice upper bounds to implicit ones:
gofmt -r 'α[β:len(α)] -> α[β:]' -w $GOROOT/src/pkg
*/
package documentation
package main
// BUG(rsc): The implementation of -r is a bit slow.

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
Ld is the portable code for a modified version of the Plan 9 linker. The original is documented at
@ -70,4 +72,4 @@ Options new in this version:
calls, not false positives caused by dead temporaries stored in
the current function call.
*/
package documentation
package main

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
Nm is a version of the Plan 9 nm command. The original is documented at
@ -18,4 +20,4 @@ Usage:
go tool nm [-aghnsTu] file
*/
package documentation
package main

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
Pack is a variant of the Plan 9 ar tool. The original is documented at
@ -24,4 +26,4 @@ The new option 'P' causes pack to remove the given prefix
from file names in the line number information in object files
that are already stored in or added to the archive.
*/
package documentation
package main

View file

@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
/*
Prof is a rudimentary real-time profiler.
@ -44,4 +46,4 @@ every 100ms until the program completes.
It is installed as go tool prof and is architecture-independent.
*/
package documentation
package main

View file

@ -67,4 +67,4 @@ The other flags are:
-printfuncs=Warn:1,Warnf:1
*/
package documentation
package main

View file

@ -48,4 +48,4 @@ referenced by yacc's generated code. Setting it to distinct values
allows multiple grammars to be placed in a single package.
*/
package documentation
package main

View file

@ -19,4 +19,4 @@ The --start flag specifies the name of the start production for
the grammar; it defaults to "Start".
*/
package documentation
package main

View file

@ -58,6 +58,6 @@ To verify the output of a pipe:
echo "package foo" | gotype
*/
package documentation
package main
// BUG(gri): At the moment, only single-file scope analysis is performed.