(structName, tagType, goFieldName string, fieldType ast.Expr, tokenPos token.Pos, pass *analysis.Pass)
| 269 | } |
| 270 | |
| 271 | func checkAndReportInvalidTypes(structName, tagType, goFieldName string, fieldType ast.Expr, tokenPos token.Pos, pass *analysis.Pass) (newFieldType string, ok bool) { |
| 272 | switch ft := fieldType.(type) { |
| 273 | case *ast.StarExpr: |
| 274 | // Check for *[]T where T is builtin - should be []T |
| 275 | if arrType, ok := ft.X.(*ast.ArrayType); ok { |
| 276 | if ident, ok := arrType.Elt.(*ast.Ident); ok && isBuiltinType(ident.Name) { |
| 277 | const msg = "change the %q field type to %q in the struct %q" |
| 278 | pass.Reportf(tokenPos, msg, goFieldName, "[]"+ident.Name, structName) |
| 279 | } else if starExpr, ok := arrType.Elt.(*ast.StarExpr); ok { |
| 280 | // Check for *[]*T - should be []*T |
| 281 | if ident, ok := starExpr.X.(*ast.Ident); ok { |
| 282 | const msg = "change the %q field type to %q in the struct %q" |
| 283 | pass.Reportf(tokenPos, msg, goFieldName, "[]*"+ident.Name, structName) |
| 284 | } |
| 285 | } else { |
| 286 | checkStructArrayType(structName, goFieldName, arrType, tokenPos, pass) |
| 287 | } |
| 288 | } |
| 289 | // Check for *map - should be map |
| 290 | if _, ok := ft.X.(*ast.MapType); ok { |
| 291 | const msg = "change the %q field type to %q in the struct %q" |
| 292 | pass.Reportf(tokenPos, msg, goFieldName, exprToString(ft.X), structName) |
| 293 | } |
| 294 | if ident, ok := ft.X.(*ast.Ident); ok && tagType == "url" && isBuiltinType(ident.Name) { |
| 295 | // Remove the pointer for primitives in url tags |
| 296 | return ident.Name, false |
| 297 | } |
| 298 | return "", true |
| 299 | case *ast.MapType: |
| 300 | return "", true |
| 301 | case *ast.ArrayType: |
| 302 | checkStructArrayType(structName, goFieldName, ft, tokenPos, pass) |
| 303 | return "", true |
| 304 | case *ast.SelectorExpr: |
| 305 | // Check for json.RawMessage |
| 306 | if ident, ok := ft.X.(*ast.Ident); ok && ident.Name == "json" && ft.Sel.Name == "RawMessage" { |
| 307 | return "", true |
| 308 | } |
| 309 | case *ast.Ident: |
| 310 | // Check for `any` type |
| 311 | if ft.Name == "any" { |
| 312 | return "", true |
| 313 | } |
| 314 | if tagType == "url" && isBuiltinType(ft.Name) { |
| 315 | return "", true |
| 316 | } |
| 317 | default: |
| 318 | log.Fatalf("unhandled type: %T", ft) |
| 319 | } |
| 320 | |
| 321 | newFieldType = "*" + exprToString(fieldType) |
| 322 | return newFieldType, false |
| 323 | } |
| 324 | |
| 325 | func checkStructArrayType(structName, goFieldName string, arrType *ast.ArrayType, tokenPos token.Pos, pass *analysis.Pass) { |
| 326 | if starExpr, ok := arrType.Elt.(*ast.StarExpr); ok { |
no test coverage detected
searching dependent graphs…