golang.org/x/tools@v0.21.0/go/cfg/main.go (about) 1 //go:build ignore 2 3 // Copyright 2024 The Go Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file. 6 7 // The cfg command prints the control-flow graph of the first function 8 // or method whose name matches 'funcname' in the specified package. 9 // 10 // Usage: cfg package funcname 11 // 12 // Example: 13 // 14 // $ go build -o cfg ./go/cfg/main.go 15 // $ cfg ./go/cfg stmt | dot -Tsvg > cfg.svg && open cfg.svg 16 package main 17 18 import ( 19 "flag" 20 "fmt" 21 "go/ast" 22 "log" 23 "os" 24 25 "golang.org/x/tools/go/cfg" 26 "golang.org/x/tools/go/packages" 27 ) 28 29 func main() { 30 flag.Parse() 31 if len(flag.Args()) != 2 { 32 log.Fatal("Usage: package funcname") 33 } 34 pattern, funcname := flag.Args()[0], flag.Args()[1] 35 pkgs, err := packages.Load(&packages.Config{Mode: packages.LoadSyntax}, pattern) 36 if err != nil { 37 log.Fatal(err) 38 } 39 if packages.PrintErrors(pkgs) > 0 { 40 os.Exit(1) 41 } 42 for _, pkg := range pkgs { 43 for _, f := range pkg.Syntax { 44 for _, decl := range f.Decls { 45 if decl, ok := decl.(*ast.FuncDecl); ok { 46 if decl.Name.Name == funcname { 47 g := cfg.New(decl.Body, mayReturn) 48 fmt.Println(g.Dot(pkg.Fset)) 49 os.Exit(0) 50 } 51 } 52 } 53 } 54 } 55 log.Fatalf("no function %q found in %s", funcname, pattern) 56 } 57 58 // A trivial mayReturn predicate that looks only at syntax, not types. 59 func mayReturn(call *ast.CallExpr) bool { 60 switch fun := call.Fun.(type) { 61 case *ast.Ident: 62 return fun.Name != "panic" 63 case *ast.SelectorExpr: 64 return fun.Sel.Name != "Fatal" 65 } 66 return true 67 }