"io/ioutil"
"os"
"path/filepath"
+ "sort"
"strconv"
"strings"
exporters = make(map[string]func() interface{})
)
+// The exporters data as written to the vetx output file.
+type vetxExport struct {
+ Name string
+ Data interface{}
+}
+
// Vet can provide its own "export information"
// about package A to future invocations of vet
// on packages importing A. If B imports A,
mustTypecheck = true
doPackage(vcfg.GoFiles, nil)
if vcfg.VetxOutput != "" {
- out := make(map[string]interface{})
+ out := make([]vetxExport, 0, len(exporters))
for name, fn := range exporters {
- out[name] = fn()
+ out = append(out, vetxExport{
+ Name: name,
+ Data: fn(),
+ })
}
+ // Sort the data so that it is consistent across builds.
+ sort.Slice(out, func(i, j int) bool {
+ return out[i].Name < out[j].Name
+ })
var buf bytes.Buffer
if err := gob.NewEncoder(&buf).Encode(out); err != nil {
errorf("encoding vet output: %v", err)
if err != nil {
return nil
}
- m = make(map[string]interface{})
- err = gob.NewDecoder(bytes.NewReader(data)).Decode(&m)
+ var out []vetxExport
+ err = gob.NewDecoder(bytes.NewReader(data)).Decode(&out)
if err != nil {
return nil
}
+ m = make(map[string]interface{})
+ for _, x := range out {
+ m[x.Name] = x.Data
+ }
imported[path] = m
}
return m[key]
"go/token"
"go/types"
"regexp"
+ "sort"
"strconv"
"strings"
"unicode/utf8"
funcDecl, callExpr)
registerPkgCheck("printf", findPrintfLike)
registerExport("printf", exportPrintfLike)
- gob.Register(map[string]int(nil))
+ gob.Register([]printfExport(nil))
}
func initPrintFlags() {
var localPrintfLike = make(map[string]int)
+type printfExport struct {
+ Name string
+ Kind int
+}
+
+// printfImported maps from package name to the printf vet data
+// exported by that package.
+var printfImported = make(map[string]map[string]int)
+
type printfWrapper struct {
name string
fn *ast.FuncDecl
}
func exportPrintfLike() interface{} {
- return localPrintfLike
+ out := make([]printfExport, 0, len(localPrintfLike))
+ for name, kind := range localPrintfLike {
+ out = append(out, printfExport{
+ Name: name,
+ Kind: kind,
+ })
+ }
+ sort.Slice(out, func(i, j int) bool {
+ return out[i].Name < out[j].Name
+ })
+ return out
}
// isPrint records the print functions.
if pkgpath == "" {
kind = localPrintfLike[name]
+ } else if m, ok := printfImported[pkgpath]; ok {
+ kind = m[name]
} else {
- printfLike, _ := readVetx(pkgpath, "printf").(map[string]int)
- kind = printfLike[name]
+ var m map[string]int
+ if out, ok := readVetx(pkgpath, "printf").([]printfExport); ok {
+ m = make(map[string]int)
+ for _, x := range out {
+ m[x.Name] = x.Kind
+ }
+ }
+ printfImported[pkgpath] = m
+ kind = m[name]
}
if kind == 0 {