...

Source file src/pkg/go/doc/headscan.go

     1	// Copyright 2011 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	// +build ignore
     6	
     7	/*
     8		The headscan command extracts comment headings from package files;
     9		it is used to detect false positives which may require an adjustment
    10		to the comment formatting heuristics in comment.go.
    11	
    12		Usage: headscan [-root root_directory]
    13	
    14		By default, the $GOROOT/src directory is scanned.
    15	*/
    16	package main
    17	
    18	import (
    19		"bytes"
    20		"flag"
    21		"fmt"
    22		"go/doc"
    23		"go/parser"
    24		"go/token"
    25		"internal/lazyregexp"
    26		"os"
    27		"path/filepath"
    28		"runtime"
    29		"strings"
    30	)
    31	
    32	var (
    33		root    = flag.String("root", filepath.Join(runtime.GOROOT(), "src"), "root of filesystem tree to scan")
    34		verbose = flag.Bool("v", false, "verbose mode")
    35	)
    36	
    37	// ToHTML in comment.go assigns a (possibly blank) ID to each heading
    38	var html_h = lazyregexp.New(`<h3 id="[^"]*">`)
    39	
    40	const html_endh = "</h3>\n"
    41	
    42	func isGoFile(fi os.FileInfo) bool {
    43		return strings.HasSuffix(fi.Name(), ".go") &&
    44			!strings.HasSuffix(fi.Name(), "_test.go")
    45	}
    46	
    47	func appendHeadings(list []string, comment string) []string {
    48		var buf bytes.Buffer
    49		doc.ToHTML(&buf, comment, nil)
    50		for s := buf.String(); ; {
    51			loc := html_h.FindStringIndex(s)
    52			if len(loc) == 0 {
    53				break
    54			}
    55			i := loc[1]
    56			j := strings.Index(s, html_endh)
    57			if j < 0 {
    58				list = append(list, s[i:]) // incorrect HTML
    59				break
    60			}
    61			list = append(list, s[i:j])
    62			s = s[j+len(html_endh):]
    63		}
    64		return list
    65	}
    66	
    67	func main() {
    68		flag.Parse()
    69		fset := token.NewFileSet()
    70		nheadings := 0
    71		err := filepath.Walk(*root, func(path string, fi os.FileInfo, err error) error {
    72			if !fi.IsDir() {
    73				return nil
    74			}
    75			pkgs, err := parser.ParseDir(fset, path, isGoFile, parser.ParseComments)
    76			if err != nil {
    77				if *verbose {
    78					fmt.Fprintln(os.Stderr, err)
    79				}
    80				return nil
    81			}
    82			for _, pkg := range pkgs {
    83				d := doc.New(pkg, path, doc.Mode(0))
    84				list := appendHeadings(nil, d.Doc)
    85				for _, d := range d.Consts {
    86					list = appendHeadings(list, d.Doc)
    87				}
    88				for _, d := range d.Types {
    89					list = appendHeadings(list, d.Doc)
    90				}
    91				for _, d := range d.Vars {
    92					list = appendHeadings(list, d.Doc)
    93				}
    94				for _, d := range d.Funcs {
    95					list = appendHeadings(list, d.Doc)
    96				}
    97				if len(list) > 0 {
    98					// directories may contain multiple packages;
    99					// print path and package name
   100					fmt.Printf("%s (package %s)\n", path, pkg.Name)
   101					for _, h := range list {
   102						fmt.Printf("\t%s\n", h)
   103					}
   104					nheadings += len(list)
   105				}
   106			}
   107			return nil
   108		})
   109		if err != nil {
   110			fmt.Fprintln(os.Stderr, err)
   111			os.Exit(1)
   112		}
   113		fmt.Println(nheadings, "headings found")
   114	}
   115	

View as plain text