Passed
Push — main ( 488c53...b50ef2 )
by Rushan
57s queued 11s
created

validation.Scope.BuildViolation   A

Complexity

Conditions 3

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 8
dl 0
loc 11
ccs 7
cts 7
cp 1
crap 3
rs 10
c 0
b 0
f 0
nop 2
1
package validation
2
3
import (
4
	"context"
5
	"fmt"
6
7
	languagepkg "github.com/muonsoft/language"
8
	"golang.org/x/text/language"
9
)
10
11
// Scope holds the current state of validation. On the client-side of the package,
12
// it can be used to build violations.
13
type Scope struct {
14
	context          context.Context
15
	propertyPath     PropertyPath
16
	language         language.Tag
17
	translator       *Translator
18
	violationFactory ViolationFactory
19
}
20
21
// Context returns context value that was passed to the validator by Context argument or
22
// by creating scoped validator with the validator.WithContext method.
23
func (s Scope) Context() context.Context {
24 1
	return s.context
25
}
26
27
// BuildViolation is used to create violations in validation methods of constraints.
28
// This method automatically injects the property path and language of the current validation scope.
29
func (s Scope) BuildViolation(code, message string) *ViolationBuilder {
30 1
	b := NewViolationBuilder(s.violationFactory).BuildViolation(code, message)
31 1
	b.SetPropertyPath(s.propertyPath)
32
33 1
	if s.language != language.Und {
34 1
		b.SetLanguage(s.language)
35 1
	} else if s.context != nil {
36 1
		b.SetLanguage(languagepkg.FromContext(s.context))
37
	}
38
39 1
	return b
40
}
41
42
func (s *Scope) applyOptions(options ...Option) error {
43 1
	for _, option := range options {
44 1
		var err error
45 1
		if o, ok := option.(internalOption); ok {
46 1
			err = o.setUpOnScope(s)
47
		} else {
48 1
			err = option.SetUp()
49
		}
50 1
		if err != nil {
51 1
			return s.describeOptionError(option, err)
52
		}
53
	}
54
55 1
	return nil
56
}
57
58
func (s *Scope) describeOptionError(option Option, err error) error {
59 1
	c, ok := option.(Constraint)
60 1
	if !ok {
61
		return fmt.Errorf(`failed to set up option: %w`, err)
62
	}
63
64 1
	if len(s.propertyPath) == 0 {
65 1
		err = fmt.Errorf(`failed to set up constraint "%s": %w`, c.Name(), err)
66
	} else {
67 1
		err = fmt.Errorf(`failed to set up constraint "%s" at path "%s": %w`, c.Name(), s.propertyPath.String(), err)
68
	}
69
70 1
	return err
71
}
72
73
func (s Scope) withContext(ctx context.Context) Scope {
74 1
	s.context = ctx
75
76 1
	return s
77
}
78
79
func (s Scope) withLanguage(tag language.Tag) Scope {
80 1
	s.language = tag
81
82 1
	return s
83
}
84
85
func (s Scope) atProperty(name string) Scope {
86 1
	s.propertyPath = append(s.propertyPath, PropertyNameElement(name))
87
88 1
	return s
89
}
90
91
func (s Scope) atIndex(index int) Scope {
92 1
	s.propertyPath = append(s.propertyPath, ArrayIndexElement(index))
93
94 1
	return s
95
}
96
97
func newScope() Scope {
98 1
	translator := newTranslator()
99
100 1
	return Scope{
101
		context:          context.Background(),
102
		translator:       translator,
103
		violationFactory: newViolationFactory(translator),
104
	}
105
}
106