github.com/flyinox/gosm@v0.0.0-20171117061539-16768cb62077/src/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 "regexp" 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 = regexp.MustCompile(`<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 }