on 5b2da2b help sign in
81 lines 2.1 kB history raw
1// The hugeparam command identifies by-value parameters that are larger than n bytes.
2//
3// Example:
4// $ ./hugeparams encoding/xml
5package main
7import (
8 "flag"
9 "fmt"
10 "go/ast"
11 "go/token"
12 "go/types"
13 "log"
15 "golang.org/x/tools/go/loader"
18//!+
19var bytesFlag = flag.Int("bytes", 48, "maximum parameter size in bytes")
21var sizeof = (&types.StdSizes{8, 8}).Sizeof // the sizeof function
23func PrintHugeParams(fset *token.FileSet, info *types.Info, files []*ast.File) {
24 checkTuple := func(descr string, tuple *types.Tuple) {
25 for i := 0; i < tuple.Len(); i++ {
26 v := tuple.At(i)
27 if sz := sizeof(v.Type()); sz > int64(*bytesFlag) {
28 fmt.Printf("%s: %q %s: %s = %d bytes\n",
29 fset.Position(v.Pos()),
30 v.Name(), descr, v.Type(), sz)
31 }
32 }
33 }
34 checkSig := func(sig *types.Signature) {
35 checkTuple("parameter", sig.Params())
36 checkTuple("result", sig.Results())
37 }
38 for _, file := range files {
39 ast.Inspect(file, func(n ast.Node) bool {
40 switch n := n.(type) {
41 case *ast.FuncDecl:
42 checkSig(info.Defs[n.Name].Type().(*types.Signature))
43 case *ast.FuncLit:
44 checkSig(info.Types[n.Type].Type.(*types.Signature))
45 }
46 return true
47 })
48 }
51//!-
53func main() {
54 flag.Parse()
56 // The loader loads a complete Go program from source code.
57 var conf loader.Config
58 _, err := conf.FromArgs(flag.Args(), false)
59 if err != nil {
60 log.Fatal(err) // command syntax error
61 }
62 lprog, err := conf.Load()
63 if err != nil {
64 log.Fatal(err) // load error
65 }
67 for _, info := range lprog.InitialPackages() {
68 PrintHugeParams(lprog.Fset, &info.Info, info.Files)
69 }
72/*
73//!+output
74% ./hugeparam encoding/xml
75/go/src/encoding/xml/marshal.go:167:50: "start" parameter: encoding/xml.StartElement = 56 bytes
76/go/src/encoding/xml/marshal.go:734:97: "" result: encoding/xml.StartElement = 56 bytes
77/go/src/encoding/xml/marshal.go:761:51: "start" parameter: encoding/xml.StartElement = 56 bytes
78/go/src/encoding/xml/marshal.go:781:68: "start" parameter: encoding/xml.StartElement = 56 bytes
79/go/src/encoding/xml/xml.go:72:30: "" result: encoding/xml.StartElement = 56 bytes
80//!-output
81*/