validationCode produces Go code that runs the validations defined in the given attribute definition if any against the content of the variable named target. The generated code assumes that there is a pre-existing "err" variable of type error. It initializes that variable in case a validation fails.
(att *expr.AttributeExpr, attCtx *AttributeContext, req, alias bool, target, context string)
| 337 | // |
| 338 | // context is used to produce helpful messages in case of error. |
| 339 | func validationCode(att *expr.AttributeExpr, attCtx *AttributeContext, req, alias bool, target, context string) string { |
| 340 | validation := att.Validation |
| 341 | if ut, ok := att.Type.(expr.UserType); ok { |
| 342 | val := ut.Attribute().Validation |
| 343 | if val != nil { |
| 344 | if validation == nil { |
| 345 | validation = val |
| 346 | } else { |
| 347 | validation.Merge(val) |
| 348 | } |
| 349 | att.Validation = validation |
| 350 | } |
| 351 | } |
| 352 | if validation == nil { |
| 353 | return "" |
| 354 | } |
| 355 | |
| 356 | var ( |
| 357 | kind = att.Type.Kind() |
| 358 | unaliased = unalias(att.Type) |
| 359 | isNativePointer = unaliased.Kind() == expr.BytesKind || unaliased.Kind() == expr.AnyKind |
| 360 | isPointer = attCtx.Pointer || (!req && (att.DefaultValue == nil || !attCtx.UseDefault)) |
| 361 | tval = target |
| 362 | ) |
| 363 | if isPointer && expr.IsPrimitive(att.Type) && !isNativePointer { |
| 364 | tval = "*" + tval |
| 365 | } |
| 366 | if alias { |
| 367 | tval = fmt.Sprintf("%s(%s)", unaliased.Name(), tval) |
| 368 | // When validating alias types, use the underlying type's kind |
| 369 | // for string detection (needed for utf8.RuneCountInString usage) |
| 370 | kind = unaliased.Kind() |
| 371 | } |
| 372 | data := map[string]any{ |
| 373 | "attribute": att, |
| 374 | "attCtx": attCtx, |
| 375 | "isPointer": isPointer, |
| 376 | "context": context, |
| 377 | "target": target, |
| 378 | "targetVal": tval, |
| 379 | "string": kind == expr.StringKind, |
| 380 | "array": expr.IsArray(att.Type), |
| 381 | "map": expr.IsMap(att.Type), |
| 382 | } |
| 383 | runTemplate := func(tmpl *template.Template, data any) string { |
| 384 | var buf bytes.Buffer |
| 385 | if err := tmpl.Execute(&buf, data); err != nil { |
| 386 | panic(err) // bug |
| 387 | } |
| 388 | return strings.Trim(buf.String(), "\n") |
| 389 | } |
| 390 | res := make([]string, 0, 8) // preallocate with typical validation count |
| 391 | if values := validation.Values; values != nil { |
| 392 | data["values"] = values |
| 393 | if val := runTemplate(enumValT, data); val != "" { |
| 394 | res = append(res, val) |
| 395 | } |
| 396 | } |
no test coverage detected