Validate tests whether the attribute required fields exist. Since attributes are unaware of their context, additional context information can be provided to be used in error messages. The parent definition context is automatically added to error messages.
(ctx string, parent eval.Expression)
| 237 | // to be used in error messages. The parent definition context is automatically |
| 238 | // added to error messages. |
| 239 | func (a *AttributeExpr) Validate(ctx string, parent eval.Expression) *eval.ValidationErrors { |
| 240 | if validated[a] { |
| 241 | return nil |
| 242 | } |
| 243 | validated[a] = true |
| 244 | verr := new(eval.ValidationErrors) |
| 245 | if a.Type == nil { |
| 246 | verr.Add(parent, "attribute type is nil") |
| 247 | return verr |
| 248 | } |
| 249 | if ctx != "" { |
| 250 | ctx += " - " |
| 251 | } |
| 252 | verr.Merge(a.validateEnumDefault(ctx, parent)) |
| 253 | if v := a.Validation; v != nil { |
| 254 | verr.Merge(v.Validate(ctx, parent)) |
| 255 | } |
| 256 | verr.Merge(a.validateExamples(ctx, parent)) |
| 257 | if o := AsObject(a.Type); o != nil { |
| 258 | for _, n := range a.AllRequired() { |
| 259 | if a.Find(n) == nil { |
| 260 | verr.Add(parent, `%srequired field %q does not exist in type %s`, ctx, n, a.Type.Name()) |
| 261 | } |
| 262 | } |
| 263 | var pkgPath string |
| 264 | if ut, ok := a.Type.(UserType); ok { |
| 265 | if meta, ok := ut.Attribute().Meta["struct:pkg:path"]; ok { |
| 266 | pkgPath = meta[0] |
| 267 | } |
| 268 | } |
| 269 | for _, nat := range *o { |
| 270 | verr.Merge(a.validatePkgPath(pkgPath, nat.Attribute.Type)) |
| 271 | ctx = fmt.Sprintf("field %s", nat.Name) |
| 272 | verr.Merge(nat.Attribute.Validate(ctx, parent)) |
| 273 | } |
| 274 | } else if ar := AsArray(a.Type); ar != nil { |
| 275 | elemType := ar.ElemType |
| 276 | verr.Merge(elemType.Validate(ctx, a)) |
| 277 | } else if u := AsUnion(a.Type); u != nil { |
| 278 | for _, ut := range u.Values { |
| 279 | verr.Merge(ut.Attribute.Validate(ctx, parent)) |
| 280 | } |
| 281 | } |
| 282 | |
| 283 | if view, ok := a.Meta.Last(ViewMetaKey); ok { |
| 284 | rt, ok := a.Type.(*ResultTypeExpr) |
| 285 | if !ok { |
| 286 | verr.Add(parent, "%s uses view %q but %q is not a result type", ctx, view, a.Type.Name()) |
| 287 | } |
| 288 | if view != DefaultView && rt != nil { |
| 289 | found := false |
| 290 | for _, v := range rt.Views { |
| 291 | if v.Name == view { |
| 292 | found = true |
| 293 | break |
| 294 | } |
| 295 | } |
| 296 | if !found { |