// checkUntaggedLiteral checks if a composite literal is an struct literal with // untagged fields. func (f *File) checkUntaggedLiteral(c *ast.CompositeLit) { if !vet("composites") { return } // Check that the CompositeLit's type is a slice or array (which need no tag), if possible. if f.pkg != nil { typ := f.pkg.types[c] if typ != nil { // If it's a named type, pull out the underlying type. if namedType, ok := typ.(*types.NamedType); ok { typ = namedType.Underlying } switch typ.(type) { case *types.Slice: return case *types.Array: return } } } // It's a struct, or we can't tell it's not a struct because we don't have types. // Check if the CompositeLit contains an untagged field. allKeyValue := true for _, e := range c.Elts { if _, ok := e.(*ast.KeyValueExpr); !ok { allKeyValue = false break } } if allKeyValue { return } // Check that the CompositeLit's type has the form pkg.Typ. s, ok := c.Type.(*ast.SelectorExpr) if !ok { return } pkg, ok := s.X.(*ast.Ident) if !ok { return } // Convert the package name to an import path, and compare to a whitelist. path := pkgPath(f, pkg.Name) if path == "" { f.Warnf(c.Pos(), "unresolvable package for %s.%s literal", pkg.Name, s.Sel.Name) return } typ := path + "." + s.Sel.Name if *compositeWhiteList && untaggedLiteralWhitelist[typ] { return } f.Warnf(c.Pos(), "%s composite literal uses untagged fields", typ) }
// checkUntaggedLiteral checks if a composite literal is an struct literal with // untagged fields. func (f *File) checkUntaggedLiteral(c *ast.CompositeLit) { if !*vetUntaggedLiteral && !*vetAll { return } // Check if the CompositeLit contains an untagged field. allKeyValue := true for _, e := range c.Elts { if _, ok := e.(*ast.KeyValueExpr); !ok { allKeyValue = false break } } if allKeyValue { return } // Check that the CompositeLit's type has the form pkg.Typ. s, ok := c.Type.(*ast.SelectorExpr) if !ok { return } pkg, ok := s.X.(*ast.Ident) if !ok { return } // Convert the package name to an import path, and compare to a whitelist. path := pkgPath(f, pkg.Name) if path == "" { f.Warnf(c.Pos(), "unresolvable package for %s.%s literal", pkg.Name, s.Sel.Name) return } typ := path + "." + s.Sel.Name if untaggedLiteralWhitelist[typ] { return } f.Warnf(c.Pos(), "%s struct literal uses untagged fields", typ) }
// checkUntaggedLiteral checks if a composite literal is a struct literal with // untagged fields. func (f *File) checkUntaggedLiteral(c *ast.CompositeLit) { if !vet("composites") { return } typ := c.Type for { if typ1, ok := c.Type.(*ast.ParenExpr); ok { typ = typ1 continue } break } switch typ.(type) { case *ast.ArrayType: return case *ast.MapType: return case *ast.StructType: return // a literal struct type does not need to use tags case *ast.Ident: // A simple type name like t or T does not need tags either, // since it is almost certainly declared in the current package. // (The exception is names being used via import . "pkg", but // those are already breaking the Go 1 compatibility promise, // so not reporting potential additional breakage seems okay.) return } // Otherwise the type is a selector like pkg.Name. // We only care if pkg.Name is a struct, not if it's a map, array, or slice. isStruct, typeString := f.pkg.isStruct(c) if !isStruct { return } if typeString == "" { // isStruct doesn't know typeString = f.gofmt(typ) } // It's a struct, or we can't tell it's not a struct because we don't have types. // Check if the CompositeLit contains an untagged field. allKeyValue := true for _, e := range c.Elts { if _, ok := e.(*ast.KeyValueExpr); !ok { allKeyValue = false break } } if allKeyValue { return } // Check that the CompositeLit's type has the form pkg.Typ. s, ok := c.Type.(*ast.SelectorExpr) if !ok { return } pkg, ok := s.X.(*ast.Ident) if !ok { return } // Convert the package name to an import path, and compare to a whitelist. path := pkgPath(f, pkg.Name) if path == "" { f.Badf(c.Pos(), "unresolvable package for %s.%s literal", pkg.Name, s.Sel.Name) return } typeName := path + "." + s.Sel.Name if *compositeWhiteList && untaggedLiteralWhitelist[typeName] { return } f.Warn(c.Pos(), typeString+" composite literal uses untagged fields") }