Bubble errors instead of panicking (#194)
This commit is contained in:
@@ -12,7 +12,6 @@ import (
|
|||||||
type Plugins []interface{}
|
type Plugins []interface{}
|
||||||
|
|
||||||
func build(k *Kong, ast interface{}) (app *Application, err error) {
|
func build(k *Kong, ast interface{}) (app *Application, err error) {
|
||||||
defer catch(&err)
|
|
||||||
v := reflect.ValueOf(ast)
|
v := reflect.ValueOf(ast)
|
||||||
iv := reflect.Indirect(v)
|
iv := reflect.Indirect(v)
|
||||||
if v.Kind() != reflect.Ptr || iv.Kind() != reflect.Struct {
|
if v.Kind() != reflect.Ptr || iv.Kind() != reflect.Struct {
|
||||||
@@ -25,7 +24,10 @@ func build(k *Kong, ast interface{}) (app *Application, err error) {
|
|||||||
for _, flag := range extraFlags {
|
for _, flag := range extraFlags {
|
||||||
seenFlags[flag.Name] = true
|
seenFlags[flag.Name] = true
|
||||||
}
|
}
|
||||||
node := buildNode(k, iv, ApplicationNode, seenFlags)
|
node, err := buildNode(k, iv, ApplicationNode, seenFlags)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if len(node.Positional) > 0 && len(node.Children) > 0 {
|
if len(node.Positional) > 0 && len(node.Children) > 0 {
|
||||||
return nil, fmt.Errorf("can't mix positional arguments and branching arguments on %T", ast)
|
return nil, fmt.Errorf("can't mix positional arguments and branching arguments on %T", ast)
|
||||||
}
|
}
|
||||||
@@ -46,12 +48,15 @@ type flattenedField struct {
|
|||||||
tag *Tag
|
tag *Tag
|
||||||
}
|
}
|
||||||
|
|
||||||
func flattenedFields(v reflect.Value) (out []flattenedField) {
|
func flattenedFields(v reflect.Value) (out []flattenedField, err error) {
|
||||||
v = reflect.Indirect(v)
|
v = reflect.Indirect(v)
|
||||||
for i := 0; i < v.NumField(); i++ {
|
for i := 0; i < v.NumField(); i++ {
|
||||||
ft := v.Type().Field(i)
|
ft := v.Type().Field(i)
|
||||||
fv := v.Field(i)
|
fv := v.Field(i)
|
||||||
tag := parseTag(v, ft)
|
tag, err := parseTag(v, ft)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
if tag.Ignored {
|
if tag.Ignored {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -67,11 +72,18 @@ func flattenedFields(v reflect.Value) (out []flattenedField) {
|
|||||||
fv = fv.Elem()
|
fv = fv.Elem()
|
||||||
} else if fv.Type() == reflect.TypeOf(Plugins{}) {
|
} else if fv.Type() == reflect.TypeOf(Plugins{}) {
|
||||||
for i := 0; i < fv.Len(); i++ {
|
for i := 0; i < fv.Len(); i++ {
|
||||||
out = append(out, flattenedFields(fv.Index(i).Elem())...)
|
fields, ferr := flattenedFields(fv.Index(i).Elem())
|
||||||
|
if ferr != nil {
|
||||||
|
return nil, ferr
|
||||||
|
}
|
||||||
|
out = append(out, fields...)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
sub := flattenedFields(fv)
|
sub, err := flattenedFields(fv)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
for _, subf := range sub {
|
for _, subf := range sub {
|
||||||
// Assign parent if it's not already set.
|
// Assign parent if it's not already set.
|
||||||
if subf.tag.Group == "" {
|
if subf.tag.Group == "" {
|
||||||
@@ -84,16 +96,20 @@ func flattenedFields(v reflect.Value) (out []flattenedField) {
|
|||||||
}
|
}
|
||||||
out = append(out, sub...)
|
out = append(out, sub...)
|
||||||
}
|
}
|
||||||
return out
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildNode(k *Kong, v reflect.Value, typ NodeType, seenFlags map[string]bool) *Node {
|
func buildNode(k *Kong, v reflect.Value, typ NodeType, seenFlags map[string]bool) (*Node, error) {
|
||||||
node := &Node{
|
node := &Node{
|
||||||
Type: typ,
|
Type: typ,
|
||||||
Target: v,
|
Target: v,
|
||||||
Tag: newEmptyTag(),
|
Tag: newEmptyTag(),
|
||||||
}
|
}
|
||||||
for _, field := range flattenedFields(v) {
|
fields, err := flattenedFields(v)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, field := range fields {
|
||||||
ft := field.field
|
ft := field.field
|
||||||
fv := field.value
|
fv := field.value
|
||||||
|
|
||||||
@@ -111,9 +127,12 @@ func buildNode(k *Kong, v reflect.Value, typ NodeType, seenFlags map[string]bool
|
|||||||
if tag.Arg {
|
if tag.Arg {
|
||||||
typ = ArgumentNode
|
typ = ArgumentNode
|
||||||
}
|
}
|
||||||
buildChild(k, node, typ, v, ft, fv, tag, name, seenFlags)
|
err = buildChild(k, node, typ, v, ft, fv, tag, name, seenFlags)
|
||||||
} else {
|
} else {
|
||||||
buildField(k, node, v, ft, fv, tag, name, seenFlags)
|
err = buildField(k, node, v, ft, fv, tag, name, seenFlags)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,18 +148,21 @@ func buildNode(k *Kong, v reflect.Value, typ NodeType, seenFlags map[string]bool
|
|||||||
last := true
|
last := true
|
||||||
for i, p := range node.Positional {
|
for i, p := range node.Positional {
|
||||||
if !last && p.Required {
|
if !last && p.Required {
|
||||||
fail("argument %q can not be required after an optional", p.Name)
|
return nil, fmt.Errorf("argument %q can not be required after an optional", p.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
last = p.Required
|
last = p.Required
|
||||||
p.Position = i
|
p.Position = i
|
||||||
}
|
}
|
||||||
|
|
||||||
return node
|
return node, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildChild(k *Kong, node *Node, typ NodeType, v reflect.Value, ft reflect.StructField, fv reflect.Value, tag *Tag, name string, seenFlags map[string]bool) {
|
func buildChild(k *Kong, node *Node, typ NodeType, v reflect.Value, ft reflect.StructField, fv reflect.Value, tag *Tag, name string, seenFlags map[string]bool) error {
|
||||||
child := buildNode(k, fv, typ, seenFlags)
|
child, err := buildNode(k, fv, typ, seenFlags)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
child.Name = name
|
child.Name = name
|
||||||
child.Tag = tag
|
child.Tag = tag
|
||||||
child.Parent = node
|
child.Parent = node
|
||||||
@@ -157,10 +179,10 @@ func buildChild(k *Kong, node *Node, typ NodeType, v reflect.Value, ft reflect.S
|
|||||||
// a positional argument is provided to the child, and move it to the branching argument field.
|
// a positional argument is provided to the child, and move it to the branching argument field.
|
||||||
if tag.Arg {
|
if tag.Arg {
|
||||||
if len(child.Positional) == 0 {
|
if len(child.Positional) == 0 {
|
||||||
failField(v, ft, "positional branch must have at least one child positional argument named %q", name)
|
return failField(v, ft, "positional branch must have at least one child positional argument named %q", name)
|
||||||
}
|
}
|
||||||
if child.Positional[0].Name != name {
|
if child.Positional[0].Name != name {
|
||||||
failField(v, ft, "first field in positional branch must have the same name as the parent field (%s).", child.Name)
|
return failField(v, ft, "first field in positional branch must have the same name as the parent field (%s).", child.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
child.Argument = child.Positional[0]
|
child.Argument = child.Positional[0]
|
||||||
@@ -170,24 +192,26 @@ func buildChild(k *Kong, node *Node, typ NodeType, v reflect.Value, ft reflect.S
|
|||||||
}
|
}
|
||||||
} else if tag.Default != "" {
|
} else if tag.Default != "" {
|
||||||
if node.DefaultCmd != nil {
|
if node.DefaultCmd != nil {
|
||||||
failField(v, ft, "can't have more than one default command under %s", node.Summary())
|
return failField(v, ft, "can't have more than one default command under %s", node.Summary())
|
||||||
}
|
}
|
||||||
if tag.Default != "withargs" && (len(child.Children) > 0 || len(child.Positional) > 0) {
|
if tag.Default != "withargs" && (len(child.Children) > 0 || len(child.Positional) > 0) {
|
||||||
failField(v, ft, "default command %s must not have subcommands or arguments", child.Summary())
|
return failField(v, ft, "default command %s must not have subcommands or arguments", child.Summary())
|
||||||
}
|
}
|
||||||
node.DefaultCmd = child
|
node.DefaultCmd = child
|
||||||
}
|
}
|
||||||
node.Children = append(node.Children, child)
|
node.Children = append(node.Children, child)
|
||||||
|
|
||||||
if len(child.Positional) > 0 && len(child.Children) > 0 {
|
if len(child.Positional) > 0 && len(child.Children) > 0 {
|
||||||
failField(v, ft, "can't mix positional arguments and branching arguments")
|
return failField(v, ft, "can't mix positional arguments and branching arguments")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildField(k *Kong, node *Node, v reflect.Value, ft reflect.StructField, fv reflect.Value, tag *Tag, name string, seenFlags map[string]bool) {
|
func buildField(k *Kong, node *Node, v reflect.Value, ft reflect.StructField, fv reflect.Value, tag *Tag, name string, seenFlags map[string]bool) error {
|
||||||
mapper := k.registry.ForNamedValue(tag.Type, fv)
|
mapper := k.registry.ForNamedValue(tag.Type, fv)
|
||||||
if mapper == nil {
|
if mapper == nil {
|
||||||
failField(v, ft, "unsupported field type %s, perhaps missing a cmd:\"\" tag?", ft.Type)
|
return failField(v, ft, "unsupported field type %s, perhaps missing a cmd:\"\" tag?", ft.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
value := &Value{
|
value := &Value{
|
||||||
@@ -210,16 +234,14 @@ func buildField(k *Kong, node *Node, v reflect.Value, ft reflect.StructField, fv
|
|||||||
node.Positional = append(node.Positional, value)
|
node.Positional = append(node.Positional, value)
|
||||||
} else {
|
} else {
|
||||||
if seenFlags["--"+value.Name] {
|
if seenFlags["--"+value.Name] {
|
||||||
failField(v, ft, "duplicate flag --%s", value.Name)
|
return failField(v, ft, "duplicate flag --%s", value.Name)
|
||||||
} else {
|
|
||||||
seenFlags["--"+value.Name] = true
|
|
||||||
}
|
}
|
||||||
|
seenFlags["--"+value.Name] = true
|
||||||
if tag.Short != 0 {
|
if tag.Short != 0 {
|
||||||
if seenFlags["-"+string(tag.Short)] {
|
if seenFlags["-"+string(tag.Short)] {
|
||||||
failField(v, ft, "duplicate short flag -%c", tag.Short)
|
return failField(v, ft, "duplicate short flag -%c", tag.Short)
|
||||||
} else {
|
|
||||||
seenFlags["-"+string(tag.Short)] = true
|
|
||||||
}
|
}
|
||||||
|
seenFlags["-"+string(tag.Short)] = true
|
||||||
}
|
}
|
||||||
flag := &Flag{
|
flag := &Flag{
|
||||||
Value: value,
|
Value: value,
|
||||||
@@ -233,6 +255,7 @@ func buildField(k *Kong, node *Node, v reflect.Value, ft reflect.StructField, fv
|
|||||||
value.Flag = flag
|
value.Flag = flag
|
||||||
node.Flags = append(node.Flags, flag)
|
node.Flags = append(node.Flags, flag)
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildGroupForKey(k *Kong, key string) *Group {
|
func buildGroupForKey(k *Kong, key string) *Group {
|
||||||
|
|||||||
@@ -653,7 +653,6 @@ func (c *Context) Apply() (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Context) parseFlag(flags []*Flag, match string) (err error) {
|
func (c *Context) parseFlag(flags []*Flag, match string) (err error) {
|
||||||
defer catch(&err)
|
|
||||||
candidates := []string{}
|
candidates := []string{}
|
||||||
for _, flag := range flags {
|
for _, flag := range flags {
|
||||||
long := "--" + flag.Name
|
long := "--" + flag.Name
|
||||||
@@ -734,7 +733,6 @@ func (c *Context) RunNode(node *Node, binds ...interface{}) (err error) {
|
|||||||
// Any passed values will be bindable to arguments of the target Run() method. Additionally,
|
// Any passed values will be bindable to arguments of the target Run() method. Additionally,
|
||||||
// all parent nodes in the command structure will be bound.
|
// all parent nodes in the command structure will be bound.
|
||||||
func (c *Context) Run(binds ...interface{}) (err error) {
|
func (c *Context) Run(binds ...interface{}) (err error) {
|
||||||
defer catch(&err)
|
|
||||||
node := c.Selected()
|
node := c.Selected()
|
||||||
if node == nil {
|
if node == nil {
|
||||||
return fmt.Errorf("no command selected")
|
return fmt.Errorf("no command selected")
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ func TestParseHandlingBadBuild(t *testing.T) {
|
|||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
require.Equal(t, Error{msg: "fail=' is not quoted properly"}, r)
|
require.Equal(t, "fail=' is not quoted properly", r.(error).Error())
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
//go:build (!appengine && linux) || freebsd || darwin || dragonfly || netbsd || openbsd
|
||||||
// +build !appengine,linux freebsd darwin dragonfly netbsd openbsd
|
// +build !appengine,linux freebsd darwin dragonfly netbsd openbsd
|
||||||
|
|
||||||
package kong
|
package kong
|
||||||
|
|||||||
@@ -13,22 +13,12 @@ var (
|
|||||||
callbackReturnSignature = reflect.TypeOf((*error)(nil)).Elem()
|
callbackReturnSignature = reflect.TypeOf((*error)(nil)).Elem()
|
||||||
)
|
)
|
||||||
|
|
||||||
// Error reported by Kong.
|
func failField(parent reflect.Value, field reflect.StructField, format string, args ...interface{}) error {
|
||||||
type Error struct{ msg string }
|
|
||||||
|
|
||||||
func (e Error) Error() string { return e.msg }
|
|
||||||
|
|
||||||
func fail(format string, args ...interface{}) {
|
|
||||||
panic(Error{msg: fmt.Sprintf(format, args...)})
|
|
||||||
}
|
|
||||||
|
|
||||||
func failField(parent reflect.Value, field reflect.StructField, format string, args ...interface{}) {
|
|
||||||
name := parent.Type().Name()
|
name := parent.Type().Name()
|
||||||
if name == "" {
|
if name == "" {
|
||||||
name = "<anonymous struct>"
|
name = "<anonymous struct>"
|
||||||
}
|
}
|
||||||
msg := fmt.Sprintf("%s.%s: %s", name, field.Name, fmt.Sprintf(format, args...))
|
return fmt.Errorf("%s.%s: %s", name, field.Name, fmt.Sprintf(format, args...))
|
||||||
panic(Error{msg: msg})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must creates a new Parser or panics if there is an error.
|
// Must creates a new Parser or panics if there is an error.
|
||||||
@@ -118,16 +108,22 @@ func New(grammar interface{}, options ...Option) (*Kong, error) {
|
|||||||
|
|
||||||
// Synthesise command nodes.
|
// Synthesise command nodes.
|
||||||
for _, dcmd := range k.dynamicCommands {
|
for _, dcmd := range k.dynamicCommands {
|
||||||
tag := parseTagString(strings.Join(dcmd.tags, " "))
|
tag, terr := parseTagString(strings.Join(dcmd.tags, " "))
|
||||||
|
if terr != nil {
|
||||||
|
return nil, terr
|
||||||
|
}
|
||||||
tag.Name = dcmd.name
|
tag.Name = dcmd.name
|
||||||
tag.Help = dcmd.help
|
tag.Help = dcmd.help
|
||||||
tag.Group = dcmd.group
|
tag.Group = dcmd.group
|
||||||
tag.Cmd = true
|
tag.Cmd = true
|
||||||
v := reflect.Indirect(reflect.ValueOf(dcmd.cmd))
|
v := reflect.Indirect(reflect.ValueOf(dcmd.cmd))
|
||||||
buildChild(k, k.Model.Node, CommandNode, reflect.Value{}, reflect.StructField{
|
err = buildChild(k, k.Model.Node, CommandNode, reflect.Value{}, reflect.StructField{
|
||||||
Name: dcmd.name,
|
Name: dcmd.name,
|
||||||
Type: v.Type(),
|
Type: v.Type(),
|
||||||
}, v, tag, dcmd.name, map[string]bool{})
|
}, v, tag, dcmd.name, map[string]bool{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, option := range k.postBuildOptions {
|
for _, option := range k.postBuildOptions {
|
||||||
@@ -231,7 +227,6 @@ func (k *Kong) extraFlags() []*Flag {
|
|||||||
// Will return a ParseError if a *semantically* invalid command-line is encountered (as opposed to a syntactically
|
// Will return a ParseError if a *semantically* invalid command-line is encountered (as opposed to a syntactically
|
||||||
// invalid one, which will report a normal error).
|
// invalid one, which will report a normal error).
|
||||||
func (k *Kong) Parse(args []string) (ctx *Context, err error) {
|
func (k *Kong) Parse(args []string) (ctx *Context, err error) {
|
||||||
defer catch(&err)
|
|
||||||
ctx, err = Trace(k, args)
|
ctx, err = Trace(k, args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -398,12 +393,3 @@ func (k *Kong) LoadConfig(path string) (Resolver, error) {
|
|||||||
|
|
||||||
return k.loader(r)
|
return k.loader(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func catch(err *error) {
|
|
||||||
msg := recover()
|
|
||||||
if test, ok := msg.(Error); ok {
|
|
||||||
*err = test
|
|
||||||
} else if msg != nil {
|
|
||||||
panic(msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -317,16 +317,6 @@ func (v *Value) IsCounter() bool {
|
|||||||
|
|
||||||
// Parse tokens into value, parse, and validate, but do not write to the field.
|
// Parse tokens into value, parse, and validate, but do not write to the field.
|
||||||
func (v *Value) Parse(scan *Scanner, target reflect.Value) (err error) {
|
func (v *Value) Parse(scan *Scanner, target reflect.Value) (err error) {
|
||||||
defer func() {
|
|
||||||
if rerr := recover(); rerr != nil {
|
|
||||||
switch rerr := rerr.(type) {
|
|
||||||
case Error:
|
|
||||||
err = errors.Wrap(rerr, v.ShortSummary())
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("mapper %T failed to apply to %s: %s", v.Mapper, v.Summary(), rerr))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
err = v.Mapper.Decode(&DecodeContext{Value: v, Scan: scan}, target)
|
err = v.Mapper.Decode(&DecodeContext{Value: v, Scan: scan}, target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, v.ShortSummary())
|
return errors.Wrap(err, v.ShortSummary())
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ type tagChars struct {
|
|||||||
var kongChars = tagChars{sep: ',', quote: '\'', assign: '='}
|
var kongChars = tagChars{sep: ',', quote: '\'', assign: '='}
|
||||||
var bareChars = tagChars{sep: ' ', quote: '"', assign: ':'}
|
var bareChars = tagChars{sep: ' ', quote: '"', assign: ':'}
|
||||||
|
|
||||||
func parseTagItems(tagString string, chr tagChars) map[string][]string {
|
func parseTagItems(tagString string, chr tagChars) (map[string][]string, error) {
|
||||||
d := map[string][]string{}
|
d := map[string][]string{}
|
||||||
key := []rune{}
|
key := []rune{}
|
||||||
value := []rune{}
|
value := []rune{}
|
||||||
@@ -91,11 +91,10 @@ func parseTagItems(tagString string, chr tagChars) map[string][]string {
|
|||||||
if next == chr.sep || eof {
|
if next == chr.sep || eof {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fail("%v has an unexpected char at pos %v", tagString, idx)
|
return nil, fmt.Errorf("%v has an unexpected char at pos %v", tagString, idx)
|
||||||
} else {
|
|
||||||
quotes = true
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
quotes = true
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
if inKey {
|
if inKey {
|
||||||
key = append(key, r)
|
key = append(key, r)
|
||||||
@@ -104,12 +103,12 @@ func parseTagItems(tagString string, chr tagChars) map[string][]string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if quotes {
|
if quotes {
|
||||||
fail("%v is not quoted properly", tagString)
|
return nil, fmt.Errorf("%v is not quoted properly", tagString)
|
||||||
}
|
}
|
||||||
|
|
||||||
add()
|
add()
|
||||||
|
|
||||||
return d
|
return d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTagInfo(ft reflect.StructField) (string, tagChars) {
|
func getTagInfo(ft reflect.StructField) (string, tagChars) {
|
||||||
@@ -129,31 +128,39 @@ func tagSplitFn(r rune) bool {
|
|||||||
return r == ',' || r == ' '
|
return r == ',' || r == ' '
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseTagString(s string) *Tag {
|
func parseTagString(s string) (*Tag, error) {
|
||||||
t := &Tag{
|
items, err := parseTagItems(s, bareChars)
|
||||||
items: parseTagItems(s, bareChars),
|
|
||||||
}
|
|
||||||
err := hydrateTag(t, "", false)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fail("%s: %s", s, err)
|
return nil, err
|
||||||
}
|
}
|
||||||
return t
|
t := &Tag{
|
||||||
|
items: items,
|
||||||
|
}
|
||||||
|
err = hydrateTag(t, "", false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("%s: %s", s, err)
|
||||||
|
}
|
||||||
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseTag(parent reflect.Value, ft reflect.StructField) *Tag {
|
func parseTag(parent reflect.Value, ft reflect.StructField) (*Tag, error) {
|
||||||
if ft.Tag.Get("kong") == "-" {
|
if ft.Tag.Get("kong") == "-" {
|
||||||
t := newEmptyTag()
|
t := newEmptyTag()
|
||||||
t.Ignored = true
|
t.Ignored = true
|
||||||
return t
|
return t, nil
|
||||||
|
}
|
||||||
|
items, err := parseTagItems(getTagInfo(ft))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
t := &Tag{
|
t := &Tag{
|
||||||
items: parseTagItems(getTagInfo(ft)),
|
items: items,
|
||||||
}
|
}
|
||||||
err := hydrateTag(t, ft.Type.Name(), ft.Type.Kind() == reflect.Bool)
|
err = hydrateTag(t, ft.Type.Name(), ft.Type.Kind() == reflect.Bool)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
failField(parent, ft, "%s", err)
|
return nil, failField(parent, ft, "%s", err)
|
||||||
}
|
}
|
||||||
return t
|
return t, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func hydrateTag(t *Tag, typeName string, isBool bool) error {
|
func hydrateTag(t *Tag, typeName string, isBool bool) error {
|
||||||
|
|||||||
Reference in New Issue
Block a user