1
0
mirror of https://github.com/golang/go synced 2024-11-05 15:06:09 -07:00

godoc: Fix commandline mode output.

Fix output of packages with multiple files.
Remove extra output when filter is requested.
Fixes golang/go#7115.

R=bradfitz, adg
CC=golang-codereviews
https://golang.org/cl/52750044
This commit is contained in:
Brad Garcia 2014-01-30 06:28:19 -05:00
parent bf4d636dc9
commit 2ca2bfc172
7 changed files with 91 additions and 60 deletions

View File

@ -4,11 +4,9 @@
package godoc
import (
"bytes"
"fmt"
"go/ast"
"go/build"
"go/printer"
"io"
"log"
"os"
@ -106,7 +104,8 @@ func CommandLine(w io.Writer, fs vfs.NameSpace, pres *Presentation, args []strin
// If we have more than one argument, use the remaining arguments for filtering.
if len(args) > 1 {
filterInfo(pres, args[1:], info)
info.IsFiltered = true
filterInfo(args[1:], info)
}
packageText := pres.PackageText
@ -145,7 +144,9 @@ func paths(fs vfs.NameSpace, pres *Presentation, path string) (string, string) {
return pathpkg.Join(pres.PkgFSRoot(), path), path
}
func filterInfo(pres *Presentation, args []string, info *PageInfo) {
// filterInfo updates info to include only the nodes that match the given
// filter args.
func filterInfo(args []string, info *PageInfo) {
rx, err := makeRx(args)
if err != nil {
log.Fatalf("illegal regular expression from %v: %v", args, err)
@ -154,29 +155,21 @@ func filterInfo(pres *Presentation, args []string, info *PageInfo) {
filter := func(s string) bool { return rx.MatchString(s) }
switch {
case info.PAst != nil:
cmap := ast.NewCommentMap(info.FSet, info.PAst, info.PAst.Comments)
ast.FilterFile(info.PAst, filter)
// Special case: Don't use templates for printing
// so we only get the filtered declarations without
// package clause or extra whitespace.
for i, d := range info.PAst.Decls {
// determine the comments associated with d only
comments := cmap.Filter(d).Comments()
cn := &printer.CommentedNode{Node: d, Comments: comments}
if i > 0 {
fmt.Println()
newPAst := map[string]*ast.File{}
for name, a := range info.PAst {
cmap := ast.NewCommentMap(info.FSet, a, a.Comments)
a.Comments = []*ast.CommentGroup{} // remove all comments.
ast.FilterFile(a, filter)
if len(a.Decls) > 0 {
newPAst[name] = a
}
if pres.HTMLMode {
var buf bytes.Buffer
pres.WriteNode(&buf, info.FSet, cn)
FormatText(os.Stdout, buf.Bytes(), -1, true, "", nil)
} else {
pres.WriteNode(os.Stdout, info.FSet, cn)
for _, d := range a.Decls {
// add back the comments associated with d only
comments := cmap.Filter(d).Comments()
a.Comments = append(a.Comments, comments...)
}
fmt.Println()
}
return
info.PAst = newPAst // add only matching files.
case info.PDoc != nil:
info.PDoc.Filter(filter)
}

View File

@ -157,6 +157,17 @@ func TestCommandLine(t *testing.T) {
mfs := mapfs.New(map[string]string{
"src/pkg/bar/bar.go": `// Package bar is an example.
package bar
`,
"src/pkg/foo/foo.go": `// Package foo.
package foo
// First function is first.
func First() {
}
// Second function is second.
func Second() {
}
`,
"src/cmd/go/doc.go": `// The go command
package main
@ -172,7 +183,10 @@ package main
p.cmdHandler = handlerServer{p, c, "/cmd/", "/src/cmd"}
p.pkgHandler = handlerServer{p, c, "/pkg/", "/src/pkg"}
p.initFuncMap()
p.PackageText = template.Must(template.New("PackageText").Funcs(p.FuncMap()).Parse(`{{with .PAst}}{{node $ .}}{{end}}{{with .PDoc}}{{if $.IsMain}}COMMAND {{.Doc}}{{else}}PACKAGE {{.Doc}}{{end}}{{end}}`))
p.PackageText = template.Must(template.New("PackageText").Funcs(p.FuncMap()).Parse(`{{with .PAst}}{{range $filename, $ast := .}}{{$filename}}:
{{node $ $ast}}{{end}}{{end}}{{with .PDoc}}{{if $.IsMain}}COMMAND {{.Doc}}{{else}}PACKAGE {{.Doc}}{{end}}{{with .Funcs}}
{{range .}}{{node $ .Decl}}
{{comment_text .Doc " " "\t"}}{{end}}{{end}}{{end}}`))
for _, tc := range []struct {
desc string
@ -190,10 +204,20 @@ package main
args: []string{"bar"},
exp: "PACKAGE Package bar is an example.\n",
},
{
desc: "package w. filter",
args: []string{"foo", "First"},
exp: "PACKAGE \nfunc First()\n First function is first.\n",
},
{
desc: "source mode",
args: []string{"src/bar"},
exp: "// Package bar is an example.\npackage bar\n",
exp: "bar/bar.go:\n// Package bar is an example.\npackage bar\n",
},
{
desc: "source mode w. filter",
args: []string{"src/foo", "Second"},
exp: "// Second function is second.\nfunc Second() {\n}",
},
{
desc: "command",

View File

@ -219,12 +219,13 @@ type PageInfo struct {
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
Notes map[string][]*doc.Note // nil if no package Notes
PAst *ast.File // nil if no AST with package exports
IsMain bool // true for package main
FSet *token.FileSet // nil if no package documentation
PDoc *doc.Package // nil if no package documentation
Examples []*doc.Example // nil if no example code
Notes map[string][]*doc.Note // nil if no package Notes
PAst map[string]*ast.File // nil if no AST with package exports
IsMain bool // true for package main
IsFiltered bool // true if results were filtered
// directory info
Dirs *DirList // nil if no directory information

View File

@ -24,7 +24,7 @@ func (c *Corpus) parseFile(fset *token.FileSet, filename string, mode parser.Mod
return parser.ParseFile(fset, filename, src, mode)
}
func (c *Corpus) parseFiles(fset *token.FileSet, abspath string, localnames []string) (map[string]*ast.File, error) {
func (c *Corpus) parseFiles(fset *token.FileSet, relpath string, abspath string, localnames []string) (map[string]*ast.File, error) {
files := make(map[string]*ast.File)
for _, f := range localnames {
absname := pathpkg.Join(abspath, f)
@ -32,7 +32,7 @@ func (c *Corpus) parseFiles(fset *token.FileSet, abspath string, localnames []st
if err != nil {
return nil, err
}
files[absname] = file
files[pathpkg.Join(relpath, f)] = file
}
return files, nil

View File

@ -97,7 +97,7 @@ func (h *handlerServer) GetPageInfo(abspath, relpath string, mode PageInfoMode)
if len(pkgfiles) > 0 {
// build package AST
fset := token.NewFileSet()
files, err := h.c.parseFiles(fset, abspath, pkgfiles)
files, err := h.c.parseFiles(fset, relpath, abspath, pkgfiles)
if err != nil {
info.Err = err
return info
@ -128,7 +128,7 @@ func (h *handlerServer) GetPageInfo(abspath, relpath string, mode PageInfoMode)
// collect examples
testfiles := append(pkginfo.TestGoFiles, pkginfo.XTestGoFiles...)
files, err = h.c.parseFiles(fset, abspath, testfiles)
files, err = h.c.parseFiles(fset, relpath, abspath, testfiles)
if err != nil {
log.Println("parsing examples:", err)
}
@ -156,7 +156,7 @@ func (h *handlerServer) GetPageInfo(abspath, relpath string, mode PageInfoMode)
if mode&NoFiltering == 0 {
packageExports(fset, pkg)
}
info.PAst = ast.MergePackageFiles(pkg, 0)
info.PAst = files
}
info.IsMain = pkgname == "main"
}
@ -218,7 +218,10 @@ func (h *handlerServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
var tabtitle, title, subtitle string
switch {
case info.PAst != nil:
tabtitle = info.PAst.Name.Name
for _, ast := range info.PAst {
tabtitle = ast.Name.Name
break
}
case info.PDoc != nil:
tabtitle = info.PDoc.Name
default:

View File

@ -1,51 +1,56 @@
{{with .PAst}}{{node $ .}}{{end}}{{/*
{{$info := .}}{{$filtered := .IsFiltered}}{{/*
---------------------------------------
*/}}{{if $filtered}}{{range .PAst}}{{range .Decls}}{{node $info .}}{{end}}{{end}}{{else}}{{with .PAst}}{{range $filename, $ast := .}}{{$filename}}:
{{node $ $ast}}{{end}}{{end}}{{end}}{{/*
---------------------------------------
*/}}{{with .PDoc}}{{if $.IsMain}}COMMAND DOCUMENTATION
{{comment_text .Doc " " "\t"}}
{{else}}PACKAGE DOCUMENTATION
{{else}}{{if not $filtered}}PACKAGE DOCUMENTATION
package {{.Name}}
import "{{.ImportPath}}"
{{comment_text .Doc " " "\t"}}
{{example_text $ "" " "}}{{/*
{{example_text $ "" " "}}{{end}}{{/*
---------------------------------------
*/}}{{with .Consts}}
*/}}{{with .Consts}}{{if not $filtered}}
CONSTANTS
{{range .}}{{node $ .Decl}}
{{end}}{{range .}}{{node $ .Decl}}
{{comment_text .Doc " " "\t"}}
{{end}}{{end}}{{/*
---------------------------------------
*/}}{{with .Vars}}
*/}}{{with .Vars}}{{if not $filtered}}
VARIABLES
{{range .}}{{node $ .Decl}}
{{end}}{{range .}}{{node $ .Decl}}
{{comment_text .Doc " " "\t"}}
{{end}}{{end}}{{/*
---------------------------------------
*/}}{{with .Funcs}}
*/}}{{with .Funcs}}{{if not $filtered}}
FUNCTIONS
{{range .}}{{node $ .Decl}}
{{end}}{{range .}}{{node $ .Decl}}
{{comment_text .Doc " " "\t"}}
{{example_text $ .Name " "}}{{end}}{{end}}{{/*
---------------------------------------
*/}}{{with .Types}}
*/}}{{with .Types}}{{if not $filtered}}
TYPES
{{range .}}{{$tname := .Name}}{{node $ .Decl}}
{{end}}{{range .}}{{$tname := .Name}}{{node $ .Decl}}
{{comment_text .Doc " " "\t"}}
{{range .Consts}}{{node $ .Decl}}
{{comment_text .Doc " " "\t"}}

View File

@ -751,54 +751,59 @@ $(document).ready(function() {
{{end}}
{{end}}
`,
"package.txt": `{{with .PAst}}{{node $ .}}{{end}}{{/*
"package.txt": `{{$info := .}}{{$filtered := .IsFiltered}}{{/*
---------------------------------------
*/}}{{if $filtered}}{{range .PAst}}{{range .Decls}}{{node $info .}}{{end}}{{end}}{{else}}{{with .PAst}}{{range $filename, $ast := .}}{{$filename}}:
{{node $ $ast}}{{end}}{{end}}{{end}}{{/*
---------------------------------------
*/}}{{with .PDoc}}{{if $.IsMain}}COMMAND DOCUMENTATION
{{comment_text .Doc " " "\t"}}
{{else}}PACKAGE DOCUMENTATION
{{else}}{{if not $filtered}}PACKAGE DOCUMENTATION
package {{.Name}}
import "{{.ImportPath}}"
{{comment_text .Doc " " "\t"}}
{{example_text $ "" " "}}{{/*
{{example_text $ "" " "}}{{end}}{{/*
---------------------------------------
*/}}{{with .Consts}}
*/}}{{with .Consts}}{{if not $filtered}}
CONSTANTS
{{range .}}{{node $ .Decl}}
{{end}}{{range .}}{{node $ .Decl}}
{{comment_text .Doc " " "\t"}}
{{end}}{{end}}{{/*
---------------------------------------
*/}}{{with .Vars}}
*/}}{{with .Vars}}{{if not $filtered}}
VARIABLES
{{range .}}{{node $ .Decl}}
{{end}}{{range .}}{{node $ .Decl}}
{{comment_text .Doc " " "\t"}}
{{end}}{{end}}{{/*
---------------------------------------
*/}}{{with .Funcs}}
*/}}{{with .Funcs}}{{if not $filtered}}
FUNCTIONS
{{range .}}{{node $ .Decl}}
{{end}}{{range .}}{{node $ .Decl}}
{{comment_text .Doc " " "\t"}}
{{example_text $ .Name " "}}{{end}}{{end}}{{/*
---------------------------------------
*/}}{{with .Types}}
*/}}{{with .Types}}{{if not $filtered}}
TYPES
{{range .}}{{$tname := .Name}}{{node $ .Decl}}
{{end}}{{range .}}{{$tname := .Name}}{{node $ .Decl}}
{{comment_text .Doc " " "\t"}}
{{range .Consts}}{{node $ .Decl}}
{{comment_text .Doc " " "\t"}}