Skip to content

Commit

Permalink
Merge pull request #54 from caesarxuchao/fix-defaut-gen
Browse files Browse the repository at this point in the history
Default-gen changes for moving API types to k8s.io/api
  • Loading branch information
lavalamp authored May 31, 2017
2 parents 57e5dee + e9953d1 commit c79c13d
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 10 deletions.
48 changes: 38 additions & 10 deletions examples/defaulter-gen/generators/defaulter.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,18 @@ type CustomArgs struct {
ExtraPeerDirs []string // Always consider these as last-ditch possibilities for conversions.
}

// This is the comment tag that carries parameters for defaulter generation.
// These are the comment tags that carry parameters for defaulter generation.
const tagName = "k8s:defaulter-gen"
const intputTagName = "k8s:defaulter-gen-input"

func extractTag(comments []string) []string {
return types.ExtractCommentTags("+", comments)[tagName]
}

func extractInputTag(comments []string) []string {
return types.ExtractCommentTags("+", comments)[intputTagName]
}

func checkTag(comments []string, require ...string) bool {
values := types.ExtractCommentTags("+", comments)[tagName]
if len(require) == 0 {
Expand Down Expand Up @@ -220,6 +225,11 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
// If the input had no Go files, for example.
continue
}
// typesPkg is where the types that needs defaulter are defined.
// Sometimes it is different from pkg. For example, kubernetes core/v1
// types are defined in vendor/k8s.io/api/core/v1, while pkg is at
// pkg/api/v1.
typesPkg := pkg

// Add defaulting functions.
getManualDefaultingFunctions(context, pkg, existingDefaulters)
Expand Down Expand Up @@ -271,8 +281,24 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
return false
}

// if the types are not in the same package where the defaulter functions to be generated
inputTags := extractInputTag(pkg.Comments)
if len(inputTags) > 1 {
panic(fmt.Sprintf("there could only be one input tag, got %#v", inputTags))
}
if len(inputTags) == 1 {
var err error
typesPkg, err = context.AddDirectory(filepath.Join(pkg.Path, inputTags[0]))
if err != nil {
glog.Fatalf("cannot import package %s", inputTags[0])
}
// update context.Order to the latest context.Universe
orderer := namer.Orderer{Namer: namer.NewPublicNamer(1)}
context.Order = orderer.OrderUniverse(context.Universe)
}

newDefaulters := defaulterFuncMap{}
for _, t := range pkg.Types {
for _, t := range typesPkg.Types {
if !shouldCreateObjectDefaulterFn(t) {
continue
}
Expand Down Expand Up @@ -350,11 +376,11 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
HeaderText: header,
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
return []generator.Generator{
NewGenDefaulter(arguments.OutputFileBaseName, pkg.Path, existingDefaulters, newDefaulters, peerPkgs),
NewGenDefaulter(arguments.OutputFileBaseName, typesPkg.Path, pkg.Path, existingDefaulters, newDefaulters, peerPkgs),
}
},
FilterFunc: func(c *generator.Context, t *types.Type) bool {
return t.Name.Package == pkg.Path
return t.Name.Package == typesPkg.Path
},
})
}
Expand Down Expand Up @@ -457,20 +483,22 @@ const (
// genDefaulter produces a file with a autogenerated conversions.
type genDefaulter struct {
generator.DefaultGen
targetPackage string
typesPackage string
outputPackage string
peerPackages []string
newDefaulters defaulterFuncMap
existingDefaulters defaulterFuncMap
imports namer.ImportTracker
typesForInit []*types.Type
}

func NewGenDefaulter(sanitizedName, targetPackage string, existingDefaulters, newDefaulters defaulterFuncMap, peerPkgs []string) generator.Generator {
func NewGenDefaulter(sanitizedName, typesPackage, outputPackage string, existingDefaulters, newDefaulters defaulterFuncMap, peerPkgs []string) generator.Generator {
return &genDefaulter{
DefaultGen: generator.DefaultGen{
OptionalName: sanitizedName,
},
targetPackage: targetPackage,
typesPackage: typesPackage,
outputPackage: outputPackage,
peerPackages: peerPkgs,
newDefaulters: newDefaulters,
existingDefaulters: existingDefaulters,
Expand All @@ -482,15 +510,15 @@ func NewGenDefaulter(sanitizedName, targetPackage string, existingDefaulters, ne
func (g *genDefaulter) Namers(c *generator.Context) namer.NameSystems {
// Have the raw namer for this file track what it imports.
return namer.NameSystems{
"raw": namer.NewRawNamer(g.targetPackage, g.imports),
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
}
}

func (g *genDefaulter) isOtherPackage(pkg string) bool {
if pkg == g.targetPackage {
if pkg == g.outputPackage {
return false
}
if strings.HasSuffix(pkg, `"`+g.targetPackage+`"`) {
if strings.HasSuffix(pkg, `"`+g.outputPackage+`"`) {
return false
}
return true
Expand Down
8 changes: 8 additions & 0 deletions generator/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,14 @@ func NewContext(b *parser.Builder, nameSystems namer.NameSystems, canonicalOrder
// 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 {
return ctxt.builder.AddDirTo(path, &ctxt.Universe)
}

// AddDirectory 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.
func (ctxt *Context) AddDirectory(path string) (*types.Package, error) {
return ctxt.builder.AddDirectoryTo(path, &ctxt.Universe)
}
19 changes: 19 additions & 0 deletions parser/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ func (b *Builder) AddDirRecursive(dir string) error {
// generator (rather than just at init time. 'dir' must be a single go package.
// GOPATH, GOROOT, and the location of your go binary (`which go`) will all be
// searched if dir doesn't literally resolve.
// Deprecated. Please use AddDirectoryTo.
func (b *Builder) AddDirTo(dir string, u *types.Universe) error {
// We want all types from this package, as if they were directly added
// by the user. They WERE added by the user, in effect.
Expand All @@ -260,6 +261,24 @@ func (b *Builder) AddDirTo(dir string, u *types.Universe) error {
return b.findTypesIn(canonicalizeImportPath(b.buildPackages[dir].ImportPath), u)
}

// AddDirectoryTo adds an entire directory to a given Universe. Unlike AddDir,
// this processes the package immediately, which makes it safe to use from
// within a generator (rather than just at init time. 'dir' must be a single go
// package. GOPATH, GOROOT, and the location of your go binary (`which go`)
// will all be searched if dir doesn't literally resolve.
func (b *Builder) AddDirectoryTo(dir string, u *types.Universe) (*types.Package, error) {
// We want all types from this package, as if they were directly added
// by the user. They WERE added by the user, in effect.
if _, err := b.importPackage(dir, true); err != nil {
return nil, err
}
path := canonicalizeImportPath(b.buildPackages[dir].ImportPath)
if err := b.findTypesIn(path, u); err != nil {
return nil, err
}
return u.Package(string(path)), nil
}

// The implementation of AddDir. A flag indicates whether this directory was
// user-requested or just from following the import graph.
func (b *Builder) addDir(dir string, userRequested bool) error {
Expand Down

0 comments on commit c79c13d

Please # to comment.