Commit f736de04 authored by Rob Pike's avatar Rob Pike

cmd/doc: always print package clause except for commands

There was an implicit heuristic before about when to print the
package clause or omit it, but it was undocumented and confusing.
Get rid of it and print it always unless asking for the package
docs for a command, which are more of a usage message than a
programming question. This simplifies the processing.

There are several paths to the output, so to put the fix in one
place we place a wrapper before the output buffer than adds the
clause when Write is first called.

The tests don't verify this behavior, but they didn't before either.
Unsure what the right approach is but this will do for now.

Fixes #31457

Change-Id: Ia6a9e740d556f45265c55f06b5306621c7a40ea9
Reviewed-on: https://go-review.googlesource.com/c/go/+/177797Reviewed-by: default avatarRuss Cox <rsc@golang.org>
parent 15311922
...@@ -31,18 +31,36 @@ const ( ...@@ -31,18 +31,36 @@ const (
) )
type Package struct { type Package struct {
writer io.Writer // Destination for output. writer io.Writer // Destination for output.
name string // Package name, json for encoding/json. name string // Package name, json for encoding/json.
userPath string // String the user used to find this package. userPath string // String the user used to find this package.
pkg *ast.Package // Parsed package. pkg *ast.Package // Parsed package.
file *ast.File // Merged from all files in the package file *ast.File // Merged from all files in the package
doc *doc.Package doc *doc.Package
build *build.Package build *build.Package
typedValue map[*doc.Value]bool // Consts and vars related to types. typedValue map[*doc.Value]bool // Consts and vars related to types.
constructor map[*doc.Func]bool // Constructors. constructor map[*doc.Func]bool // Constructors.
packageClausePrinted bool // Prevent repeated package clauses. fs *token.FileSet // Needed for printing.
fs *token.FileSet // Needed for printing. buf pkgBuffer
buf bytes.Buffer }
// pkgBuffer is a wrapper for bytes.Buffer that prints a package clause the
// first time Write is called.
type pkgBuffer struct {
pkg *Package
printed bool // Prevent repeated package clauses.
bytes.Buffer
}
func (pb *pkgBuffer) Write(p []byte) (int, error) {
if !pb.printed && len(p) > 0 {
pb.printed = true
// Only show package clause for commands if requested explicitly.
if pb.pkg.pkg.Name != "main" || showCmd {
pb.pkg.packageClause()
}
}
return pb.Buffer.Write(p)
} }
type PackageError string // type returned by pkg.Fatalf. type PackageError string // type returned by pkg.Fatalf.
...@@ -171,7 +189,7 @@ func parsePackage(writer io.Writer, pkg *build.Package, userPath string) *Packag ...@@ -171,7 +189,7 @@ func parsePackage(writer io.Writer, pkg *build.Package, userPath string) *Packag
} }
} }
return &Package{ p := &Package{
writer: writer, writer: writer,
name: pkg.Name, name: pkg.Name,
userPath: userPath, userPath: userPath,
...@@ -183,6 +201,8 @@ func parsePackage(writer io.Writer, pkg *build.Package, userPath string) *Packag ...@@ -183,6 +201,8 @@ func parsePackage(writer io.Writer, pkg *build.Package, userPath string) *Packag
build: pkg, build: pkg,
fs: fs, fs: fs,
} }
p.buf.pkg = p
return p
} }
func (pkg *Package) Printf(format string, args ...interface{}) { func (pkg *Package) Printf(format string, args ...interface{}) {
...@@ -426,9 +446,6 @@ func joinStrings(ss []string) string { ...@@ -426,9 +446,6 @@ func joinStrings(ss []string) string {
// allDoc prints all the docs for the package. // allDoc prints all the docs for the package.
func (pkg *Package) allDoc() { func (pkg *Package) allDoc() {
defer pkg.flush() defer pkg.flush()
if pkg.showInternals() {
pkg.packageClause(false)
}
doc.ToText(&pkg.buf, pkg.doc.Doc, "", indent, indentedWidth) doc.ToText(&pkg.buf, pkg.doc.Doc, "", indent, indentedWidth)
pkg.newlines(1) pkg.newlines(1)
...@@ -489,14 +506,11 @@ func (pkg *Package) allDoc() { ...@@ -489,14 +506,11 @@ func (pkg *Package) allDoc() {
// packageDoc prints the docs for the package (package doc plus one-liners of the rest). // packageDoc prints the docs for the package (package doc plus one-liners of the rest).
func (pkg *Package) packageDoc() { func (pkg *Package) packageDoc() {
defer pkg.flush() defer pkg.flush()
if pkg.showInternals() {
pkg.packageClause(false)
}
doc.ToText(&pkg.buf, pkg.doc.Doc, "", indent, indentedWidth) doc.ToText(&pkg.buf, pkg.doc.Doc, "", indent, indentedWidth)
pkg.newlines(1) pkg.newlines(1)
if !pkg.showInternals() { if pkg.pkg.Name == "main" && !showCmd {
// Show only package docs for commands. // Show only package docs for commands.
return return
} }
...@@ -509,29 +523,8 @@ func (pkg *Package) packageDoc() { ...@@ -509,29 +523,8 @@ func (pkg *Package) packageDoc() {
pkg.bugs() pkg.bugs()
} }
// showInternals reports whether we should show the internals
// of a package as opposed to just the package docs.
// Used to decide whether to suppress internals for commands.
// Called only by Package.packageDoc.
func (pkg *Package) showInternals() bool {
return pkg.pkg.Name != "main" || showCmd
}
// packageClause prints the package clause. // packageClause prints the package clause.
// The argument boolean, if true, suppresses the output if the func (pkg *Package) packageClause() {
// user's argument is identical to the actual package path or
// is empty, meaning it's the current directory.
func (pkg *Package) packageClause(checkUserPath bool) {
if pkg.packageClausePrinted {
return
}
if checkUserPath {
if pkg.userPath == "" || pkg.userPath == pkg.build.ImportPath {
return
}
}
importPath := pkg.build.ImportComment importPath := pkg.build.ImportComment
if importPath == "" { if importPath == "" {
importPath = pkg.build.ImportPath importPath = pkg.build.ImportPath
...@@ -563,7 +556,6 @@ func (pkg *Package) packageClause(checkUserPath bool) { ...@@ -563,7 +556,6 @@ func (pkg *Package) packageClause(checkUserPath bool) {
if !usingModules && importPath != pkg.build.ImportPath { if !usingModules && importPath != pkg.build.ImportPath {
pkg.Printf("WARNING: package source is installed in %q\n", pkg.build.ImportPath) pkg.Printf("WARNING: package source is installed in %q\n", pkg.build.ImportPath)
} }
pkg.packageClausePrinted = true
} }
// valueSummary prints a one-line summary for each set of values and constants. // valueSummary prints a one-line summary for each set of values and constants.
...@@ -701,9 +693,6 @@ func (pkg *Package) symbolDoc(symbol string) bool { ...@@ -701,9 +693,6 @@ func (pkg *Package) symbolDoc(symbol string) bool {
found := false found := false
// Functions. // Functions.
for _, fun := range pkg.findFuncs(symbol) { for _, fun := range pkg.findFuncs(symbol) {
if !found {
pkg.packageClause(true)
}
// Symbol is a function. // Symbol is a function.
decl := fun.Decl decl := fun.Decl
pkg.emit(fun.Doc, decl) pkg.emit(fun.Doc, decl)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment