Skip to content

Commit

Permalink
immutable/cmd/immutableGen: fix go/packages res and type-based res
Browse files Browse the repository at this point in the history
We need to fight go/packages a bit to find the right package to use for
type information (see golang/go#27910 for more
details).

Also, our logic for surfacing embedded fields where the embedded type
had a valid go/types.Type was incorrect. It assumed that all such types
must be external to the package being generated, and hence required that
all fields be exported. However, it is possible for a package-local type
to fully type check and therefore be valid. In this case, non-exported
fields _are_ valid for surfacing.

Also a small fix in cmd/gg whereby xtest packages were incorrectly being
considered as not Done() because they were missing a hash (which they
will never have). Added a failsafe that errors in case any work was left
un-Done
  • Loading branch information
myitcv committed Feb 20, 2019
1 parent 5f6a877 commit b268ca4
Show file tree
Hide file tree
Showing 7 changed files with 364 additions and 11 deletions.
51 changes: 48 additions & 3 deletions immutable/cmd/immutableGen/generator.go
Expand Up @@ -9,6 +9,9 @@ import (
"go/token"
"go/types"
"path/filepath"
"regexp"
"sort"
"strings"

"golang.org/x/tools/go/packages"
"myitcv.io/gogenerate"
Expand All @@ -29,18 +32,59 @@ func execute(dir string, envPkg string, licenseHeader string, cmds gogenCmds) {
}

config := &packages.Config{
Dir: absDir,
Mode: packages.LoadSyntax,
Fset: token.NewFileSet(),
Tests: false,
Tests: true,
}

pkgs, err := packages.Load(config, absDir)
if err != nil {
fatalf("could not load packages from dir %v: %v", dir, err)
}

pkg := pkgs[0]
forTest := regexp.MustCompile(` \[[^\]]+\]$`)

testPkgs := make(map[string]*packages.Package)
var nonTestPkg *packages.Package

// Becase of https://github.com/golang/go/issues/27910 we have to
// apply some janky logic to find the "right" package
for _, p := range pkgs {
switch {
case strings.HasSuffix(p.PkgPath, ".test"):
// we don't ever want this package
continue
case forTest.MatchString(p.ID):
testPkgs[p.Name] = p
default:
nonTestPkg = p
}
}

ids := func() []string {
var ids []string
for _, p := range pkgs {
ids = append(ids, p.ID)
}
sort.Strings(ids)
return ids
}

if nonTestPkg == nil {
fatalf("always expect to have the actual package. Got %v", ids())
}

var pkg *packages.Package

if strings.HasSuffix(envPkg, "_test") {
if pkg = testPkgs[envPkg]; pkg == nil {
fatalf("called with package name %v, but go/packages did not give us such a package. Got %v", envPkg, ids())
}
} else {
if pkg = testPkgs[envPkg]; pkg == nil {
pkg = nonTestPkg
}
}

if pkg.Name != envPkg {
pps := make([]string, 0, len(pkgs))
Expand Down Expand Up @@ -135,6 +179,7 @@ type embedded struct {
typ types.Type
es string
path []string
info *types.Info
}

type field struct {
Expand Down
5 changes: 3 additions & 2 deletions immutable/cmd/immutableGen/internal/coretest/core.go
Expand Up @@ -7,7 +7,7 @@ import (
"myitcv.io/immutable/cmd/immutableGen/internal/coretest/pkga"
)

//go:generate immutableGen -licenseFile license.txt -G "echo \"hello world\""
//go:generate gobin -m -run myitcv.io/immutable/cmd/immutableGen -licenseFile license.txt -G "echo \"hello world\""

// a comment about MyMap
type _Imm_MyMap map[string]int
Expand Down Expand Up @@ -101,7 +101,8 @@ type _Imm_Embed1 struct {
}

type _Imm_Embed2 struct {
Age int
Age int
otherdetails string
}

type NonImmStruct struct {
Expand Down
17 changes: 17 additions & 0 deletions immutable/cmd/immutableGen/internal/coretest/core_test.go
@@ -0,0 +1,17 @@
package coretest_test

import (
_ "myitcv.io/immutable/cmd/immutableGen/internal/coretest"
)

//go:generate gobin -m -run myitcv.io/immutable/cmd/immutableGen -licenseFile license.txt -G "echo \"hello world\""

type _Imm_xtestA struct {
*XTestB

age int
}

type _Imm_XTestB struct {
Name string
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit b268ca4

Please sign in to comment.