refact(deps): bump k8s and client-go deps to version v0.20.2 (#294)

Signed-off-by: prateekpandey14 <prateek.pandey@mayadata.io>
This commit is contained in:
Prateek Pandey 2021-03-31 16:43:42 +05:30 committed by GitHub
parent 533e17a9aa
commit b1aa6ab51a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2196 changed files with 306727 additions and 251810 deletions

5
vendor/k8s.io/gengo/args/args.go generated vendored
View file

@ -112,7 +112,7 @@ func (g *GeneratorArgs) LoadGoBoilerplate() ([]byte, error) {
if err != nil {
return nil, err
}
b = bytes.Replace(b, []byte("YEAR"), []byte(strconv.Itoa(time.Now().Year())), -1)
b = bytes.Replace(b, []byte("YEAR"), []byte(strconv.Itoa(time.Now().UTC().Year())), -1)
if g.GeneratedByCommentTemplate != "" {
if len(b) != 0 {
@ -159,6 +159,9 @@ func (g *GeneratorArgs) InputIncludes(p *types.Package) bool {
if strings.HasSuffix(d, "...") {
d = strings.TrimSuffix(d, "...")
}
if strings.HasPrefix(d, "./vendor/") {
d = strings.TrimPrefix(d, "./vendor/")
}
if strings.HasPrefix(p.Path, d) {
return true
}

View file

@ -29,7 +29,7 @@ import (
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
"k8s.io/klog"
"k8s.io/klog/v2"
)
// CustomArgs is used tby the go2idl framework to pass args specific to this

View file

@ -18,6 +18,7 @@ package generators
import (
"bytes"
"encoding/json"
"fmt"
"io"
"path/filepath"
@ -29,7 +30,7 @@ import (
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
"k8s.io/klog"
"k8s.io/klog/v2"
)
// CustomArgs is used tby the go2idl framework to pass args specific to this
@ -38,16 +39,45 @@ type CustomArgs struct {
ExtraPeerDirs []string // Always consider these as last-ditch possibilities for conversions.
}
var typeZeroValue = map[string]interface{}{
"uint": 0.,
"uint8": 0.,
"uint16": 0.,
"uint32": 0.,
"uint64": 0.,
"int": 0.,
"int8": 0.,
"int16": 0.,
"int32": 0.,
"int64": 0.,
"byte": 0,
"float64": 0.,
"float32": 0.,
"bool": false,
"time.Time": "",
"string": "",
"integer": 0.,
"number": 0.,
"boolean": false,
"[]byte": "", // base64 encoded characters
"interface{}": interface{}(nil),
}
// These are the comment tags that carry parameters for defaulter generation.
const tagName = "k8s:defaulter-gen"
const intputTagName = "k8s:defaulter-gen-input"
const inputTagName = "k8s:defaulter-gen-input"
const defaultTagName = "default"
func extractDefaultTag(comments []string) []string {
return types.ExtractCommentTags("+", comments)[defaultTagName]
}
func extractTag(comments []string) []string {
return types.ExtractCommentTags("+", comments)[tagName]
}
func extractInputTag(comments []string) []string {
return types.ExtractCommentTags("+", comments)[intputTagName]
return types.ExtractCommentTags("+", comments)[inputTagName]
}
func checkTag(comments []string, require ...string) bool {
@ -248,7 +278,11 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
shouldCreateObjectDefaulterFn := func(t *types.Type) bool {
if defaults, ok := existingDefaulters[t]; ok && defaults.object != nil {
// A default generator is defined
klog.V(5).Infof(" an object defaulter already exists as %s", defaults.base.Name)
baseTypeName := "<unknown>"
if defaults.base != nil {
baseTypeName = defaults.base.Name.String()
}
klog.V(5).Infof(" an object defaulter already exists as %s", baseTypeName)
return false
}
// opt-out
@ -397,6 +431,112 @@ func newCallTreeForType(existingDefaulters, newDefaulters defaulterFuncMap) *cal
}
}
func resolveTypeAndDepth(t *types.Type) (*types.Type, int) {
var prev *types.Type
depth := 0
for prev != t {
prev = t
if t.Kind == types.Alias {
t = t.Underlying
} else if t.Kind == types.Pointer {
t = t.Elem
depth += 1
}
}
return t, depth
}
// getNestedDefault returns the first default value when resolving alias types
func getNestedDefault(t *types.Type) string {
var prev *types.Type
for prev != t {
prev = t
defaultMap := extractDefaultTag(t.CommentLines)
if len(defaultMap) == 1 && defaultMap[0] != "" {
return defaultMap[0]
}
if t.Kind == types.Alias {
t = t.Underlying
} else if t.Kind == types.Pointer {
t = t.Elem
}
}
return ""
}
func mustEnforceDefault(t *types.Type, depth int, omitEmpty bool) (interface{}, error) {
if depth > 0 {
return nil, nil
}
switch t.Kind {
case types.Pointer, types.Map, types.Slice, types.Array, types.Interface:
return nil, nil
case types.Struct:
return map[string]interface{}{}, nil
case types.Builtin:
if !omitEmpty {
if zero, ok := typeZeroValue[t.String()]; ok {
return zero, nil
} else {
return nil, fmt.Errorf("please add type %v to typeZeroValue struct", t)
}
}
return nil, nil
default:
return nil, fmt.Errorf("not sure how to enforce default for %v", t.Kind)
}
}
func populateDefaultValue(node *callNode, t *types.Type, tags string, commentLines []string) *callNode {
defaultMap := extractDefaultTag(commentLines)
var defaultString string
if len(defaultMap) == 1 {
defaultString = defaultMap[0]
}
t, depth := resolveTypeAndDepth(t)
if depth > 0 && defaultString == "" {
defaultString = getNestedDefault(t)
}
if len(defaultMap) > 1 {
klog.Fatalf("Found more than one default tag for %v", t.Kind)
} else if len(defaultMap) == 0 {
return node
}
var defaultValue interface{}
if err := json.Unmarshal([]byte(defaultString), &defaultValue); err != nil {
klog.Fatalf("Failed to unmarshal default: %v", err)
}
omitEmpty := strings.Contains(reflect.StructTag(tags).Get("json"), "omitempty")
if enforced, err := mustEnforceDefault(t, depth, omitEmpty); err != nil {
klog.Fatal(err)
} else if enforced != nil {
if defaultValue != nil {
if reflect.DeepEqual(defaultValue, enforced) {
// If the default value annotation matches the default value for the type,
// do not generate any defaulting function
return node
} else {
enforcedJSON, _ := json.Marshal(enforced)
klog.Fatalf("Invalid default value (%#v) for non-pointer/non-omitempty. If specified, must be: %v", defaultValue, string(enforcedJSON))
}
}
}
// callNodes are not automatically generated for primitive types. Generate one if the callNode does not exist
if node == nil {
node = &callNode{}
node.markerOnly = true
}
node.defaultIsPrimitive = t.IsPrimitive()
node.defaultType = t.String()
node.defaultValue = defaultString
node.defaultDepth = depth
return node
}
// build creates a tree of paths to fields (based on how they would be accessed in Go - pointer, elem,
// slice, or key) and the functions that should be invoked on each field. An in-order traversal of the resulting tree
// can be used to generate a Go function that invokes each nested function on the appropriate type. The return
@ -469,12 +609,19 @@ func (c *callTreeForType) build(t *types.Type, root bool) *callNode {
child.elem = true
}
parent.children = append(parent.children, *child)
} else if member := populateDefaultValue(nil, t.Elem, "", t.Elem.CommentLines); member != nil {
member.index = true
parent.children = append(parent.children, *member)
}
case types.Map:
if child := c.build(t.Elem, false); child != nil {
child.key = true
parent.children = append(parent.children, *child)
} else if member := populateDefaultValue(nil, t.Elem, "", t.Elem.CommentLines); member != nil {
member.key = true
parent.children = append(parent.children, *member)
}
case types.Struct:
for _, field := range t.Members {
name := field.Name
@ -487,7 +634,11 @@ func (c *callTreeForType) build(t *types.Type, root bool) *callNode {
}
if child := c.build(field.Type, false); child != nil {
child.field = name
populateDefaultValue(child, field.Type, field.Tags, field.CommentLines)
parent.children = append(parent.children, *child)
} else if member := populateDefaultValue(nil, field.Type, field.Tags, field.CommentLines); member != nil {
member.field = name
parent.children = append(parent.children, *member)
}
}
case types.Alias:
@ -672,6 +823,27 @@ type callNode struct {
call []*types.Type
// children is the child call nodes that must also be traversed
children []callNode
// defaultValue is the defaultValue of a callNode struct
// Only primitive types and pointer types are eligible to have a default value
defaultValue string
// defaultIsPrimitive is used to determine how to assign the default value.
// Primitive types will be directly assigned while complex types will use JSON unmarshalling
defaultIsPrimitive bool
// markerOnly is true if the callNode exists solely to fill in a default value
markerOnly bool
// defaultDepth is used to determine pointer level of the default value
// For example 1 corresponds to setting a default value and taking its pointer while
// 2 corresponds to setting a default value and taking its pointer's pointer
// 0 implies that no pointers are used
defaultDepth int
// defaultType is the type of the default value.
// Only populated if defaultIsPrimitive is true
defaultType string
}
// CallNodeVisitorFunc is a function for visiting a call tree. ancestors is the list of all parents
@ -727,6 +899,85 @@ func (n *callNode) writeCalls(varName string, isVarPointer bool, sw *generator.S
}
}
func (n *callNode) writeDefaulter(varName string, index string, isVarPointer bool, sw *generator.SnippetWriter) {
if n.defaultValue == "" {
return
}
varPointer := varName
if !isVarPointer {
varPointer = "&" + varPointer
}
args := generator.Args{
"defaultValue": n.defaultValue,
"varPointer": varPointer,
"varName": varName,
"index": index,
"varDepth": n.defaultDepth,
"varType": n.defaultType,
}
if n.index {
sw.Do("if reflect.ValueOf($.var$[$.index$]).IsZero() {\n", generator.Args{"var": varName, "index": index})
if n.defaultIsPrimitive {
if n.defaultDepth > 0 {
sw.Do("var ptrVar$.varDepth$ $.varType$ = $.defaultValue$\n", args)
for i := n.defaultDepth; i > 0; i-- {
sw.Do("ptrVar$.ptri$ := &ptrVar$.i$\n", generator.Args{"i": fmt.Sprintf("%d", i), "ptri": fmt.Sprintf("%d", (i - 1))})
}
sw.Do("$.varName$[$.index$] = ptrVar0", args)
} else {
sw.Do("$.varName$[$.index$] = $.defaultValue$", args)
}
} else {
sw.Do("if err := json.Unmarshal([]byte(`$.defaultValue$`), $.varPointer$[$.index$]); err != nil {\n", args)
sw.Do("panic(err)\n", nil)
sw.Do("}\n", nil)
}
} else if n.key {
mapDefaultVar := index + "_default"
args["mapDefaultVar"] = mapDefaultVar
sw.Do("if reflect.ValueOf($.var$[$.index$]).IsZero() {\n", generator.Args{"var": varName, "index": index})
if n.defaultIsPrimitive {
if n.defaultDepth > 0 {
sw.Do("var ptrVar$.varDepth$ $.varType$ = $.defaultValue$\n", args)
for i := n.defaultDepth; i > 0; i-- {
sw.Do("ptrVar$.ptri$ := &ptrVar$.i$\n", generator.Args{"i": fmt.Sprintf("%d", i), "ptri": fmt.Sprintf("%d", (i - 1))})
}
sw.Do("$.varName$[$.index$] = ptrVar0", args)
} else {
sw.Do("$.varName$[$.index$] = $.defaultValue$", args)
}
} else {
sw.Do("$.mapDefaultVar$ := $.varName$[$.index$]\n", args)
sw.Do("if err := json.Unmarshal([]byte(`$.defaultValue$`), &$.mapDefaultVar$); err != nil {\n", args)
sw.Do("panic(err)\n", nil)
sw.Do("}\n", nil)
sw.Do("$.varName$[$.index$] = $.mapDefaultVar$\n", args)
}
} else {
sw.Do("if reflect.ValueOf($.var$).IsZero() {\n", generator.Args{"var": varName})
if n.defaultIsPrimitive {
if n.defaultDepth > 0 {
sw.Do("var ptrVar$.varDepth$ $.varType$ = $.defaultValue$\n", args)
for i := n.defaultDepth; i > 0; i-- {
sw.Do("ptrVar$.ptri$ := &ptrVar$.i$\n", generator.Args{"i": fmt.Sprintf("%d", i), "ptri": fmt.Sprintf("%d", (i - 1))})
}
sw.Do("$.varName$ = ptrVar0", args)
} else {
sw.Do("$.varName$ = $.defaultValue$", args)
}
} else {
sw.Do("if err := json.Unmarshal([]byte(`$.defaultValue$`), $.varPointer$); err != nil {\n", args)
sw.Do("panic(err)\n", nil)
sw.Do("}\n", nil)
}
}
sw.Do("}\n", nil)
}
// WriteMethod performs an in-order traversal of the calltree, generating loops and if blocks as necessary
// to correctly turn the call tree into a method body that invokes all calls on all child nodes of the call tree.
// Depth is used to generate local variables at the proper depth.
@ -754,19 +1005,31 @@ func (n *callNode) WriteMethod(varName string, depth int, ancestors []*callNode,
switch {
case n.index:
sw.Do("for $.index$ := range $.var$ {\n", vars)
if n.elem {
sw.Do("$.local$ := $.var$[$.index$]\n", vars)
} else {
sw.Do("$.local$ := &$.var$[$.index$]\n", vars)
if !n.markerOnly {
if n.elem {
sw.Do("$.local$ := $.var$[$.index$]\n", vars)
} else {
sw.Do("$.local$ := &$.var$[$.index$]\n", vars)
}
}
n.writeDefaulter(varName, index, isPointer, sw)
n.writeCalls(local, true, sw)
for i := range n.children {
n.children[i].WriteMethod(local, depth+1, append(ancestors, n), sw)
}
sw.Do("}\n", nil)
case n.key:
if n.defaultValue != "" {
// Map keys are typed and cannot share the same index variable as arrays and other maps
index = index + "_" + ancestors[len(ancestors)-1].field
vars["index"] = index
sw.Do("for $.index$ := range $.var$ {\n", vars)
n.writeDefaulter(varName, index, isPointer, sw)
sw.Do("}\n", nil)
}
default:
n.writeDefaulter(varName, index, isPointer, sw)
n.writeCalls(varName, isPointer, sw)
for i := range n.children {
n.children[i].WriteMethod(varName, depth, append(ancestors, n), sw)

View file

@ -33,11 +33,13 @@ import (
"k8s.io/gengo/generator"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
"sigs.k8s.io/yaml"
"k8s.io/klog"
"k8s.io/klog/v2"
)
const (
goModFile = "go.mod"
importBossFileType = "import-boss"
)
@ -58,7 +60,7 @@ func DefaultNameSystem() string {
func Packages(c *generator.Context, arguments *args.GeneratorArgs) generator.Packages {
pkgs := generator.Packages{}
c.FileTypes = map[string]generator.FileType{
importBossFileType: importRuleFile{},
importBossFileType: importRuleFile{c},
}
for _, p := range c.Universe {
@ -70,6 +72,7 @@ func Packages(c *generator.Context, arguments *args.GeneratorArgs) generator.Pac
pkgs = append(pkgs, &generator.DefaultPackage{
PackageName: p.Name,
PackagePath: p.Path,
Source: p.SourcePath,
// GeneratorFunc returns a list of generators. Each generator makes a
// single file.
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
@ -96,10 +99,19 @@ type Rule struct {
ForbiddenPrefixes []string
}
type InverseRule struct {
Rule
// True if the rule is to be applied to transitive imports.
Transitive bool
}
type fileFormat struct {
CurrentImports []string
Rules []Rule
Rules []Rule
InverseRules []InverseRule
path string
}
func readFile(path string) (*fileFormat, error) {
@ -109,10 +121,11 @@ func readFile(path string) (*fileFormat, error) {
}
var current fileFormat
err = json.Unmarshal(currentBytes, &current)
err = yaml.Unmarshal(currentBytes, &current)
if err != nil {
return nil, fmt.Errorf("couldn't unmarshal %v: %v", path, err)
}
current.path = path
return &current, nil
}
@ -131,10 +144,12 @@ func writeFile(path string, ff *fileFormat) error {
}
// This does the actual checking, since it knows the literal destination file.
type importRuleFile struct{}
type importRuleFile struct {
context *generator.Context
}
func (importRuleFile) AssembleFile(f *generator.File, path string) error {
return nil
func (irf importRuleFile) AssembleFile(f *generator.File, path string) error {
return irf.VerifyFile(f, path)
}
// TODO: make a flag to enable this, or expose this information in some other way.
@ -169,62 +184,99 @@ func removeLastDir(path string) (newPath, removedDir string) {
return filepath.Join(filepath.Dir(dir), file), filepath.Base(dir)
}
// Keep going up a directory until we find an .import-restrictions file.
func recursiveRead(path string) (*fileFormat, string, error) {
// isGoModRoot checks if a directory is the root directory for a package
// by checking for the existence of a 'go.mod' file in that directory.
func isGoModRoot(path string) bool {
_, err := os.Stat(filepath.Join(filepath.Dir(path), goModFile))
return err == nil
}
// recursiveRead collects all '.import-restriction' files, between the current directory,
// and the package root when Go modules are enabled, or $GOPATH/src when they are not.
func recursiveRead(path string) ([]*fileFormat, error) {
restrictionFiles := make([]*fileFormat, 0)
for {
if _, err := os.Stat(path); err == nil {
ff, err := readFile(path)
return ff, path, err
rules, err := readFile(path)
if err != nil {
return nil, err
}
restrictionFiles = append(restrictionFiles, rules)
}
nextPath, removedDir := removeLastDir(path)
if nextPath == path || removedDir == "src" {
if nextPath == path || isGoModRoot(path) || removedDir == "src" {
break
}
path = nextPath
}
return nil, "", nil
return restrictionFiles, nil
}
func (importRuleFile) VerifyFile(f *generator.File, path string) error {
rules, actualPath, err := recursiveRead(path)
func (irf importRuleFile) VerifyFile(f *generator.File, path string) error {
restrictionFiles, err := recursiveRead(filepath.Join(f.PackageSourcePath, f.Name))
if err != nil {
return fmt.Errorf("error finding rules file: %v", err)
}
if rules == nil {
// No restrictions on this directory.
return nil
if err := irf.verifyRules(restrictionFiles, f); err != nil {
return err
}
return irf.verifyInverseRules(restrictionFiles, f)
}
func (irf importRuleFile) verifyRules(restrictionFiles []*fileFormat, f *generator.File) error {
selectors := make([][]*regexp.Regexp, len(restrictionFiles))
for i, restrictionFile := range restrictionFiles {
for _, r := range restrictionFile.Rules {
re, err := regexp.Compile(r.SelectorRegexp)
if err != nil {
return fmt.Errorf("regexp `%s` in file %q doesn't compile: %v", r.SelectorRegexp, restrictionFile.path, err)
}
selectors[i] = append(selectors[i], re)
}
}
forbiddenImports := map[string]string{}
allowedMismatchedImports := []string{}
for _, r := range rules.Rules {
re, err := regexp.Compile(r.SelectorRegexp)
if err != nil {
return fmt.Errorf("regexp `%s` in file %q doesn't compile: %v", r.SelectorRegexp, actualPath, err)
}
for v := range f.Imports {
klog.V(4).Infof("Checking %v matches %v: %v\n", r.SelectorRegexp, v, re.MatchString(v))
if !re.MatchString(v) {
continue
}
for _, forbidden := range r.ForbiddenPrefixes {
klog.V(4).Infof("Checking %v against %v\n", v, forbidden)
if strings.HasPrefix(v, forbidden) {
forbiddenImports[v] = forbidden
for v := range f.Imports {
explicitlyAllowed := false
NextRestrictionFiles:
for i, rules := range restrictionFiles {
for j, r := range rules.Rules {
matching := selectors[i][j].MatchString(v)
klog.V(5).Infof("Checking %v matches %v: %v\n", r.SelectorRegexp, v, matching)
if !matching {
continue
}
}
found := false
for _, allowed := range r.AllowedPrefixes {
klog.V(4).Infof("Checking %v against %v\n", v, allowed)
if strings.HasPrefix(v, allowed) {
found = true
break
for _, forbidden := range r.ForbiddenPrefixes {
klog.V(4).Infof("Checking %v against %v\n", v, forbidden)
if strings.HasPrefix(v, forbidden) {
forbiddenImports[v] = forbidden
}
}
for _, allowed := range r.AllowedPrefixes {
klog.V(4).Infof("Checking %v against %v\n", v, allowed)
if strings.HasPrefix(v, allowed) {
explicitlyAllowed = true
break
}
}
if !explicitlyAllowed {
allowedMismatchedImports = append(allowedMismatchedImports, v)
} else {
klog.V(2).Infof("%v importing %v allowed by %v\n", f.PackagePath, v, restrictionFiles[i].path)
break NextRestrictionFiles
}
}
if !found {
allowedMismatchedImports = append(allowedMismatchedImports, v)
}
}
}
@ -243,8 +295,85 @@ func (importRuleFile) VerifyFile(f *generator.File, path string) error {
}
return errors.New(errorBuilder.String())
}
if len(rules.Rules) > 0 {
klog.V(2).Infof("%v passes rules found in %v\n", path, actualPath)
return nil
}
// verifyInverseRules checks that all packages that import a package are allowed to import it.
func (irf importRuleFile) verifyInverseRules(restrictionFiles []*fileFormat, f *generator.File) error {
// compile all Selector regex in all restriction files
selectors := make([][]*regexp.Regexp, len(restrictionFiles))
for i, restrictionFile := range restrictionFiles {
for _, r := range restrictionFile.InverseRules {
re, err := regexp.Compile(r.SelectorRegexp)
if err != nil {
return fmt.Errorf("regexp `%s` in file %q doesn't compile: %v", r.SelectorRegexp, restrictionFile.path, err)
}
selectors[i] = append(selectors[i], re)
}
}
directImport := map[string]bool{}
for _, imp := range irf.context.IncomingImports()[f.PackagePath] {
directImport[imp] = true
}
forbiddenImports := map[string]string{}
allowedMismatchedImports := []string{}
for _, v := range irf.context.TransitiveIncomingImports()[f.PackagePath] {
explicitlyAllowed := false
NextRestrictionFiles:
for i, rules := range restrictionFiles {
for j, r := range rules.InverseRules {
if !r.Transitive && !directImport[v] {
continue
}
re := selectors[i][j]
matching := re.MatchString(v)
klog.V(4).Infof("Checking %v matches %v (importing %v: %v\n", r.SelectorRegexp, v, f.PackagePath, matching)
if !matching {
continue
}
for _, forbidden := range r.ForbiddenPrefixes {
klog.V(4).Infof("Checking %v against %v\n", v, forbidden)
if strings.HasPrefix(v, forbidden) {
forbiddenImports[v] = forbidden
}
}
for _, allowed := range r.AllowedPrefixes {
klog.V(4).Infof("Checking %v against %v\n", v, allowed)
if strings.HasPrefix(v, allowed) {
explicitlyAllowed = true
break
}
}
if !explicitlyAllowed {
allowedMismatchedImports = append(allowedMismatchedImports, v)
} else {
klog.V(2).Infof("%v importing %v allowed by %v\n", v, f.PackagePath, restrictionFiles[i].path)
break NextRestrictionFiles
}
}
}
}
if len(forbiddenImports) > 0 || len(allowedMismatchedImports) > 0 {
var errorBuilder strings.Builder
for i, f := range forbiddenImports {
fmt.Fprintf(&errorBuilder, "(inverse): import %v has forbidden prefix %v\n", i, f)
}
if len(allowedMismatchedImports) > 0 {
sort.Sort(sort.StringSlice(allowedMismatchedImports))
fmt.Fprintf(&errorBuilder, "(inverse): the following imports did not match any allowed prefix:\n")
for _, i := range allowedMismatchedImports {
fmt.Fprintf(&errorBuilder, " %v\n", i)
}
}
return errors.New(errorBuilder.String())
}
return nil

View file

@ -25,7 +25,7 @@ import (
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
"k8s.io/klog"
"k8s.io/klog/v2"
)
// NameSystems returns the name system used by the generators in this package.
@ -187,7 +187,7 @@ type $.type|public$ map[$.type|raw$]Empty
// New$.type|public$ creates a $.type|public$ from a list of values.
func New$.type|public$(items ...$.type|raw$) $.type|public$ {
ss := $.type|public${}
ss := make($.type|public$, len(items))
ss.Insert(items...)
return ss
}

View file

@ -18,7 +18,7 @@ package generators
import (
"k8s.io/gengo/types"
"k8s.io/klog"
"k8s.io/klog/v2"
)
// extractBoolTagOrDie gets the comment-tags for the key and asserts that, if

View file

@ -28,7 +28,7 @@ type Byte map[byte]Empty
// NewByte creates a Byte from a list of values.
func NewByte(items ...byte) Byte {
ss := Byte{}
ss := make(Byte, len(items))
ss.Insert(items...)
return ss
}

View file

@ -28,7 +28,7 @@ type Int map[int]Empty
// NewInt creates a Int from a list of values.
func NewInt(items ...int) Int {
ss := Int{}
ss := make(Int, len(items))
ss.Insert(items...)
return ss
}

View file

@ -28,7 +28,7 @@ type Int64 map[int64]Empty
// NewInt64 creates a Int64 from a list of values.
func NewInt64(items ...int64) Int64 {
ss := Int64{}
ss := make(Int64, len(items))
ss.Insert(items...)
return ss
}

View file

@ -28,7 +28,7 @@ type String map[string]Empty
// NewString creates a String from a list of values.
func NewString(items ...string) String {
ss := String{}
ss := make(String, len(items))
ss.Insert(items...)
return ss
}

View file

@ -26,6 +26,8 @@ type DefaultPackage struct {
PackageName string
// Import path of the package, and the location on disk of the package.
PackagePath string
// The location of the package on disk.
Source string
// Emitted at the top of every file.
HeaderText []byte
@ -43,8 +45,9 @@ type DefaultPackage struct {
FilterFunc func(*Context, *types.Type) bool
}
func (d *DefaultPackage) Name() string { return d.PackageName }
func (d *DefaultPackage) Path() string { return d.PackagePath }
func (d *DefaultPackage) Name() string { return d.PackageName }
func (d *DefaultPackage) Path() string { return d.PackagePath }
func (d *DefaultPackage) SourcePath() string { return d.Source }
func (d *DefaultPackage) Filter(c *Context, t *types.Type) bool {
if d.FilterFunc != nil {

View file

@ -29,7 +29,7 @@ import (
"k8s.io/gengo/namer"
"k8s.io/gengo/types"
"k8s.io/klog"
"k8s.io/klog/v2"
)
func errs2strings(errors []error) []string {
@ -233,11 +233,13 @@ func (c *Context) ExecutePackage(outDir string, p Package) error {
if f == nil {
// This is the first generator to reference this file, so start it.
f = &File{
Name: g.Filename(),
FileType: fileType,
PackageName: p.Name(),
Header: p.Header(g.Filename()),
Imports: map[string]struct{}{},
Name: g.Filename(),
FileType: fileType,
PackageName: p.Name(),
PackagePath: p.Path(),
PackageSourcePath: p.SourcePath(),
Header: p.Header(g.Filename()),
Imports: map[string]struct{}{},
}
files[f.Name] = f
} else {

View file

@ -31,6 +31,8 @@ type Package interface {
Name() string
// Path returns the package import path.
Path() string
// SourcePath returns the location of the package on disk.
SourcePath() string
// Filter should return true if this package cares about this type.
// Otherwise, this type will be omitted from the type ordering for
@ -50,14 +52,16 @@ type Package interface {
}
type File struct {
Name string
FileType string
PackageName string
Header []byte
Imports map[string]struct{}
Vars bytes.Buffer
Consts bytes.Buffer
Body bytes.Buffer
Name string
FileType string
PackageName string
Header []byte
PackagePath string
PackageSourcePath string
Imports map[string]struct{}
Vars bytes.Buffer
Consts bytes.Buffer
Body bytes.Buffer
}
type FileType interface {
@ -156,6 +160,12 @@ type Context struct {
// All the types, in case you want to look up something.
Universe types.Universe
// Incoming imports, i.e. packages importing the given package.
incomingImports map[string][]string
// Incoming transitive imports, i.e. the transitive closure of IncomingImports
incomingTransitiveImports map[string][]string
// All the user-specified packages. This is after recursive expansion.
Inputs []string
@ -203,11 +213,36 @@ func NewContext(b *parser.Builder, nameSystems namer.NameSystems, canonicalOrder
return c, nil
}
// IncomingImports returns the incoming imports for each package. The map is lazily computed.
func (ctxt *Context) IncomingImports() map[string][]string {
if ctxt.incomingImports == nil {
incoming := map[string][]string{}
for _, pkg := range ctxt.Universe {
for imp := range pkg.Imports {
incoming[imp] = append(incoming[imp], pkg.Path)
}
}
ctxt.incomingImports = incoming
}
return ctxt.incomingImports
}
// TransitiveIncomingImports returns the transitive closure of the incoming imports for each package.
// The map is lazily computed.
func (ctxt *Context) TransitiveIncomingImports() map[string][]string {
if ctxt.incomingTransitiveImports == nil {
ctxt.incomingTransitiveImports = transitiveClosure(ctxt.IncomingImports())
}
return ctxt.incomingTransitiveImports
}
// AddDir adds a Go package to the context. The specified path must be a single
// go package import path. GOPATH, GOROOT, and the location of your go binary
// (`which go`) will all be searched, in the normal Go fashion.
// Deprecated. Please use AddDirectory.
func (ctxt *Context) AddDir(path string) error {
ctxt.incomingImports = nil
ctxt.incomingTransitiveImports = nil
return ctxt.builder.AddDirTo(path, &ctxt.Universe)
}
@ -215,5 +250,7 @@ func (ctxt *Context) AddDir(path string) error {
// single go package import path. GOPATH, GOROOT, and the location of your go
// binary (`which go`) will all be searched, in the normal Go fashion.
func (ctxt *Context) AddDirectory(path string) (*types.Package, error) {
ctxt.incomingImports = nil
ctxt.incomingTransitiveImports = nil
return ctxt.builder.AddDirectoryTo(path, &ctxt.Universe)
}

View file

@ -20,7 +20,7 @@ import (
"go/token"
"strings"
"k8s.io/klog"
"k8s.io/klog/v2"
"k8s.io/gengo/namer"
"k8s.io/gengo/types"

View file

@ -57,7 +57,7 @@ func NewSnippetWriter(w io.Writer, c *Context, left, right string) *SnippetWrite
// Do parses format and runs args through it. You can have arbitrary logic in
// the format (see the text/template documentation), but consider running many
// short templaces, with ordinary go logic in between--this may be more
// short templates with ordinary go logic in between--this may be more
// readable. Do is chainable. Any error causes every other call to do to be
// ignored, and the error will be returned by Error(). So you can check it just
// once, at the end of your function.

65
vendor/k8s.io/gengo/generator/transitive_closure.go generated vendored Normal file
View file

@ -0,0 +1,65 @@
/*
Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package generator
import "sort"
type edge struct {
from string
to string
}
func transitiveClosure(in map[string][]string) map[string][]string {
adj := make(map[edge]bool)
imports := make(map[string]struct{})
for from, tos := range in {
for _, to := range tos {
adj[edge{from, to}] = true
imports[to] = struct{}{}
}
}
// Warshal's algorithm
for k := range in {
for i := range in {
if !adj[edge{i, k}] {
continue
}
for j := range imports {
if adj[edge{i, j}] {
continue
}
if adj[edge{k, j}] {
adj[edge{i, j}] = true
}
}
}
}
out := make(map[string][]string, len(in))
for i := range in {
for j := range imports {
if adj[edge{i, j}] {
out[i] = append(out[i], j)
}
}
sort.Strings(out[i])
}
return out
}

3
vendor/k8s.io/gengo/namer/order.go generated vendored
View file

@ -43,6 +43,9 @@ func (o *Orderer) OrderUniverse(u types.Universe) []*types.Type {
for _, v := range p.Variables {
list.types = append(list.types, v)
}
for _, v := range p.Constants {
list.types = append(list.types, v)
}
}
sort.Sort(list)
return list.types

View file

@ -22,7 +22,7 @@ import (
"k8s.io/gengo/types"
)
var consonants = "bcdfghjklmnpqrsttvwxyz"
var consonants = "bcdfghjklmnpqrstvwxyz"
type pluralNamer struct {
// key is the case-sensitive type name, value is the case-insensitive

75
vendor/k8s.io/gengo/parser/parse.go generated vendored
View file

@ -20,6 +20,7 @@ import (
"fmt"
"go/ast"
"go/build"
"go/constant"
"go/parser"
"go/token"
tc "go/types"
@ -28,11 +29,12 @@ import (
"os/exec"
"path"
"path/filepath"
"regexp"
"sort"
"strings"
"k8s.io/gengo/types"
"k8s.io/klog"
"k8s.io/klog/v2"
)
// This clarifies when a pkg path has been canonicalized.
@ -227,12 +229,16 @@ func (b *Builder) AddDirRecursive(dir string) error {
klog.Warningf("Ignoring directory %v: %v", dir, err)
}
// filepath.Walk includes the root dir, but we already did that, so we'll
// remove that prefix and rebuild a package import path.
prefix := b.buildPackages[dir].Dir
// filepath.Walk does not follow symlinks. We therefore evaluate symlinks and use that with
// filepath.Walk.
realPath, err := filepath.EvalSymlinks(b.buildPackages[dir].Dir)
if err != nil {
return err
}
fn := func(filePath string, info os.FileInfo, err error) error {
if info != nil && info.IsDir() {
rel := filepath.ToSlash(strings.TrimPrefix(filePath, prefix))
rel := filepath.ToSlash(strings.TrimPrefix(filePath, realPath))
if rel != "" {
// Make a pkg path.
pkg := path.Join(string(canonicalizeImportPath(b.buildPackages[dir].ImportPath)), rel)
@ -245,7 +251,7 @@ func (b *Builder) AddDirRecursive(dir string) error {
}
return nil
}
if err := filepath.Walk(b.buildPackages[dir].Dir, fn); err != nil {
if err := filepath.Walk(realPath, fn); err != nil {
return err
}
return nil
@ -330,6 +336,13 @@ func (b *Builder) addDir(dir string, userRequested bool) error {
return nil
}
// regexErrPackageNotFound helps test the expected error for not finding a package.
var regexErrPackageNotFound = regexp.MustCompile(`^unable to import ".*?":.*`)
func isErrPackageNotFound(err error) bool {
return regexErrPackageNotFound.MatchString(err.Error())
}
// importPackage is a function that will be called by the type check package when it
// needs to import a go package. 'path' is the import path.
func (b *Builder) importPackage(dir string, userRequested bool) (*tc.Package, error) {
@ -352,6 +365,11 @@ func (b *Builder) importPackage(dir string, userRequested bool) (*tc.Package, er
// Add it.
if err := b.addDir(dir, userRequested); err != nil {
if isErrPackageNotFound(err) {
klog.V(6).Info(err)
return nil, nil
}
return nil, err
}
@ -544,6 +562,10 @@ func (b *Builder) findTypesIn(pkgPath importPathString, u *types.Universe) error
if ok && !tv.IsField() {
b.addVariable(*u, nil, tv)
}
tconst, ok := obj.(*tc.Const)
if ok {
b.addConstant(*u, nil, tconst)
}
}
importedPkgs := []string{}
@ -569,7 +591,7 @@ func (b *Builder) importWithMode(dir string, mode build.ImportMode) (*build.Pack
if err != nil {
return nil, fmt.Errorf("unable to get current directory: %v", err)
}
buildPkg, err := b.context.Import(dir, cwd, mode)
buildPkg, err := b.context.Import(filepath.ToSlash(dir), cwd, mode)
if err != nil {
return nil, err
}
@ -742,7 +764,11 @@ func (b *Builder) walkType(u types.Universe, useName *types.Name, in tc.Type) *t
if out.Methods == nil {
out.Methods = map[string]*types.Type{}
}
out.Methods[t.Method(i).Name()] = b.walkType(u, nil, t.Method(i).Type())
method := t.Method(i)
name := tcNameToName(method.String())
mt := b.walkType(u, &name, method.Type())
mt.CommentLines = splitLines(b.priorCommentLines(method.Pos(), 1).Text())
out.Methods[method.Name()] = mt
}
return out
case *tc.Named:
@ -774,7 +800,11 @@ func (b *Builder) walkType(u types.Universe, useName *types.Name, in tc.Type) *t
if out.Methods == nil {
out.Methods = map[string]*types.Type{}
}
out.Methods[t.Method(i).Name()] = b.walkType(u, nil, t.Method(i).Type())
method := t.Method(i)
name := tcNameToName(method.String())
mt := b.walkType(u, &name, method.Type())
mt.CommentLines = splitLines(b.priorCommentLines(method.Pos(), 1).Text())
out.Methods[method.Name()] = mt
}
}
return out
@ -811,6 +841,33 @@ func (b *Builder) addVariable(u types.Universe, useName *types.Name, in *tc.Var)
return out
}
func (b *Builder) addConstant(u types.Universe, useName *types.Name, in *tc.Const) *types.Type {
name := tcVarNameToName(in.String())
if useName != nil {
name = *useName
}
out := u.Constant(name)
out.Kind = types.DeclarationOf
out.Underlying = b.walkType(u, nil, in.Type())
var constval string
// For strings, we use `StringVal()` to get the un-truncated,
// un-quoted string. For other values, `.String()` is preferable to
// get something relatively human readable (especially since for
// floating point types, `ExactString()` will generate numeric
// expressions using `big.(*Float).Text()`.
switch in.Val().Kind() {
case constant.String:
constval = constant.StringVal(in.Val())
default:
constval = in.Val().String()
}
out.ConstValue = &constval
return out
}
// canonicalizeImportPath takes an import path and returns the actual package.
// It doesn't support nested vendoring.
func canonicalizeImportPath(importPath string) importPathString {

34
vendor/k8s.io/gengo/types/types.go generated vendored
View file

@ -135,6 +135,10 @@ type Package struct {
// package name).
Variables map[string]*Type
// Global constants within this package, indexed by their name (*not* including
// package name).
Constants map[string]*Type
// Packages imported by this package, indexed by (canonicalized)
// package path.
Imports map[string]*Package
@ -193,6 +197,20 @@ func (p *Package) Variable(varName string) *Type {
return t
}
// Constant gets the given constant Type in this Package. If the constant is
// not already defined, this will add it. If a constant is added, it's the caller's
// responsibility to finish construction of the constant by setting Underlying
// to the correct type.
func (p *Package) Constant(constName string) *Type {
if t, ok := p.Constants[constName]; ok {
return t
}
t := &Type{Name: Name{Package: p.Path, Name: constName}}
t.Kind = DeclarationOf
p.Constants[constName] = t
return t
}
// HasImport returns true if p imports packageName. Package names include the
// package directory.
func (p *Package) HasImport(packageName string) bool {
@ -229,6 +247,14 @@ func (u Universe) Variable(n Name) *Type {
return u.Package(n.Package).Variable(n.Name)
}
// Constant returns the canonical constant for the given fully-qualified name.
// If a non-existing constant is requested, this will create (a marker for) it.
// If a marker is created, it's the caller's responsibility to finish
// construction of the constant by setting Underlying to the correct type.
func (u Universe) Constant(n Name) *Type {
return u.Package(n.Package).Constant(n.Name)
}
// AddImports registers import lines for packageName. May be called multiple times.
// You are responsible for canonicalizing all package paths.
func (u Universe) AddImports(packagePath string, importPaths ...string) {
@ -251,6 +277,7 @@ func (u Universe) Package(packagePath string) *Package {
Types: map[string]*Type{},
Functions: map[string]*Type{},
Variables: map[string]*Type{},
Constants: map[string]*Type{},
Imports: map[string]*Package{},
}
u[packagePath] = p
@ -314,6 +341,13 @@ type Type struct {
// If Kind == func, this is the signature of the function.
Signature *Signature
// ConstValue contains a stringified constant value if
// Kind == DeclarationOf and this is a constant value
// declaration. For string constants, this field contains
// the entire, un-quoted value. For other types, it contains
// a human-readable literal.
ConstValue *string
// TODO: Add:
// * channel direction
// * array length