diff options
author | Robert Griesemer <gri@golang.org> | 2011-12-01 11:50:15 -0800 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2011-12-01 11:50:15 -0800 |
commit | bc9ce6a129af4b99ec63810e61166e2b98285823 (patch) | |
tree | e9e2a104f9825f125d8e2994383ccef7ee68befd | |
parent | 473de6035930f4014a07f5b2a1315993cb42fb27 (diff) | |
download | go-bc9ce6a129af4b99ec63810e61166e2b98285823.tar.gz go-bc9ce6a129af4b99ec63810e61166e2b98285823.zip |
go/doc: better headscan
- scan all comments not just the package documentation
- declutter output so that false positives are more easily spotted
- count the number of headings to quickly see differences
- minor tweaks
R=golang-dev, r, r
CC=golang-dev
https://golang.org/cl/5450061
-rw-r--r-- | src/pkg/go/doc/comment.go | 14 | ||||
-rw-r--r-- | src/pkg/go/doc/comment_test.go | 2 | ||||
-rw-r--r-- | src/pkg/go/doc/headscan.go | 90 |
3 files changed, 82 insertions, 24 deletions
diff --git a/src/pkg/go/doc/comment.go b/src/pkg/go/doc/comment.go index 44a047588d..d7bb384ed0 100644 --- a/src/pkg/go/doc/comment.go +++ b/src/pkg/go/doc/comment.go @@ -303,9 +303,8 @@ func heading(line []byte) []byte { return nil } - // allow ' for possessive 's only - b := line - for { + // allow "'" for possessive "'s" only + for b := line; ; { i := bytes.IndexRune(b, '\'') if i < 0 { break @@ -339,7 +338,7 @@ func heading(line []byte) []byte { func ToHTML(w io.Writer, s []byte, words map[string]string) { inpara := false lastWasBlank := false - lastNonblankWasHeading := false + lastWasHeading := false close := func() { if inpara { @@ -389,10 +388,11 @@ func ToHTML(w io.Writer, s []byte, words map[string]string) { emphasize(w, line, nil, false) // no nice text formatting } w.Write(html_endpre) + lastWasHeading = false continue } - if lastWasBlank && !lastNonblankWasHeading && i+2 < len(lines) && + if lastWasBlank && !lastWasHeading && i+2 < len(lines) && isBlank(lines[i+1]) && !isBlank(lines[i+2]) && indentLen(lines[i+2]) == 0 { // current line is non-blank, sourounded by blank lines // and the next non-blank line is not indented: this @@ -403,7 +403,7 @@ func ToHTML(w io.Writer, s []byte, words map[string]string) { template.HTMLEscape(w, head) w.Write(html_endh) i += 2 - lastNonblankWasHeading = true + lastWasHeading = true continue } } @@ -411,7 +411,7 @@ func ToHTML(w io.Writer, s []byte, words map[string]string) { // open paragraph open() lastWasBlank = false - lastNonblankWasHeading = false + lastWasHeading = false emphasize(w, lines[i], words, true) // nice text formatting i++ } diff --git a/src/pkg/go/doc/comment_test.go b/src/pkg/go/doc/comment_test.go index 9e77ae2cde..870660ad62 100644 --- a/src/pkg/go/doc/comment_test.go +++ b/src/pkg/go/doc/comment_test.go @@ -19,7 +19,7 @@ var headingTests = []struct { {"", false}, {"section", false}, {"A typical usage:", true}, - {"δ is Greek", false}, // TODO: consider allowing this + {"δ is Greek", false}, {"Foo §", false}, {"Fermat's Last Sentence", true}, {"Fermat's", true}, diff --git a/src/pkg/go/doc/headscan.go b/src/pkg/go/doc/headscan.go index 95953b3bdc..83f24627c9 100644 --- a/src/pkg/go/doc/headscan.go +++ b/src/pkg/go/doc/headscan.go @@ -1,53 +1,111 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* + The headscan command extracts comment headings from package files; + it is used to detect false positives which may require an adjustment + to the comment formatting heuristics in comment.go. + + Usage: headscan [-root root_directory] + + By default, the $GOROOT/src directory is scanned. +*/ package main import ( "bytes" "flag" + "fmt" "go/doc" "go/parser" "go/token" - "log" "os" "path/filepath" + "runtime" "strings" ) +var ( + root = flag.String("root", filepath.Join(runtime.GOROOT(), "src"), "root of filesystem tree to scan") + verbose = flag.Bool("v", false, "verbose mode") +) + +const ( + html_h = "<h3>" + html_endh = "</h3>\n" +) + func isGoFile(fi os.FileInfo) bool { return strings.HasSuffix(fi.Name(), ".go") && !strings.HasSuffix(fi.Name(), "_test.go") } +func appendHeadings(list []string, comment string) []string { + var buf bytes.Buffer + doc.ToHTML(&buf, []byte(comment), nil) + for s := buf.String(); ; { + i := strings.Index(s, html_h) + if i < 0 { + break + } + i += len(html_h) + j := strings.Index(s, html_endh) + if j < 0 { + list = append(list, s[i:]) // incorrect HTML + break + } + list = append(list, s[i:j]) + s = s[j+len(html_endh):] + } + return list +} + func main() { - fset := token.NewFileSet() - rootDir := flag.String("root", "./", "root of filesystem tree to scan") flag.Parse() - err := filepath.Walk(*rootDir, func(path string, fi os.FileInfo, err error) error { + fset := token.NewFileSet() + nheadings := 0 + err := filepath.Walk(*root, func(path string, fi os.FileInfo, err error) error { if !fi.IsDir() { return nil } pkgs, err := parser.ParseDir(fset, path, isGoFile, parser.ParseComments) if err != nil { - log.Println(path, err) + if *verbose { + fmt.Fprintln(os.Stderr, err) + } return nil } for _, pkg := range pkgs { d := doc.NewPackageDoc(pkg, path) - buf := new(bytes.Buffer) - doc.ToHTML(buf, []byte(d.Doc), nil) - b := buf.Bytes() - for { - i := bytes.Index(b, []byte("<h3>")) - if i == -1 { - break + list := appendHeadings(nil, d.Doc) + for _, d := range d.Consts { + list = appendHeadings(list, d.Doc) + } + for _, d := range d.Types { + list = appendHeadings(list, d.Doc) + } + for _, d := range d.Vars { + list = appendHeadings(list, d.Doc) + } + for _, d := range d.Funcs { + list = appendHeadings(list, d.Doc) + } + if len(list) > 0 { + // directories may contain multiple packages; + // print path and package name + fmt.Printf("%s (package %s)\n", path, pkg.Name) + for _, h := range list { + fmt.Printf("\t%s\n", h) } - line := bytes.SplitN(b[i:], []byte("\n"), 2)[0] - log.Printf("%s: %s", path, line) - b = b[i+len(line):] + nheadings += len(list) } } return nil }) if err != nil { - log.Fatal(err) + fmt.Fprintln(os.Stderr, err) + os.Exit(1) } + fmt.Println(nheadings, "headings found") } |