summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Pike <r@golang.org>2018-10-10 11:50:49 +1100
committerRob Pike <r@golang.org>2018-10-10 23:40:35 +0000
commit294d16c9c58187492baf1fd8bac034b5fecbf0ba (patch)
tree02bf9378eb65669f7a6c68f4984c37084f07521f
parentd5e722034ab19d47377507f3606c1a72f484d7eb (diff)
downloadgo-git-294d16c9c58187492baf1fd8bac034b5fecbf0ba.tar.gz
cmd/doc: add a -src flag to show original source
It's long-desired but was blocked by #26835. That is now fixed, so it's easy. When -src is off, we behave as before. But with -src set, initialize the go/doc package to preserve the original AST and things flow very easily. With -src, since you're seeing inside the package source anyway it shows unexported fields and constants: you see the original source. But you still need -u to ask about them. Fixes #18807 Change-Id: I473e90323b4eff0735360274dc0d2d9dba16ff8b Reviewed-on: https://go-review.googlesource.com/c/140959 Reviewed-by: Andrew Gerrand <adg@golang.org> Run-TryBot: Andrew Gerrand <adg@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
-rw-r--r--src/cmd/doc/doc_test.go149
-rw-r--r--src/cmd/doc/main.go5
-rw-r--r--src/cmd/doc/pkg.go21
-rw-r--r--src/cmd/doc/testdata/pkg.go8
-rw-r--r--src/cmd/go/alldocs.go7
-rw-r--r--src/cmd/go/internal/doc/doc.go7
6 files changed, 141 insertions, 56 deletions
diff --git a/src/cmd/doc/doc_test.go b/src/cmd/doc/doc_test.go
index 6010f04b56..64b1fb596b 100644
--- a/src/cmd/doc/doc_test.go
+++ b/src/cmd/doc/doc_test.go
@@ -127,24 +127,24 @@ var tests = []test{
`type T1 = T2`, // Type alias
},
[]string{
- `const internalConstant = 2`, // No internal constants.
- `var internalVariable = 2`, // No internal variables.
- `func internalFunc(a int) bool`, // No internal functions.
- `Comment about exported constant`, // No comment for single constant.
- `Comment about exported variable`, // No comment for single variable.
- `Comment about block of constants.`, // No comment for constant block.
- `Comment about block of variables.`, // No comment for variable block.
- `Comment before ConstOne`, // No comment for first entry in constant block.
- `Comment before VarOne`, // No comment for first entry in variable block.
- `ConstTwo = 2`, // No second entry in constant block.
- `VarTwo = 2`, // No second entry in variable block.
- `VarFive = 5`, // From block starting with unexported variable.
- `type unexportedType`, // No unexported type.
- `unexportedTypedConstant`, // No unexported typed constant.
- `\bField`, // No fields.
- `Method`, // No methods.
- `someArgument[5-8]`, // No truncated arguments.
- `type T1 T2`, // Type alias does not display as type declaration.
+ `const internalConstant = 2`, // No internal constants.
+ `var internalVariable = 2`, // No internal variables.
+ `func internalFunc(a int) bool`, // No internal functions.
+ `Comment about exported constant`, // No comment for single constant.
+ `Comment about exported variable`, // No comment for single variable.
+ `Comment about block of constants`, // No comment for constant block.
+ `Comment about block of variables`, // No comment for variable block.
+ `Comment before ConstOne`, // No comment for first entry in constant block.
+ `Comment before VarOne`, // No comment for first entry in variable block.
+ `ConstTwo = 2`, // No second entry in constant block.
+ `VarTwo = 2`, // No second entry in variable block.
+ `VarFive = 5`, // From block starting with unexported variable.
+ `type unexportedType`, // No unexported type.
+ `unexportedTypedConstant`, // No unexported typed constant.
+ `\bField`, // No fields.
+ `Method`, // No methods.
+ `someArgument[5-8]`, // No truncated arguments.
+ `type T1 T2`, // Type alias does not display as type declaration.
},
},
// Package dump -u
@@ -207,6 +207,18 @@ var tests = []test{
},
nil,
},
+ // Block of constants -src.
+ {
+ "block of constants with -src",
+ []string{"-src", p, `ConstTwo`},
+ []string{
+ `Comment about block of constants`, // Top comment.
+ `ConstOne.*=.*1`, // Each constant seen.
+ `ConstTwo.*=.*2.*Comment on line with ConstTwo`,
+ `constThree`, // Even unexported constants.
+ },
+ nil,
+ },
// Block of constants with carryover type from unexported field.
{
"block of constants with carryover type",
@@ -295,6 +307,17 @@ var tests = []test{
},
nil,
},
+ // Function with -src.
+ {
+ "function with -src",
+ []string{"-src", p, `ExportedFunc`},
+ []string{
+ `Comment about exported function`, // Include comment.
+ `func ExportedFunc\(a int\) bool`,
+ `return true != false`, // Include body.
+ },
+ nil,
+ },
// Type.
{
@@ -304,21 +327,44 @@ var tests = []test{
`Comment about exported type`, // Include comment.
`type ExportedType struct`, // Type definition.
`Comment before exported field.*\n.*ExportedField +int` +
- `.*Comment on line with exported field.`,
- `ExportedEmbeddedType.*Comment on line with exported embedded field.`,
+ `.*Comment on line with exported field`,
+ `ExportedEmbeddedType.*Comment on line with exported embedded field`,
`Has unexported fields`,
`func \(ExportedType\) ExportedMethod\(a int\) bool`,
`const ExportedTypedConstant ExportedType = iota`, // Must include associated constant.
`func ExportedTypeConstructor\(\) \*ExportedType`, // Must include constructor.
- `io.Reader.*Comment on line with embedded Reader.`,
+ `io.Reader.*Comment on line with embedded Reader`,
},
[]string{
- `unexportedField`, // No unexported field.
- `int.*embedded`, // No unexported embedded field.
- `Comment about exported method.`, // No comment about exported method.
- `unexportedMethod`, // No unexported method.
- `unexportedTypedConstant`, // No unexported constant.
- `error`, // No embedded error.
+ `unexportedField`, // No unexported field.
+ `int.*embedded`, // No unexported embedded field.
+ `Comment about exported method`, // No comment about exported method.
+ `unexportedMethod`, // No unexported method.
+ `unexportedTypedConstant`, // No unexported constant.
+ `error`, // No embedded error.
+ },
+ },
+ // Type with -src. Will see unexported fields.
+ {
+ "type",
+ []string{"-src", p, `ExportedType`},
+ []string{
+ `Comment about exported type`, // Include comment.
+ `type ExportedType struct`, // Type definition.
+ `Comment before exported field.*\n.*ExportedField +int` +
+ `.*Comment on line with exported field`,
+ `ExportedEmbeddedType.*Comment on line with exported embedded field`,
+ `unexportedType.*Comment on line with unexported embedded field`,
+ `func \(ExportedType\) ExportedMethod\(a int\) bool`,
+ `const ExportedTypedConstant ExportedType = iota`, // Must include associated constant.
+ `func ExportedTypeConstructor\(\) \*ExportedType`, // Must include constructor.
+ `io.Reader.*Comment on line with embedded Reader`,
+ },
+ []string{
+ `int.*embedded`, // No unexported embedded field.
+ `Comment about exported method`, // No comment about exported method.
+ `unexportedMethod`, // No unexported method.
+ `unexportedTypedConstant`, // No unexported constant.
},
},
// Type T1 dump (alias).
@@ -341,14 +387,14 @@ var tests = []test{
`Comment about exported type`, // Include comment.
`type ExportedType struct`, // Type definition.
`Comment before exported field.*\n.*ExportedField +int`,
- `unexportedField.*int.*Comment on line with unexported field.`,
- `ExportedEmbeddedType.*Comment on line with exported embedded field.`,
- `\*ExportedEmbeddedType.*Comment on line with exported embedded \*field.`,
- `\*qualified.ExportedEmbeddedType.*Comment on line with exported embedded \*selector.field.`,
- `unexportedType.*Comment on line with unexported embedded field.`,
- `\*unexportedType.*Comment on line with unexported embedded \*field.`,
- `io.Reader.*Comment on line with embedded Reader.`,
- `error.*Comment on line with embedded error.`,
+ `unexportedField.*int.*Comment on line with unexported field`,
+ `ExportedEmbeddedType.*Comment on line with exported embedded field`,
+ `\*ExportedEmbeddedType.*Comment on line with exported embedded \*field`,
+ `\*qualified.ExportedEmbeddedType.*Comment on line with exported embedded \*selector.field`,
+ `unexportedType.*Comment on line with unexported embedded field`,
+ `\*unexportedType.*Comment on line with unexported embedded \*field`,
+ `io.Reader.*Comment on line with embedded Reader`,
+ `error.*Comment on line with embedded error`,
`func \(ExportedType\) unexportedMethod\(a int\) bool`,
`unexportedTypedConstant`,
},
@@ -380,8 +426,8 @@ var tests = []test{
`type ExportedInterface interface`, // Interface definition.
`Comment before exported method.*\n.*ExportedMethod\(\)` +
`.*Comment on line with exported method`,
- `io.Reader.*Comment on line with embedded Reader.`,
- `error.*Comment on line with embedded error.`,
+ `io.Reader.*Comment on line with embedded Reader`,
+ `error.*Comment on line with embedded error`,
`Has unexported methods`,
},
[]string{
@@ -400,9 +446,9 @@ var tests = []test{
`type ExportedInterface interface`, // Interface definition.
`Comment before exported method.*\n.*ExportedMethod\(\)` +
`.*Comment on line with exported method`,
- `unexportedMethod\(\).*Comment on line with unexported method.`,
- `io.Reader.*Comment on line with embedded Reader.`,
- `error.*Comment on line with embedded error.`,
+ `unexportedMethod\(\).*Comment on line with unexported method`,
+ `io.Reader.*Comment on line with embedded Reader`,
+ `error.*Comment on line with embedded error`,
},
[]string{
`Has unexported methods`,
@@ -418,7 +464,7 @@ var tests = []test{
`.*Comment on line with exported method`,
},
[]string{
- `Comment about exported interface.`,
+ `Comment about exported interface`,
},
},
@@ -428,7 +474,7 @@ var tests = []test{
[]string{p, `ExportedType.ExportedMethod`},
[]string{
`func \(ExportedType\) ExportedMethod\(a int\) bool`,
- `Comment about exported method.`,
+ `Comment about exported method`,
},
nil,
},
@@ -438,7 +484,18 @@ var tests = []test{
[]string{"-u", p, `ExportedType.unexportedMethod`},
[]string{
`func \(ExportedType\) unexportedMethod\(a int\) bool`,
- `Comment about unexported method.`,
+ `Comment about unexported method`,
+ },
+ nil,
+ },
+ // Method with -src.
+ {
+ "method with -src",
+ []string{"-src", p, `ExportedType.ExportedMethod`},
+ []string{
+ `func \(ExportedType\) ExportedMethod\(a int\) bool`,
+ `Comment about exported method`,
+ `return true != true`,
},
nil,
},
@@ -450,8 +507,8 @@ var tests = []test{
[]string{
`type ExportedType struct`,
`ExportedField int`,
- `Comment before exported field.`,
- `Comment on line with exported field.`,
+ `Comment before exported field`,
+ `Comment on line with exported field`,
`other fields elided`,
},
nil,
@@ -463,7 +520,7 @@ var tests = []test{
[]string{"-u", p, `ExportedType.unexportedField`},
[]string{
`unexportedField int`,
- `Comment on line with unexported field.`,
+ `Comment on line with unexported field`,
},
nil,
},
diff --git a/src/cmd/doc/main.go b/src/cmd/doc/main.go
index 982c8e054a..a3e09d3f87 100644
--- a/src/cmd/doc/main.go
+++ b/src/cmd/doc/main.go
@@ -28,6 +28,9 @@
// For commands, unless the -cmd flag is present "go doc command"
// shows only the package-level docs for the package.
//
+// The -src flag causes doc to print the full source code for the symbol, such
+// as the body of a struct, function or method.
+//
// For complete documentation, run "go help doc".
package main
@@ -50,6 +53,7 @@ var (
unexported bool // -u flag
matchCase bool // -c flag
showCmd bool // -cmd flag
+ showSrc bool // -src flag
)
// usage is a replacement usage function for the flags package.
@@ -85,6 +89,7 @@ func do(writer io.Writer, flagSet *flag.FlagSet, args []string) (err error) {
flagSet.BoolVar(&unexported, "u", false, "show unexported symbols as well as exported")
flagSet.BoolVar(&matchCase, "c", false, "symbol matching honors case (paths not affected)")
flagSet.BoolVar(&showCmd, "cmd", false, "show symbols with package docs even if package is a command")
+ flagSet.BoolVar(&showSrc, "src", false, "show source code for symbol")
flagSet.Parse(args)
var paths []string
var symbol, method string
diff --git a/src/cmd/doc/pkg.go b/src/cmd/doc/pkg.go
index 14e41b9106..154fb7b45f 100644
--- a/src/cmd/doc/pkg.go
+++ b/src/cmd/doc/pkg.go
@@ -137,7 +137,11 @@ func parsePackage(writer io.Writer, pkg *build.Package, userPath string) *Packag
// from finding the symbol. Work around this for now, but we
// should fix it in go/doc.
// A similar story applies to factory functions.
- docPkg := doc.New(astPkg, pkg.ImportPath, doc.AllDecls)
+ mode := doc.AllDecls
+ if showSrc {
+ mode |= doc.PreserveAST // See comment for Package.emit.
+ }
+ docPkg := doc.New(astPkg, pkg.ImportPath, mode)
for _, typ := range docPkg.Types {
docPkg.Consts = append(docPkg.Consts, typ.Consts...)
docPkg.Vars = append(docPkg.Vars, typ.Vars...)
@@ -177,14 +181,16 @@ func (pkg *Package) newlines(n int) {
}
}
-// emit prints the node.
+// emit prints the node. If showSrc is true, it ignores the provided comment,
+// assuming the comment is in the node itself. Otherwise, the go/doc package
+// clears the stuff we don't want to print anyway. It's a bit of a magic trick.
func (pkg *Package) emit(comment string, node ast.Node) {
if node != nil {
err := format.Node(&pkg.buf, pkg.fs, node)
if err != nil {
log.Fatal(err)
}
- if comment != "" {
+ if comment != "" && !showSrc {
pkg.newlines(1)
doc.ToText(&pkg.buf, comment, " ", indent, indentedWidth)
pkg.newlines(2) // Blank line after comment to separate from next item.
@@ -611,7 +617,6 @@ func (pkg *Package) symbolDoc(symbol string) bool {
}
// Symbol is a function.
decl := fun.Decl
- decl.Body = nil
pkg.emit(fun.Doc, decl)
found = true
}
@@ -641,7 +646,7 @@ func (pkg *Package) symbolDoc(symbol string) bool {
}
for _, ident := range vspec.Names {
- if isExported(ident.Name) {
+ if showSrc || isExported(ident.Name) {
if vspec.Type == nil && vspec.Values == nil && typ != nil {
// This a standalone identifier, as in the case of iota usage.
// Thus, assume the type comes from the previous type.
@@ -701,9 +706,10 @@ func (pkg *Package) symbolDoc(symbol string) bool {
}
// trimUnexportedElems modifies spec in place to elide unexported fields from
-// structs and methods from interfaces (unless the unexported flag is set).
+// structs and methods from interfaces (unless the unexported flag is set or we
+// are asked to show the original source).
func trimUnexportedElems(spec *ast.TypeSpec) {
- if unexported {
+ if unexported || showSrc {
return
}
switch typ := spec.Type.(type) {
@@ -808,7 +814,6 @@ func (pkg *Package) printMethodDoc(symbol, method string) bool {
for _, meth := range typ.Methods {
if match(method, meth.Name) {
decl := meth.Decl
- decl.Body = nil
pkg.emit(meth.Doc, decl)
found = true
}
diff --git a/src/cmd/doc/testdata/pkg.go b/src/cmd/doc/testdata/pkg.go
index bc069939f8..50105b5fcc 100644
--- a/src/cmd/doc/testdata/pkg.go
+++ b/src/cmd/doc/testdata/pkg.go
@@ -5,6 +5,8 @@
// Package comment.
package pkg
+import "io"
+
// Constants
// Comment about exported constant.
@@ -52,7 +54,9 @@ var (
)
// Comment about exported function.
-func ExportedFunc(a int) bool
+func ExportedFunc(a int) bool {
+ return true != false
+}
// Comment about internal function.
func internalFunc(a int) bool
@@ -73,7 +77,7 @@ type ExportedType struct {
// Comment about exported method.
func (ExportedType) ExportedMethod(a int) bool {
- return true
+ return true != true
}
// Comment about unexported method.
diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go
index 9528ca2984..f54f000b07 100644
--- a/src/cmd/go/alldocs.go
+++ b/src/cmd/go/alldocs.go
@@ -348,6 +348,13 @@
// Treat a command (package main) like a regular package.
// Otherwise package main's exported symbols are hidden
// when showing the package's top-level documentation.
+// -src
+// Show the full source code for the symbol. This will
+// display the full Go source of its declaration and
+// definition, such as a function definition (including
+// the body), type declaration or enclosing const
+// block. The output may therefore include unexported
+// details.
// -u
// Show documentation for unexported as well as exported
// symbols, methods, and fields.
diff --git a/src/cmd/go/internal/doc/doc.go b/src/cmd/go/internal/doc/doc.go
index 4e7dca082d..262bbb3ecb 100644
--- a/src/cmd/go/internal/doc/doc.go
+++ b/src/cmd/go/internal/doc/doc.go
@@ -112,6 +112,13 @@ Flags:
Treat a command (package main) like a regular package.
Otherwise package main's exported symbols are hidden
when showing the package's top-level documentation.
+ -src
+ Show the full source code for the symbol. This will
+ display the full Go source of its declaration and
+ definition, such as a function definition (including
+ the body), type declaration or enclosing const
+ block. The output may therefore include unexported
+ details.
-u
Show documentation for unexported as well as exported
symbols, methods, and fields.