// Packages makes the import-boss package definition. func Packages(c *generator.Context, arguments *args.GeneratorArgs) generator.Packages { pkgs := generator.Packages{} c.FileTypes = map[string]generator.FileType{ importBossFileType: importRuleFile{}, } for _, p := range c.Universe { if !arguments.InputIncludes(p) { // Don't run on e.g. third party dependencies. continue } savedPackage := p pkgs = append(pkgs, &generator.DefaultPackage{ PackageName: p.Name, PackagePath: p.Path, // GeneratorFunc returns a list of generators. Each generator makes a // single file. GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { return []generator.Generator{&importRules{ myPackage: savedPackage, }} }, FilterFunc: func(c *generator.Context, t *types.Type) bool { return false }, }) } return pkgs }
func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages { boilerplate, err := arguments.LoadGoBoilerplate() if err != nil { glog.Fatalf("Failed loading boilerplate: %v", err) } header := append([]byte(fmt.Sprintf("// +build !%s\n\n", arguments.GeneratedBuildTag)), boilerplate...) header = append(header, []byte( ` // This file was autogenerated by openapi-gen. Do not edit it manually! `)...) if err := context.AddDir(arguments.OutputPackagePath); err != nil { glog.Fatalf("Failed to load output package: %v", err) } pkg := context.Universe[arguments.OutputPackagePath] if pkg == nil { glog.Fatalf("Got nil output package: %v", err) } return generator.Packages{ &generator.DefaultPackage{ PackageName: strings.Split(filepath.Base(pkg.Path), ".")[0], PackagePath: pkg.Path, HeaderText: header, GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { return []generator.Generator{NewOpenAPIGen(arguments.OutputFileBaseName, pkg, context)} }, FilterFunc: func(c *generator.Context, t *types.Type) bool { // There is a conflict between this codegen and codecgen, we should avoid types generated for codecgen if strings.HasPrefix(t.Name.Name, "codecSelfer") { return false } pkg := context.Universe.Package(t.Name.Package) if hasOpenAPITagValue(pkg.Comments, tagValueTrue) { return !hasOpenAPITagValue(t.CommentLines, tagValueFalse) } if hasOpenAPITagValue(t.CommentLines, tagValueTrue) { return true } return false }, }, } }
func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages { boilerplate, err := arguments.LoadGoBoilerplate() if err != nil { glog.Fatalf("Failed loading boilerplate: %v", err) } inputs := sets.NewString(context.Inputs...) packages := generator.Packages{} header := append([]byte(fmt.Sprintf("// +build !%s\n\n", arguments.GeneratedBuildTag)), boilerplate...) header = append(header, []byte( ` // This file was autogenerated by deepcopy-gen. Do not edit it manually! `)...) boundingDirs := []string{} if customArgs, ok := arguments.CustomArgs.(*CustomArgs); ok { for i := range customArgs.BoundingDirs { // Strip any trailing slashes - they are not exactly "correct" but // this is friendlier. boundingDirs = append(boundingDirs, strings.TrimRight(customArgs.BoundingDirs[i], "/")) } } for i := range inputs { glog.V(5).Infof("considering pkg %q", i) pkg := context.Universe[i] if pkg == nil { // If the input had no Go files, for example. continue } ptag := extractTag(pkg.Comments) ptagValue := "" ptagRegister := false if ptag != nil { ptagValue = ptag.value if ptagValue != tagValuePackage { glog.Fatalf("Package %v: unsupported %s value: %q", i, tagName, ptagValue) } ptagRegister = ptag.register glog.V(5).Infof(" tag.value: %q, tag.register: %t", ptagValue, ptagRegister) } else { glog.V(5).Infof(" no tag") } // If the pkg-scoped tag says to generate, we can skip scanning types. pkgNeedsGeneration := (ptagValue == tagValuePackage) if !pkgNeedsGeneration { // If the pkg-scoped tag did not exist, scan all types for one that // explicitly wants generation. for _, t := range pkg.Types { glog.V(5).Infof(" considering type %q", t.Name.String()) ttag := extractTag(t.CommentLines) if ttag != nil && ttag.value == "true" { glog.V(5).Infof(" tag=true") if !copyableType(t) { glog.Fatalf("Type %v requests deepcopy generation but is not copyable", t) } pkgNeedsGeneration = true break } } } if pkgNeedsGeneration { packages = append(packages, &generator.DefaultPackage{ PackageName: strings.Split(filepath.Base(pkg.Path), ".")[0], PackagePath: pkg.Path, HeaderText: header, GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { generators = []generator.Generator{} generators = append( generators, NewGenDeepCopy(arguments.OutputFileBaseName, pkg.Path, boundingDirs, (ptagValue == tagValuePackage), ptagRegister)) return generators }, FilterFunc: func(c *generator.Context, t *types.Type) bool { return t.Name.Package == pkg.Path }, }) } } return packages }
func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages { boilerplate, err := arguments.LoadGoBoilerplate() if err != nil { glog.Fatalf("Failed loading boilerplate: %v", err) } packages := generator.Packages{} header := append([]byte(fmt.Sprintf("// +build !%s\n\n", arguments.GeneratedBuildTag)), boilerplate...) header = append(header, []byte( ` // This file was autogenerated by defaulter-gen. Do not edit it manually! `)...) // Accumulate pre-existing default functions. // TODO: This is too ad-hoc. We need a better way. existingDefaulters := defaulterFuncMap{} buffer := &bytes.Buffer{} sw := generator.NewSnippetWriter(buffer, context, "$", "$") // We are generating defaults only for packages that are explicitly // passed as InputDir. for _, i := range context.Inputs { glog.V(5).Infof("considering pkg %q", i) pkg := context.Universe[i] if pkg == nil { // If the input had no Go files, for example. continue } // Add defaulting functions. getManualDefaultingFunctions(context, pkg, existingDefaulters) var peerPkgs []string if customArgs, ok := arguments.CustomArgs.(*CustomArgs); ok { for _, pkg := range customArgs.ExtraPeerDirs { if i := strings.Index(pkg, "/vendor/"); i != -1 { pkg = pkg[i+len("/vendor/"):] } peerPkgs = append(peerPkgs, pkg) } } // Make sure our peer-packages are added and fully parsed. for _, pp := range peerPkgs { context.AddDir(pp) getManualDefaultingFunctions(context, context.Universe[pp], existingDefaulters) } typesWith := extractTag(pkg.Comments) shouldCreateObjectDefaulterFn := func(t *types.Type) bool { if defaults, ok := existingDefaulters[t]; ok && defaults.object != nil { // A default generator is defined glog.V(5).Infof(" an object defaulter already exists as %s", defaults.base.Name) return false } // opt-out if checkTag(t.SecondClosestCommentLines, "false") { return false } // opt-in if checkTag(t.SecondClosestCommentLines, "true") { return true } // For every k8s:defaulter-gen tag at the package level, interpret the value as a // field name (like TypeMeta, ListMeta, ObjectMeta) and trigger defaulter generation // for any type with any of the matching field names. Provides a more useful package // level defaulting than global (because we only need defaulters on a subset of objects - // usually those with TypeMeta). if t.Kind == types.Struct && len(typesWith) > 0 { for _, field := range t.Members { for _, s := range typesWith { if field.Name == s { return true } } } } return false } newDefaulters := defaulterFuncMap{} for _, t := range pkg.Types { if !shouldCreateObjectDefaulterFn(t) { continue } if namer.IsPrivateGoName(t.Name.Name) { // We won't be able to convert to a private type. glog.V(5).Infof(" found a type %v, but it is a private name", t) continue } // create a synthetic type we can use during generation newDefaulters[t] = defaults{} } // only generate defaulters for objects that actually have defined defaulters // prevents empty defaulters from being registered for { promoted := 0 for t, d := range newDefaulters { if d.object != nil { continue } if buildCallTreeForType(t, true, existingDefaulters, newDefaulters) != nil { args := defaultingArgsFromType(t) sw.Do("$.inType|objectdefaultfn$", args) newDefaulters[t] = defaults{ object: &types.Type{ Name: types.Name{ Package: pkg.Path, Name: buffer.String(), }, Kind: types.Func, }, } buffer.Reset() promoted++ } } if promoted != 0 { continue } // prune any types that were not used for t, d := range newDefaulters { if d.object == nil { glog.V(6).Infof("did not generate defaulter for %s because no child defaulters were registered", t.Name) delete(newDefaulters, t) } } break } if len(newDefaulters) == 0 { glog.V(5).Infof("no defaulters in package %s", pkg.Name) } packages = append(packages, &generator.DefaultPackage{ PackageName: filepath.Base(pkg.Path), PackagePath: pkg.Path, HeaderText: header, GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { return []generator.Generator{ NewGenDefaulter(arguments.OutputFileBaseName, pkg.Path, existingDefaulters, newDefaulters, peerPkgs), } }, FilterFunc: func(c *generator.Context, t *types.Type) bool { return t.Name.Package == pkg.Path }, }) } return packages }
// Packages makes the client package definition. func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages { boilerplate, err := arguments.LoadGoBoilerplate() if err != nil { glog.Fatalf("Failed loading boilerplate: %v", err) } customArgs, ok := arguments.CustomArgs.(clientgenargs.Args) if !ok { glog.Fatalf("cannot convert arguments.CustomArgs to clientgenargs.Args") } includedTypesOverrides := customArgs.IncludedTypesOverrides generatedBy := generatedBy(customArgs) gvToTypes := map[unversioned.GroupVersion][]*types.Type{} for gv, inputDir := range customArgs.GroupVersionToInputPath { p := context.Universe.Package(inputDir) for n, t := range p.Types { // filter out types which are not included in user specified overrides. typesOverride, ok := includedTypesOverrides[gv] if ok { found := false for _, typeStr := range typesOverride { if typeStr == n { found = true break } } if !found { continue } } else { // User has not specified any override for this group version. // filter out types which dont have genclient=true. if extractBoolTagOrDie("genclient", t.SecondClosestCommentLines) == false { continue } } if _, found := gvToTypes[gv]; !found { gvToTypes[gv] = []*types.Type{} } gvToTypes[gv] = append(gvToTypes[gv], t) } } var packageList []generator.Package typedClientBasePath := filepath.Join(customArgs.ClientsetOutputPath, customArgs.ClientsetName, "typed") packageList = append(packageList, packageForClientset(customArgs, typedClientBasePath, boilerplate, generatedBy)) if customArgs.FakeClient { packageList = append(packageList, fake.PackageForClientset(customArgs, typedClientBasePath, boilerplate, generatedBy)) } // If --clientset-only=true, we don't regenerate the individual typed clients. if customArgs.ClientsetOnly { return generator.Packages(packageList) } orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)} for _, gv := range customArgs.GroupVersions { types := gvToTypes[gv] inputPath := customArgs.GroupVersionToInputPath[gv] packageList = append(packageList, packageForGroup(normalization.GroupVersion(gv), orderer.OrderTypes(types), typedClientBasePath, arguments.OutputBase, inputPath, boilerplate, generatedBy)) if customArgs.FakeClient { packageList = append(packageList, fake.PackageForGroup(normalization.GroupVersion(gv), orderer.OrderTypes(types), typedClientBasePath, arguments.OutputBase, inputPath, boilerplate, generatedBy)) } } return generator.Packages(packageList) }
// Packages makes the client package definition. func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages { boilerplate, err := arguments.LoadGoBoilerplate() if err != nil { glog.Fatalf("Failed loading boilerplate: %v", err) } boilerplate = append(boilerplate, []byte(generatedBy())...) customArgs, ok := arguments.CustomArgs.(*CustomArgs) if !ok { glog.Fatalf("Wrong CustomArgs type: %T", arguments.CustomArgs) } var packageList generator.Packages typesForGroupVersion := make(map[clientgentypes.GroupVersion][]*types.Type) groupVersions := make(map[string]clientgentypes.GroupVersions) for _, inputDir := range arguments.InputDirs { p := context.Universe.Package(inputDir) objectMeta, err := objectMetaForPackage(p) if err != nil { glog.Fatal(err) } if objectMeta == nil { // no types in this package had genclient continue } var gv clientgentypes.GroupVersion if isInternal(objectMeta) { lastSlash := strings.LastIndex(p.Path, "/") if lastSlash == -1 { glog.Fatalf("error constructing internal group version for package %q", p.Path) } gv.Group = clientgentypes.Group(p.Path[lastSlash+1:]) } else { parts := strings.Split(p.Path, "/") gv.Group = clientgentypes.Group(parts[len(parts)-2]) gv.Version = clientgentypes.Version(parts[len(parts)-1]) } var typesToGenerate []*types.Type for _, t := range p.Types { // filter out types which dont have genclient=true. if extractBoolTagOrDie("genclient", t.SecondClosestCommentLines) == false { continue } // filter out types which have noMethods if extractBoolTagOrDie("noMethods", t.SecondClosestCommentLines) == true { continue } typesToGenerate = append(typesToGenerate, t) if _, ok := typesForGroupVersion[gv]; !ok { typesForGroupVersion[gv] = []*types.Type{} } typesForGroupVersion[gv] = append(typesForGroupVersion[gv], t) } if len(typesToGenerate) == 0 { continue } icGroupName := namer.IC(gv.Group.NonEmpty()) groupVersionsEntry, ok := groupVersions[icGroupName] if !ok { groupVersionsEntry = clientgentypes.GroupVersions{ Group: gv.Group, } } groupVersionsEntry.Versions = append(groupVersionsEntry.Versions, gv.Version) groupVersions[icGroupName] = groupVersionsEntry orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)} typesToGenerate = orderer.OrderTypes(typesToGenerate) packageList = append(packageList, versionPackage(arguments.OutputPackagePath, gv, boilerplate, typesToGenerate, customArgs.InternalClientSetPackage, customArgs.VersionedClientSetPackage, customArgs.ListersPackage)) } packageList = append(packageList, factoryInterfacePackage(arguments.OutputPackagePath, boilerplate, customArgs.InternalClientSetPackage, customArgs.VersionedClientSetPackage, typesForGroupVersion)) packageList = append(packageList, factoryPackage(arguments.OutputPackagePath, boilerplate, groupVersions, customArgs.InternalClientSetPackage, customArgs.VersionedClientSetPackage, typesForGroupVersion)) for _, groupVersionsEntry := range groupVersions { packageList = append(packageList, groupPackage(arguments.OutputPackagePath, groupVersionsEntry, boilerplate)) } return packageList }
// Packages makes the sets package definition. func Packages(_ *generator.Context, arguments *args.GeneratorArgs) generator.Packages { boilerplate, err := arguments.LoadGoBoilerplate() if err != nil { glog.Fatalf("Failed loading boilerplate: %v", err) } return generator.Packages{&generator.DefaultPackage{ PackageName: "sets", PackagePath: arguments.OutputPackagePath, HeaderText: append(boilerplate, []byte( ` // This file was autogenerated by set-gen. Do not edit it manually! `)...), PackageDocumentation: []byte( `// Package sets has auto-generated set types. `), // GeneratorFunc returns a list of generators. Each generator makes a // single file. GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { generators = []generator.Generator{ // Always generate a "doc.go" file. generator.DefaultGen{OptionalName: "doc"}, // Make a separate file for the Empty type, since it's shared by every type. generator.DefaultGen{ OptionalName: "empty", OptionalBody: []byte(emptyTypeDecl), }, } // Since we want a file per type that we generate a set for, we // have to provide a function for this. for _, t := range c.Order { generators = append(generators, &genSet{ DefaultGen: generator.DefaultGen{ // Use the privatized version of the // type name as the file name. // // TODO: make a namer that converts // camelCase to '-' separation for file // names? OptionalName: c.Namers["private"].Name(t), }, outputPackage: arguments.OutputPackagePath, typeToMatch: t, imports: generator.NewImportTracker(), }) } return generators }, FilterFunc: func(c *generator.Context, t *types.Type) bool { // It would be reasonable to filter by the type's package here. // It might be necessary if your input directory has a big // import graph. switch t.Kind { case types.Map, types.Slice, types.Pointer: // These types can't be keys in a map. return false case types.Builtin: return true case types.Struct: // Only some structs can be keys in a map. This is triggered by the line // // +genset // or // // +genset=true return extractBoolTagOrDie("genset", t.CommentLines) == true } return false }, }} }
func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages { boilerplate, err := arguments.LoadGoBoilerplate() if err != nil { glog.Fatalf("Failed loading boilerplate: %v", err) } inputs := sets.NewString(context.Inputs...) packages := generator.Packages{} header := append([]byte(fmt.Sprintf("// +build !%s\n\n", arguments.GeneratedBuildTag)), boilerplate...) header = append(header, []byte("\n// This file was autogenerated by conversion-gen. Do not edit it manually!\n\n")...) // Accumulate pre-existing conversion and default functions. // TODO: This is too ad-hoc. We need a better way. manualConversions := conversionFuncMap{} manualDefaults := defaulterFuncMap{} // We are generating conversions only for packages that are explicitly // passed as InputDir. for i := range inputs { glog.V(5).Infof("considering pkg %q", i) pkg := context.Universe[i] if pkg == nil { // If the input had no Go files, for example. continue } // Add conversion and defaulting functions. getManualConversionFunctions(context, pkg, manualConversions) getManualDefaultingFunctions(context, pkg, manualDefaults) // Only generate conversions for packages which explicitly request it // by specifying one or more "+k8s:conversion-gen=<peer-pkg>" // in their doc.go file. peerPkgs := extractTag(pkg.Comments) if peerPkgs != nil { glog.V(5).Infof(" tags: %q", peerPkgs) } else { glog.V(5).Infof(" no tag") continue } if customArgs, ok := arguments.CustomArgs.(*CustomArgs); ok { if len(customArgs.ExtraPeerDirs) > 0 { peerPkgs = append(peerPkgs, customArgs.ExtraPeerDirs...) } } // Make sure our peer-packages are added and fully parsed. for _, pp := range peerPkgs { context.AddDir(pp) getManualConversionFunctions(context, context.Universe[pp], manualConversions) getManualDefaultingFunctions(context, context.Universe[pp], manualDefaults) } packages = append(packages, &generator.DefaultPackage{ PackageName: filepath.Base(pkg.Path), PackagePath: pkg.Path, HeaderText: header, GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { return []generator.Generator{ NewGenConversion(arguments.OutputFileBaseName, pkg.Path, manualConversions, manualDefaults, peerPkgs), } }, FilterFunc: func(c *generator.Context, t *types.Type) bool { return t.Name.Package == pkg.Path }, }) } return packages }
// Packages makes the client package definition. func Packages(context *generator.Context, arguments *args.GeneratorArgs) generator.Packages { boilerplate, err := arguments.LoadGoBoilerplate() if err != nil { glog.Fatalf("Failed loading boilerplate: %v", err) } boilerplate = append(boilerplate, []byte(generatedBy())...) var packageList generator.Packages for _, inputDir := range arguments.InputDirs { p := context.Universe.Package(inputDir) objectMeta, err := objectMetaForPackage(p) if err != nil { glog.Fatal(err) } if objectMeta == nil { // no types in this package had genclient continue } var gv clientgentypes.GroupVersion var internalGVPkg string if isInternal(objectMeta) { lastSlash := strings.LastIndex(p.Path, "/") if lastSlash == -1 { glog.Fatalf("error constructing internal group version for package %q", p.Path) } gv.Group = clientgentypes.Group(p.Path[lastSlash+1:]) internalGVPkg = p.Path } else { parts := strings.Split(p.Path, "/") gv.Group = clientgentypes.Group(parts[len(parts)-2]) gv.Version = clientgentypes.Version(parts[len(parts)-1]) internalGVPkg = strings.Join(parts[0:len(parts)-1], "/") } var typesToGenerate []*types.Type for _, t := range p.Types { // filter out types which dont have genclient=true. if extractBoolTagOrDie("genclient", t.SecondClosestCommentLines) == false { continue } typesToGenerate = append(typesToGenerate, t) } orderer := namer.Orderer{Namer: namer.NewPrivateNamer(0)} typesToGenerate = orderer.OrderTypes(typesToGenerate) packagePath := filepath.Join(arguments.OutputPackagePath, strings.ToLower(gv.Group.NonEmpty()), strings.ToLower(gv.Version.NonEmpty())) packageList = append(packageList, &generator.DefaultPackage{ PackageName: strings.ToLower(gv.Version.NonEmpty()), PackagePath: packagePath, HeaderText: boilerplate, GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) { generators = append(generators, &expansionGenerator{ DefaultGen: generator.DefaultGen{ OptionalName: "expansion_generated", }, packagePath: filepath.Join(arguments.OutputBase, packagePath), types: typesToGenerate, }) for _, t := range typesToGenerate { generators = append(generators, &listerGenerator{ DefaultGen: generator.DefaultGen{ OptionalName: strings.ToLower(t.Name.Name), }, outputPackage: arguments.OutputPackagePath, groupVersion: gv, internalGVPkg: internalGVPkg, typeToGenerate: t, imports: generator.NewImportTracker(), objectMeta: objectMeta, }) } return generators }, FilterFunc: func(c *generator.Context, t *types.Type) bool { // piggy-back on types that are tagged for client-gen return extractBoolTagOrDie("genclient", t.SecondClosestCommentLines) == true }, }) } return packageList }