// Packages makes the sets 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
}
Example #2
0
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 conversion-gen. Do not edit it manually!

`)...)

	// 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)
		}

		pkgNeedsGeneration := false
		for _, t := range pkg.Types {
			// Check whether this type can be auto-converted to the peer
			// package type.
			peerType := getPeerTypeFor(context, t, peerPkgs)
			if peerType == nil {
				// We did not find a corresponding type.
				continue
			}
			if namer.IsPrivateGoName(peerType.Name.Name) {
				// We won't be able to convert to a private type.
				glog.V(5).Infof("  found a peer type %v, but it is a private name", t)
				continue
			}

			// If we can generate conversion in any direction, we should
			// generate this package.
			if isConvertible(t, peerType, manualConversions) || isConvertible(peerType, t, manualConversions) {
				pkgNeedsGeneration = true
				break
			}
		}
		if !pkgNeedsGeneration {
			glog.V(5).Infof("  no viable conversions, not generating for this package")
			continue
		}

		packages = append(packages,
			&generator.DefaultPackage{
				PackageName: filepath.Base(pkg.Path),
				PackagePath: pkg.Path,
				HeaderText:  header,
				GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
					generators = []generator.Generator{}
					generators = append(
						generators, NewGenConversion(arguments.OutputFileBaseName, pkg.Path, manualConversions, manualDefaults, peerPkgs))
					return generators
				},
				FilterFunc: func(c *generator.Context, t *types.Type) bool {
					return t.Name.Package == pkg.Path
				},
			})
	}
	return packages
}