func validateClientGenTags(values map[string][]string) error {
	for _, k := range supportedTags {
		delete(values, k)
	}
	for key := range values {
		if strings.HasPrefix(key, strings.TrimSuffix(genClientPrefix, ":")) {
			return errors.New("unknown tag detected: " + key)
		}
	}
	return nil
}
validateTags validates that only supported genclient tags were provided.
package util
import (
	"errors"
	"fmt"
	"strings"
	"k8s.io/gengo/types"
)
var supportedTags = []string{
	"genclient",
	"genclient:nonNamespaced",
	"genclient:noVerbs",
	"genclient:onlyVerbs",
	"genclient:skipVerbs",
	"genclient:noStatus",
	"genclient:readonly",
	"genclient:method",
}
var SupportedVerbs = []string{
	"create",
	"update",
	"updateStatus",
	"delete",
	"deleteCollection",
	"get",
	"list",
	"watch",
	"patch",
}
var ReadonlyVerbs = []string{
	"get",
	"list",
	"watch",
}
const genClientPrefix = "genclient:"
var unsupportedExtensionVerbs = []string{
	"updateStatus",
	"deleteCollection",
	"watch",
	"delete",
}
var inputTypeSupportedVerbs = []string{
	"create",
	"update",
}
var resultTypeSupportedVerbs = []string{
	"create",
	"update",
	"get",
	"list",
	"patch",
}
type extension struct {
	VerbName string
	VerbType string
	SubResourcePath string
	InputTypeOverride string
	ResultTypeOverride string
}
func (e *extension) IsSubresource() bool {
	return len(e.SubResourcePath) > 0
}
func (e *extension) HasVerb(verb string) bool {
	return e.VerbType == verb
}
func (e *extension) Input() (string, string) {
	parts := strings.Split(e.InputTypeOverride, ".")
	return parts[len(parts)-1], strings.Join(parts[0:len(parts)-1], ".")
}
func (e *extension) Result() (string, string) {
	parts := strings.Split(e.ResultTypeOverride, ".")
	return parts[len(parts)-1], strings.Join(parts[0:len(parts)-1], ".")
}
type Tags struct {
	GenerateClient bool
	NonNamespaced bool
	NoStatus bool
	NoVerbs bool
	SkipVerbs []string
	Extensions []extension
}
func (t Tags) HasVerb(verb string) bool {
	if len(t.SkipVerbs) == 0 {
		return true
	}
	for _, s := range t.SkipVerbs {
		if verb == s {
			return false
		}
	}
	return true
}
func MustParseClientGenTags(lines []string) Tags {
	tags, err := ParseClientGenTags(lines)
	if err != nil {
		panic(err.Error())
	}
	return tags
}
func ParseClientGenTags(lines []string) (Tags, error) {
	ret := Tags{}
	values := types.ExtractCommentTags("+", lines)
	value := []string{}
	value, ret.GenerateClient = values["genclient"]
	if len(value) > 0 && len(value[0]) > 0 {
		return ret, fmt.Errorf("+genclient=%s is invalid, use //+genclient if you want to generate client or omit it when you want to disable generation", value)
	}
	_, ret.NonNamespaced = values[genClientPrefix+"nonNamespaced"]
	if value := values["nonNamespaced"]; len(value) > 0 && len(value[0]) > 0 {
		return ret, fmt.Errorf("+nonNamespaced=%s is invalid, use //+genclient:nonNamespaced instead", value[0])
	}
	_, ret.NoVerbs = values[genClientPrefix+"noVerbs"]
	_, ret.NoStatus = values[genClientPrefix+"noStatus"]
	onlyVerbs := []string{}
	if _, isReadonly := values[genClientPrefix+"readonly"]; isReadonly {
		onlyVerbs = ReadonlyVerbs
	}
	if value := values["readonly"]; len(value) > 0 && len(value[0]) > 0 {
		return ret, fmt.Errorf("+readonly=%s is invalid, use //+genclient:readonly instead", value[0])
	}
	if v, exists := values[genClientPrefix+"skipVerbs"]; exists {
		ret.SkipVerbs = strings.Split(v[0], ",")
	}
	if v, exists := values[genClientPrefix+"onlyVerbs"]; exists || len(onlyVerbs) > 0 {
		if len(v) > 0 {
			onlyVerbs = append(onlyVerbs, strings.Split(v[0], ",")...)
		}
		skipVerbs := []string{}
		for _, m := range SupportedVerbs {
			skip := true
			for _, o := range onlyVerbs {
				if o == m {
					skip = false
					break
				}
			}
			for _, v := range skipVerbs {
				if v == m {
					return ret, fmt.Errorf("verb %q used both in genclient:skipVerbs and genclient:onlyVerbs", v)
				}
			}
			if skip {
				skipVerbs = append(skipVerbs, m)
			}
		}
		ret.SkipVerbs = skipVerbs
	}
	var err error
	if ret.Extensions, err = parseClientExtensions(values); err != nil {
		return ret, err
	}
	return ret, validateClientGenTags(values)
}
func parseClientExtensions(tags map[string][]string) ([]extension, error) {
	var ret []extension
	for name, values := range tags {
		if !strings.HasPrefix(name, genClientPrefix+"method") {
			continue
		}
		for _, value := range values {
			ext := extension{}
			parts := strings.Split(value, ",")
			if len(parts) == 0 {
				return nil, fmt.Errorf("invalid of empty extension verb name: %q", value)
			}
			ext.VerbName = parts[0]
			if len(ext.VerbName) == 0 {
				return nil, fmt.Errorf("must specify a verb name (// +genclient:method=Foo,verb=create)")
			}
			params := parts[1:]
			for _, p := range params {
				parts := strings.Split(p, "=")
				if len(parts) != 2 {
					return nil, fmt.Errorf("invalid extension tag specification %q", p)
				}
				key, val := strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1])
				if len(val) == 0 {
					return nil, fmt.Errorf("empty value of %q for %q extension", key, ext.VerbName)
				}
				switch key {
				case "verb":
					ext.VerbType = val
				case "subresource":
					ext.SubResourcePath = val
				case "input":
					ext.InputTypeOverride = val
				case "result":
					ext.ResultTypeOverride = val
				default:
					return nil, fmt.Errorf("unknown extension configuration key %q", key)
				}
			}
			if len(ext.VerbType) == 0 {
				return nil, fmt.Errorf("verb type must be specified (use '// +genclient:method=%s,verb=create')", ext.VerbName)
			}
			if len(ext.ResultTypeOverride) > 0 {
				supported := false
				for _, v := range resultTypeSupportedVerbs {
					if ext.VerbType == v {
						supported = true
						break
					}
				}
				if !supported {
					return nil, fmt.Errorf("%s: result type is not supported for %q verbs (supported verbs: %#v)", ext.VerbName, ext.VerbType, resultTypeSupportedVerbs)
				}
			}
			if len(ext.InputTypeOverride) > 0 {
				supported := false
				for _, v := range inputTypeSupportedVerbs {
					if ext.VerbType == v {
						supported = true
						break
					}
				}
				if !supported {
					return nil, fmt.Errorf("%s: input type is not supported for %q verbs (supported verbs: %#v)", ext.VerbName, ext.VerbType, inputTypeSupportedVerbs)
				}
			}
			for _, t := range unsupportedExtensionVerbs {
				if ext.VerbType == t {
					return nil, fmt.Errorf("verb %q is not supported by extension generator", ext.VerbType)
				}
			}
			ret = append(ret, ext)
		}
	}
	return ret, nil
}