diff --git a/src/cmd/doc/pkg.go b/src/cmd/doc/pkg.go index abc8e0b385..2c0c6c161a 100644 --- a/src/cmd/doc/pkg.go +++ b/src/cmd/doc/pkg.go @@ -31,18 +31,36 @@ const ( ) type Package struct { - writer io.Writer // Destination for output. - name string // Package name, json for encoding/json. - userPath string // String the user used to find this package. - pkg *ast.Package // Parsed package. - file *ast.File // Merged from all files in the package - doc *doc.Package - build *build.Package - typedValue map[*doc.Value]bool // Consts and vars related to types. - constructor map[*doc.Func]bool // Constructors. - packageClausePrinted bool // Prevent repeated package clauses. - fs *token.FileSet // Needed for printing. - buf bytes.Buffer + writer io.Writer // Destination for output. + name string // Package name, json for encoding/json. + userPath string // String the user used to find this package. + pkg *ast.Package // Parsed package. + file *ast.File // Merged from all files in the package + doc *doc.Package + build *build.Package + typedValue map[*doc.Value]bool // Consts and vars related to types. + constructor map[*doc.Func]bool // Constructors. + fs *token.FileSet // Needed for printing. + buf pkgBuffer +} + +// 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. @@ -171,7 +189,7 @@ func parsePackage(writer io.Writer, pkg *build.Package, userPath string) *Packag } } - return &Package{ + p := &Package{ writer: writer, name: pkg.Name, userPath: userPath, @@ -183,6 +201,8 @@ func parsePackage(writer io.Writer, pkg *build.Package, userPath string) *Packag build: pkg, fs: fs, } + p.buf.pkg = p + return p } func (pkg *Package) Printf(format string, args ...interface{}) { @@ -426,9 +446,6 @@ func joinStrings(ss []string) string { // allDoc prints all the docs for the package. func (pkg *Package) allDoc() { defer pkg.flush() - if pkg.showInternals() { - pkg.packageClause(false) - } doc.ToText(&pkg.buf, pkg.doc.Doc, "", indent, indentedWidth) pkg.newlines(1) @@ -489,14 +506,11 @@ func (pkg *Package) allDoc() { // packageDoc prints the docs for the package (package doc plus one-liners of the rest). func (pkg *Package) packageDoc() { defer pkg.flush() - if pkg.showInternals() { - pkg.packageClause(false) - } doc.ToText(&pkg.buf, pkg.doc.Doc, "", indent, indentedWidth) pkg.newlines(1) - if !pkg.showInternals() { + if pkg.pkg.Name == "main" && !showCmd { // Show only package docs for commands. return } @@ -509,29 +523,8 @@ func (pkg *Package) packageDoc() { 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. -// The argument boolean, if true, suppresses the output if the -// 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 - } - } - +func (pkg *Package) packageClause() { importPath := pkg.build.ImportComment if importPath == "" { importPath = pkg.build.ImportPath @@ -563,7 +556,6 @@ func (pkg *Package) packageClause(checkUserPath bool) { if !usingModules && importPath != 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. @@ -701,9 +693,6 @@ func (pkg *Package) symbolDoc(symbol string) bool { found := false // Functions. for _, fun := range pkg.findFuncs(symbol) { - if !found { - pkg.packageClause(true) - } // Symbol is a function. decl := fun.Decl pkg.emit(fun.Doc, decl)