Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support additional unversioned types #43

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 34 additions & 15 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ var (
)

const (
docCommentForceIncludes = "// +gencrdrefdocs:force"
docCommentForceIncludes = "+gencrdrefdocs:force"
docCommentIncludeUnversionedTypes = "+gencrdrefdocs:unversionedTypes"
)

type generatorConfig struct {
Expand Down Expand Up @@ -130,22 +131,31 @@ func main() {
}

klog.Infof("parsing go packages in directory %s", *flAPIDir)
pkgs, err := parseAPIPackages(*flAPIDir)
pkgs, unversionedPkgs, err := parseAPIPackages(*flAPIDir)
if err != nil {
klog.Fatal(err)
}
if len(pkgs) == 0 {
klog.Fatalf("no API packages found in %s", *flAPIDir)
}

apiPackages, err := combineAPIPackages(pkgs)
var unversionedPkgNames []string
for _, uvp := range unversionedPkgs {
unversionedPkgNames = append(unversionedPkgNames, uvp.Path)
}
apiPackages, err := combineAPIPackages(pkgs, unversionedPkgNames)
if err != nil {
klog.Fatal(err)
}

unversionedAPIPackages, err := combineAPIPackages(unversionedPkgs, unversionedPkgNames)
if err != nil {
klog.Fatal(err)
}

mkOutput := func() (string, error) {
var b bytes.Buffer
err := render(&b, apiPackages, config)
err := render(&b, apiPackages, unversionedAPIPackages, config)
if err != nil {
return "", errors.Wrap(err, "failed to render the result")
}
Expand Down Expand Up @@ -200,16 +210,17 @@ func groupName(pkg *types.Package) string {
return ""
}

func parseAPIPackages(dir string) ([]*types.Package, error) {
func parseAPIPackages(dir string) ([]*types.Package, []*types.Package, error) {
b := parser.New()
// the following will silently fail (turn on -v=4 to see logs)
if err := b.AddDirRecursive(*flAPIDir); err != nil {
return nil, err
return nil, nil, err
}
scan, err := b.FindTypes()
if err != nil {
return nil, errors.Wrap(err, "failed to parse pkgs and types")
return nil, nil, errors.Wrap(err, "failed to parse pkgs and types")
}
var unversionedPkgs []*types.Package
var pkgNames []string
for p := range scan {
pkg := scan[p]
Expand All @@ -223,7 +234,10 @@ func parseAPIPackages(dir string) ([]*types.Package, error) {
continue
}

if groupName(pkg) != "" && len(pkg.Types) > 0 || containsString(pkg.DocComments, docCommentForceIncludes) {
if len(pkg.Types) > 0 && containsString(pkg.DocComments, docCommentIncludeUnversionedTypes) {
klog.Infof("including package=%s as an additional unversioned include", p)
unversionedPkgs = append(unversionedPkgs, pkg)
} else if groupName(pkg) != "" && len(pkg.Types) > 0 || containsString(pkg.DocComments, docCommentForceIncludes) {
klog.V(3).Infof("package=%v has groupName and has types", p)
pkgNames = append(pkgNames, p)
}
Expand All @@ -234,7 +248,7 @@ func parseAPIPackages(dir string) ([]*types.Package, error) {
klog.Infof("using package=%s", p)
pkgs = append(pkgs, scan[p])
}
return pkgs, nil
return pkgs, unversionedPkgs, nil
}

func containsString(sl []string, str string) bool {
Expand All @@ -248,7 +262,7 @@ func containsString(sl []string, str string) bool {

// combineAPIPackages groups the Go packages by the <apiGroup+apiVersion> they
// offer, and combines the types in them.
func combineAPIPackages(pkgs []*types.Package) ([]*apiPackage, error) {
func combineAPIPackages(pkgs []*types.Package, unversionedPkgNames []string) ([]*apiPackage, error) {
pkgMap := make(map[string]*apiPackage)
var pkgIds []string

Expand All @@ -263,7 +277,7 @@ func combineAPIPackages(pkgs []*types.Package) ([]*apiPackage, error) {
}

for _, pkg := range pkgs {
apiGroup, apiVersion, err := apiVersionForPackage(pkg)
apiGroup, apiVersion, err := apiVersionForPackage(pkg, unversionedPkgNames)
if err != nil {
return nil, errors.Wrapf(err, "could not get apiVersion for package %s", pkg.Path)
}
Expand Down Expand Up @@ -597,8 +611,13 @@ func isOptionalMember(m types.Member) bool {
return ok
}

func apiVersionForPackage(pkg *types.Package) (string, string, error) {
func apiVersionForPackage(pkg *types.Package, unversionedPkgNames []string) (string, string, error) {
group := groupName(pkg)
for _, upn := range unversionedPkgNames {
if upn == pkg.Path {
return group, "unversioned", nil
}
}
version := pkg.Name // assumes basename (i.e. "v1" in "core/v1") is apiVersion
r := `^v\d+((alpha|beta)\d+)?$`
if !regexp.MustCompile(r).MatchString(version) {
Expand Down Expand Up @@ -648,9 +667,9 @@ func constantsOfType(t *types.Type, pkg *apiPackage) []*types.Type {
return sortTypes(constants)
}

func render(w io.Writer, pkgs []*apiPackage, config generatorConfig) error {
references := findTypeReferences(pkgs)
typePkgMap := extractTypeToPackageMap(pkgs)
func render(w io.Writer, pkgs []*apiPackage, unversionedPkgs []*apiPackage, config generatorConfig) error {
references := findTypeReferences(append(pkgs, unversionedPkgs...))
typePkgMap := extractTypeToPackageMap(append(pkgs, unversionedPkgs...))

t, err := template.New("").Funcs(map[string]interface{}{
"isExportedType": isExportedType,
Expand Down