github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/go/doc/headscan.go (about)

     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  	"os"
    26  	"path/filepath"
    27  	"runtime"
    28  	"strings"
    29  )
    30  
    31  var (
    32  	root    = flag.String("root", filepath.Join(runtime.GOROOT(), "src"), "root of filesystem tree to scan")
    33  	verbose = flag.Bool("v", false, "verbose mode")
    34  )
    35  
    36  const (
    37  	html_h    = "<h3>"
    38  	html_endh = "</h3>\n"
    39  )
    40  
    41  func isGoFile(fi os.FileInfo) bool {
    42  	return strings.HasSuffix(fi.Name(), ".go") &&
    43  		!strings.HasSuffix(fi.Name(), "_test.go")
    44  }
    45  
    46  func appendHeadings(list []string, comment string) []string {
    47  	var buf bytes.Buffer
    48  	doc.ToHTML(&buf, comment, nil)
    49  	for s := buf.String(); ; {
    50  		i := strings.Index(s, html_h)
    51  		if i < 0 {
    52  			break
    53  		}
    54  		i += len(html_h)
    55  		j := strings.Index(s, html_endh)
    56  		if j < 0 {
    57  			list = append(list, s[i:]) // incorrect HTML
    58  			break
    59  		}
    60  		list = append(list, s[i:j])
    61  		s = s[j+len(html_endh):]
    62  	}
    63  	return list
    64  }
    65  
    66  func main() {
    67  	flag.Parse()
    68  	fset := token.NewFileSet()
    69  	nheadings := 0
    70  	err := filepath.Walk(*root, func(path string, fi os.FileInfo, err error) error {
    71  		if !fi.IsDir() {
    72  			return nil
    73  		}
    74  		pkgs, err := parser.ParseDir(fset, path, isGoFile, parser.ParseComments)
    75  		if err != nil {
    76  			if *verbose {
    77  				fmt.Fprintln(os.Stderr, err)
    78  			}
    79  			return nil
    80  		}
    81  		for _, pkg := range pkgs {
    82  			d := doc.New(pkg, path, doc.Mode(0))
    83  			list := appendHeadings(nil, d.Doc)
    84  			for _, d := range d.Consts {
    85  				list = appendHeadings(list, d.Doc)
    86  			}
    87  			for _, d := range d.Types {
    88  				list = appendHeadings(list, d.Doc)
    89  			}
    90  			for _, d := range d.Vars {
    91  				list = appendHeadings(list, d.Doc)
    92  			}
    93  			for _, d := range d.Funcs {
    94  				list = appendHeadings(list, d.Doc)
    95  			}
    96  			if len(list) > 0 {
    97  				// directories may contain multiple packages;
    98  				// print path and package name
    99  				fmt.Printf("%s (package %s)\n", path, pkg.Name)
   100  				for _, h := range list {
   101  					fmt.Printf("\t%s\n", h)
   102  				}
   103  				nheadings += len(list)
   104  			}
   105  		}
   106  		return nil
   107  	})
   108  	if err != nil {
   109  		fmt.Fprintln(os.Stderr, err)
   110  		os.Exit(1)
   111  	}
   112  	fmt.Println(nheadings, "headings found")
   113  }