Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: common/config/validation/validation.go

Issue 2951393002: [errors] de-specialize Transient in favor of Tags. (Closed)
Patch Set: more refactor Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The LUCI Authors. All rights reserved. 1 // Copyright 2017 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0 2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file. 3 // that can be found in the LICENSE file.
4 4
5 // Package validation provides a helper for performing config validations. 5 // Package validation provides a helper for performing config validations.
6 package validation 6 package validation
7 7
8 import ( 8 import (
9 "fmt" 9 "fmt"
10 "strings" 10 "strings"
(...skipping 26 matching lines...) Expand all
37 // now). Each file may have some internal nested structure. The logical path 37 // now). Each file may have some internal nested structure. The logical path
38 // inside this structure is captured through Enter and Exit calls. 38 // inside this structure is captured through Enter and Exit calls.
39 type Context struct { 39 type Context struct {
40 Logger logging.Logger // logs errors as they appear 40 Logger logging.Logger // logs errors as they appear
41 41
42 errors errors.MultiError // all accumulated errors 42 errors errors.MultiError // all accumulated errors
43 file string // the currently validated file 43 file string // the currently validated file
44 element []string // logical path of a sub-element we validate, see Enter 44 element []string // logical path of a sub-element we validate, see Enter
45 } 45 }
46 46
47 type fileTagType struct{ Key errors.TagKey }
48
49 func (f fileTagType) With(name string) errors.TagValue { return errors.MkTagValu e(f.Key, name) }
50 func (f fileTagType) In(err error) (v string, ok bool) {
51 d, ok := errors.TagValueIn(f.Key, err)
52 if ok {
53 v = d.(string)
54 }
55 return
56 }
57
58 type elementTagType struct{ Key errors.TagKey }
59
60 func (e elementTagType) With(elements []string) errors.TagValue {
61 return errors.MkTagValue(e.Key, append([]string(nil), elements...))
62 }
63 func (e elementTagType) In(err error) (v []string, ok bool) {
64 d, ok := errors.TagValueIn(e.Key, err)
65 if ok {
66 v = d.([]string)
67 }
68 return
69 }
70
71 var fileTag = fileTagType{errors.NewTagKey("holds the file name for tests")}
72 var elementTag = elementTagType{errors.NewTagKey("holds the elements for tests") }
73
47 // Error records a validation error. 74 // Error records a validation error.
48 func (v *Context) Error(msg string, args ...interface{}) { 75 func (v *Context) Error(msg string, args ...interface{}) {
49 ctx := "" 76 ctx := ""
50 if v.file != "" { 77 if v.file != "" {
51 ctx = fmt.Sprintf("in %q", v.file) 78 ctx = fmt.Sprintf("in %q", v.file)
52 } else { 79 } else {
53 ctx = "in <unspecified file>" 80 ctx = "in <unspecified file>"
54 } 81 }
55 if len(v.element) != 0 { 82 if len(v.element) != 0 {
56 ctx += " (" + strings.Join(v.element, " / ") + ")" 83 ctx += " (" + strings.Join(v.element, " / ") + ")"
57 } 84 }
58 85
59 // Prepending ctx to msg before passing it to fmt is not entirely correc t, 86 // Prepending ctx to msg before passing it to fmt is not entirely correc t,
60 // since ctx may have format specifiers (like %s), that will be misunder stood. 87 // since ctx may have format specifiers (like %s), that will be misunder stood.
61 // So we put ctx in the argument list. 88 // So we put ctx in the argument list.
62 msg = "%s: " + msg 89 msg = "%s: " + msg
63 args = append([]interface{}{ctx}, args...) 90 args = append([]interface{}{ctx}, args...)
64 if v.Logger != nil { 91 if v.Logger != nil {
65 v.Logger.Errorf(msg, args...) 92 v.Logger.Errorf(msg, args...)
66 } 93 }
67 94
68 // Make the file and the logical path also usable through error inspecti on. 95 // Make the file and the logical path also usable through error inspecti on.
69 err := errors.Reason(fmt.Sprintf(msg, args...)). 96 err := errors.Reason(fmt.Sprintf(msg, args...)).
70 » » D("file", v.file). 97 » » Tag(fileTag.With(v.file), elementTag.With(v.element)).Err()
71 » » D("element", append([]string{}, v.element...)).Err()
72 v.errors = append(v.errors, err) 98 v.errors = append(v.errors, err)
73 } 99 }
74 100
75 // SetFile records that what follows is errors for this particular file. 101 // SetFile records that what follows is errors for this particular file.
76 // 102 //
77 // Changing the file resets the current element (see Enter/Exit). 103 // Changing the file resets the current element (see Enter/Exit).
78 func (v *Context) SetFile(path string) { 104 func (v *Context) SetFile(path string) {
79 if v.file != path { 105 if v.file != path {
80 v.file = path 106 v.file = path
81 v.element = nil 107 v.element = nil
(...skipping 25 matching lines...) Expand all
107 // 133 //
108 // Returns nil otherwise. 134 // Returns nil otherwise.
109 func (v *Context) Finalize() error { 135 func (v *Context) Finalize() error {
110 if len(v.errors) == 0 { 136 if len(v.errors) == 0 {
111 return nil 137 return nil
112 } 138 }
113 return &Error{ 139 return &Error{
114 Errors: append(errors.MultiError{}, v.errors...), 140 Errors: append(errors.MultiError{}, v.errors...),
115 } 141 }
116 } 142 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698