blob: ba62aaa7f1a872d34ed4c76f22695270da6ea074 [file] [log] [blame]
// The hugeparam command identifies by-value parameters that are larger than n bytes.
//
// Example:
// $ ./hugeparams encoding/xml
package main
import (
"flag"
"fmt"
"go/ast"
"go/token"
"log"
"golang.org/x/tools/go/loader"
"golang.org/x/tools/go/types" // TODO: will use std go/types after Mar 2016
)
//!+
var bytesFlag = flag.Int("bytes", 48, "maximum parameter size in bytes")
var sizeof = (&types.StdSizes{8, 8}).Sizeof // the sizeof function
func PrintHugeParams(fset *token.FileSet, info *types.Info, files []*ast.File) {
checkTuple := func(descr string, tuple *types.Tuple) {
for i := 0; i < tuple.Len(); i++ {
v := tuple.At(i)
if sz := sizeof(v.Type()); sz > int64(*bytesFlag) {
fmt.Printf("%s: %q %s: %s = %d bytes\n",
fset.Position(v.Pos()),
v.Name(), descr, v.Type(), sz)
}
}
}
checkSig := func(sig *types.Signature) {
checkTuple("parameter", sig.Params())
checkTuple("result", sig.Results())
}
for _, file := range files {
ast.Inspect(file, func(n ast.Node) bool {
switch n := n.(type) {
case *ast.FuncDecl:
checkSig(info.Defs[n.Name].Type().(*types.Signature))
case *ast.FuncLit:
checkSig(info.Types[n.Type].Type.(*types.Signature))
}
return true
})
}
}
//!-
func main() {
flag.Parse()
// The loader loads a complete Go program from source code.
var conf loader.Config
_, err := conf.FromArgs(flag.Args(), false)
if err != nil {
log.Fatal(err) // command syntax error
}
lprog, err := conf.Load()
if err != nil {
log.Fatal(err) // load error
}
for _, info := range lprog.InitialPackages() {
PrintHugeParams(lprog.Fset, &info.Info, info.Files)
}
}
/*
//!+output
% ./hugeparam encoding/xml
/go/src/encoding/xml/marshal.go:167:50: "start" parameter: encoding/xml.StartElement = 56 bytes
/go/src/encoding/xml/marshal.go:734:97: "" result: encoding/xml.StartElement = 56 bytes
/go/src/encoding/xml/marshal.go:761:51: "start" parameter: encoding/xml.StartElement = 56 bytes
/go/src/encoding/xml/marshal.go:781:68: "start" parameter: encoding/xml.StartElement = 56 bytes
/go/src/encoding/xml/xml.go:72:30: "" result: encoding/xml.StartElement = 56 bytes
//!-output
*/