[WIP] Support validation markers for slice/array elements - #209
Conversation
📊 Coverage ReportTotal Coverage: 81.4% DetailsRun |
|
@sivchari |
|
Hi @shiiyan |
|
Sorry for the late response! Thanks for working on this! Slice/array element validation is a great addition. I took a look at the implementation and have some thoughts on how we could make it more extensible. Let me share a few ideas. Error path should include the indexRight now, when an element fails validation, we can't tell which one: // Current
err.Path = "GT.Scores" // Which element failed?
err.Value = t.Scores // The whole slice
// Ideal
err.Path = "GT.Scores[0]" // Ah, the first element\!
err.Value = v // Just that elementThis would make debugging much easier and matches what other validators like go-playground do with Suggestion: Extract type-checking utilitiesThe helpers in How about extracting them to a shared place? // internal/validator/rules/types.go
func GetElementType(t types.Type) types.Type {
switch u := t.Underlying().(type) {
case *types.Slice:
return u.Elem()
case *types.Array:
return u.Elem()
default:
return nil
}
}
func IsNumeric(t types.Type) bool {
basic, ok := t.Underlying().(*types.Basic)
return ok && (basic.Info()&types.IsNumeric) \!= 0
}
// Returns (supported, isElementValidation)
func CheckTypeSupport(t types.Type, check func(types.Type) bool) (bool, bool) {
if check(t) {
return true, false
}
if elem := GetElementType(t); elem \!= nil && check(elem) {
return true, true
}
return false, false
}Then in the factory: func ValidateGT(input registry.ValidatorInput) validator.Validator {
typ := input.Pass.TypesInfo.TypeOf(input.Field.Type)
supported, isElement := CheckTypeSupport(typ, IsNumeric)
if \!supported {
return nil
}
v := >Validator{...}
if isElement {
return &validator.ElementValidatorWrapper{Inner: v}
}
return v
}Suggestion: Move loop generation to the templateInstead of generating the loop inside // Validate() stays simple — single value logic only
func (m *gtValidator) Validate() string {
return fmt.Sprintf("\!(t.%s > %s)", m.FieldName(), m.gtValue)
}Template handles the rest: {{ if isElementValidation . }}
for i, v := range t.{{.FieldName}} {
if {{ .Validate | replaceFieldRef .FieldName }} {
err := {{.ErrVariable}}
err.Path = fmt.Sprintf("{{.FieldPath}}[%d]", i)
err.Value = v
errs = append(errs, err)
}
}
{{ else }}
// existing single-value logic
{{ end }}This way:
Quick summary
What do you think? Happy to discuss or help with the implementation! |
Description
This Work In Progress (WIP) pull request implements support for validation markers targeted at elements within slices and arrays. It's a new feature addition in the repository and addresses the use case where validations need to be applied to individual elements of collections, rather than just the container.
How Slice/Array Validation for gt Was Implemented:
if {{.Validate}} { ... }[]T/[N]Twhere element type T is numeric!(t.Field > value)for _, v := range t.Fieldloop that returns true on the first violating elementType of Change
Quality Checklist
Before submitting this pull request, ensure your contribution meets these quality standards:
Code Quality
make golangci-lintwithout errorsmake testTesting Requirements
internal/analyzers/govalid/testdata/)test/unit/)test/benchmark/)cd test && go generatePerformance Standards
test/benchmark/README.mdDocumentation
Integration
make generate-validator MARKER=yourmarkergo install ./cmd/govalid/Final Verification
Additional Notes
Related Issues
Closes #80