Skip to content

Instantly share code, notes, and snippets.

@reusee
Created February 27, 2020 00:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save reusee/0e1f7795e51b97515ae52edb15fd10f6 to your computer and use it in GitHub Desktop.
Save reusee/0e1f7795e51b97515ae52edb15fd10f6 to your computer and use it in GitHub Desktop.
hint composite literal
package main
import (
"fmt"
"go/ast"
"go/types"
"golang.org/x/tools/go/ast/astutil"
"golang.org/x/tools/go/packages"
)
var pt = fmt.Printf
func main() {
pkgs, err := packages.Load(&packages.Config{
Mode: packages.NeedSyntax |
packages.NeedTypesInfo |
packages.NeedTypes,
}, ".")
if err != nil {
panic(err)
}
if packages.PrintErrors(pkgs) > 0 {
return
}
pkg := pkgs[0]
typ := pkg.Types.Scope().Lookup("Foo")
fieldNames := make(map[string]bool)
structType := typ.Type().(*types.Named).Underlying().(*types.Struct)
for i := 0; i < structType.NumFields(); i++ {
fieldNames[structType.Field(i).Name()] = true
}
for ident, obj := range pkg.TypesInfo.Uses {
if obj != typ {
continue
}
for _, file := range pkg.Syntax {
path, _ := astutil.PathEnclosingInterval(file, ident.Pos(), ident.End())
if len(path) < 2 {
continue
}
cl, ok := path[1].(*ast.CompositeLit)
if !ok {
continue
}
names := make(map[string]bool)
for _, expr := range cl.Elts {
kv := expr.(*ast.KeyValueExpr)
name := kv.Key.(*ast.Ident).Name
names[name] = true
}
for name := range fieldNames {
if !names[name] {
pt("no %s at %s\n", name, pkg.Fset.Position(ident.Pos()))
}
}
}
}
}
type Foo struct {
Bar string
}
var f1 = Foo{}
var f2 = Foo{
Bar: "bar",
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment