honnef.co/go/tools@v0.5.0-0.dev.0.20240520180541-dcae280a5e87/internal/cmd/gogrep/gogrep.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"go/ast"
     7  	"go/format"
     8  	"go/parser"
     9  	"go/token"
    10  	"os"
    11  	"path/filepath"
    12  	"reflect"
    13  	"strings"
    14  
    15  	"honnef.co/go/tools/pattern"
    16  )
    17  
    18  func match(fset *token.FileSet, pat pattern.Pattern, f *ast.File) {
    19  	ast.Inspect(f, func(node ast.Node) bool {
    20  		if node == nil {
    21  			return true
    22  		}
    23  
    24  		if _, ok := pat.Relevant[reflect.TypeOf(node)]; ok {
    25  			m := &pattern.Matcher{}
    26  			if m.Match(pat, node) {
    27  				fmt.Printf("%s: ", fset.Position(node.Pos()))
    28  				format.Node(os.Stdout, fset, node)
    29  				fmt.Println()
    30  			}
    31  
    32  			// OPT(dh): we could further speed this up by not
    33  			// chasing down impossible subtrees. For example,
    34  			// we'll never find an ImportSpec beneath a FuncLit.
    35  		}
    36  		return true
    37  	})
    38  
    39  }
    40  
    41  func main() {
    42  	flag.Parse()
    43  	// XXX don't use MustParse, handle error
    44  	p := &pattern.Parser{}
    45  	q, err := p.Parse(flag.Args()[0])
    46  	if err != nil {
    47  		fmt.Println(err)
    48  		os.Exit(1)
    49  	}
    50  	dir := flag.Args()[1]
    51  	// XXX should we create a new fileset per file? what if we're
    52  	// checking millions of files, will this use up a lot of memory?
    53  	fset := token.NewFileSet()
    54  	filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
    55  		if err != nil {
    56  			// XXX error handling
    57  			panic(err)
    58  		}
    59  		if !strings.HasSuffix(path, ".go") {
    60  			return nil
    61  		}
    62  		// XXX don't try to parse irregular files or directories
    63  		f, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
    64  		if err != nil {
    65  			// XXX log error?
    66  			return nil
    67  		}
    68  
    69  		match(fset, q, f)
    70  
    71  		return nil
    72  	})
    73  }