// SPDX-License-Identifier: GPL-3.0-or-later // Package enumtest reads the constants of an enum type from Go source, so // a test can check that every value is handled - and fails when a value is // added without the code that needs it. Only tests import it. package enumtest import ( "fmt" "go/ast" "go/parser" "go/token" ) // Names returns, in declaration order, the constants declared with type typ // in the Go file at path, including those an iota block types implicitly. // A type with no constants there is an error, so a renamed file or type // cannot make a test pass by finding nothing. func Names(path, typ string) ([]string, error) { f, err := parser.ParseFile(token.NewFileSet(), path, nil, 0) if err != nil { return nil, err } var names []string for _, decl := range f.Decls { g, ok := decl.(*ast.GenDecl) if !ok || g.Tok != token.CONST { continue } inType := false for _, spec := range g.Specs { vs, ok := spec.(*ast.ValueSpec) if !ok { continue } switch { case vs.Type != nil: id, ok := vs.Type.(*ast.Ident) inType = ok && id.Name == typ case len(vs.Values) > 0: inType = false } if inType { for _, n := range vs.Names { names = append(names, n.Name) } } } } if len(names) == 0 { return nil, fmt.Errorf("%s: no constants of type %s", path, typ) } return names, nil }