github.com/bir3/gocompiler@v0.9.2202/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 //go: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 "flag" 20 "fmt" 21 "github.com/bir3/gocompiler/src/go/doc" 22 "github.com/bir3/gocompiler/src/go/parser" 23 "github.com/bir3/gocompiler/src/go/token" 24 "io/fs" 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 fs.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 strings.Builder 49 doc.ToHTML(&buf, comment, nil) 50 for s := buf.String(); s != ""; { 51 loc := html_h.FindStringIndex(s) 52 if len(loc) == 0 { 53 break 54 } 55 var inner string 56 inner, s, _ = strings.Cut(s[loc[1]:], html_endh) 57 list = append(list, inner) 58 } 59 return list 60 } 61 62 func main() { 63 flag.Parse() 64 fset := token.NewFileSet() 65 nheadings := 0 66 err := filepath.WalkDir(*root, func(path string, info fs.DirEntry, err error) error { 67 if !info.IsDir() { 68 return nil 69 } 70 pkgs, err := parser.ParseDir(fset, path, isGoFile, parser.ParseComments) 71 if err != nil { 72 if *verbose { 73 fmt.Fprintln(os.Stderr, err) 74 } 75 return nil 76 } 77 for _, pkg := range pkgs { 78 d := doc.New(pkg, path, doc.Mode(0)) 79 list := appendHeadings(nil, d.Doc) 80 for _, d := range d.Consts { 81 list = appendHeadings(list, d.Doc) 82 } 83 for _, d := range d.Types { 84 list = appendHeadings(list, d.Doc) 85 } 86 for _, d := range d.Vars { 87 list = appendHeadings(list, d.Doc) 88 } 89 for _, d := range d.Funcs { 90 list = appendHeadings(list, d.Doc) 91 } 92 if len(list) > 0 { 93 // directories may contain multiple packages; 94 // print path and package name 95 fmt.Printf("%s (package %s)\n", path, pkg.Name) 96 for _, h := range list { 97 fmt.Printf("\t%s\n", h) 98 } 99 nheadings += len(list) 100 } 101 } 102 return nil 103 }) 104 if err != nil { 105 fmt.Fprintln(os.Stderr, err) 106 os.Exit(1) 107 } 108 fmt.Println(nheadings, "headings found") 109 }