Validate validates that all lists and map literals have homogeneous types, i.e. don't contain dyn types. This validator makes an exception for list and map literals which occur at any level of nesting within string format calls.
(_ *Env, c ValidatorConfig, a *ast.AST, iss *Issues)
| 311 | // This validator makes an exception for list and map literals which occur at any level of nesting within |
| 312 | // string format calls. |
| 313 | func (v homogeneousAggregateLiteralValidator) Validate(_ *Env, c ValidatorConfig, a *ast.AST, iss *Issues) { |
| 314 | var exemptedFunctions []string |
| 315 | exemptedFunctions = c.GetOrDefault(HomogeneousAggregateLiteralExemptFunctions, exemptedFunctions).([]string) |
| 316 | root := ast.NavigateAST(a) |
| 317 | listExprs := ast.MatchDescendants(root, ast.KindMatcher(ast.ListKind)) |
| 318 | for _, listExpr := range listExprs { |
| 319 | if inExemptFunction(listExpr, exemptedFunctions) { |
| 320 | continue |
| 321 | } |
| 322 | l := listExpr.AsList() |
| 323 | elements := l.Elements() |
| 324 | optIndices := l.OptionalIndices() |
| 325 | var elemType *Type |
| 326 | for i, e := range elements { |
| 327 | et := a.GetType(e.ID()) |
| 328 | if isOptionalIndex(i, optIndices) { |
| 329 | et = et.Parameters()[0] |
| 330 | } |
| 331 | if elemType == nil { |
| 332 | elemType = et |
| 333 | continue |
| 334 | } |
| 335 | if !elemType.IsEquivalentType(et) { |
| 336 | v.typeMismatch(iss, e.ID(), elemType, et) |
| 337 | break |
| 338 | } |
| 339 | } |
| 340 | } |
| 341 | mapExprs := ast.MatchDescendants(root, ast.KindMatcher(ast.MapKind)) |
| 342 | for _, mapExpr := range mapExprs { |
| 343 | if inExemptFunction(mapExpr, exemptedFunctions) { |
| 344 | continue |
| 345 | } |
| 346 | m := mapExpr.AsMap() |
| 347 | entries := m.Entries() |
| 348 | var keyType, valType *Type |
| 349 | for _, e := range entries { |
| 350 | mapEntry := e.AsMapEntry() |
| 351 | key, val := mapEntry.Key(), mapEntry.Value() |
| 352 | kt, vt := a.GetType(key.ID()), a.GetType(val.ID()) |
| 353 | if mapEntry.IsOptional() { |
| 354 | vt = vt.Parameters()[0] |
| 355 | } |
| 356 | if keyType == nil && valType == nil { |
| 357 | keyType, valType = kt, vt |
| 358 | continue |
| 359 | } |
| 360 | if !keyType.IsEquivalentType(kt) { |
| 361 | v.typeMismatch(iss, key.ID(), keyType, kt) |
| 362 | } |
| 363 | if !valType.IsEquivalentType(vt) { |
| 364 | v.typeMismatch(iss, val.ID(), valType, vt) |
| 365 | } |
| 366 | } |
| 367 | } |
| 368 | } |
| 369 | |
| 370 | func inExemptFunction(e ast.NavigableExpr, exemptFunctions []string) bool { |
nothing calls this directly
no test coverage detected