Skip to content

Commit

Permalink
make sure colliding imports are stable
Browse files Browse the repository at this point in the history
  • Loading branch information
vektah committed Jun 23, 2018
1 parent abf85a1 commit c0158f5
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 33 deletions.
4 changes: 2 additions & 2 deletions codegen/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (cfg *Config) models() (*ModelBuild, error) {
PackageName: cfg.ModelPackageName,
Models: models,
Enums: cfg.buildEnums(namedTypes),
Imports: imports.imports,
Imports: imports.finalize(),
}, nil
}

Expand Down Expand Up @@ -80,7 +80,7 @@ func (cfg *Config) bind() (*Build, error) {
Objects: objects,
Interfaces: cfg.buildInterfaces(namedTypes, prog),
Inputs: inputs,
Imports: imports.imports,
Imports: imports.finalize(),
}

if qr, ok := cfg.schema.EntryPoints["query"]; ok {
Expand Down
7 changes: 7 additions & 0 deletions codegen/codegen.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"regexp"
"strings"
"syscall"

Expand Down Expand Up @@ -136,6 +137,12 @@ func (cfg *Config) normalize() error {
return cfg.schema.Parse(cfg.SchemaStr)
}

var invalidPackageNameChar = regexp.MustCompile(`[^\w]`)

func sanitizePackageName(pkg string) string {
return invalidPackageNameChar.ReplaceAllLiteralString(filepath.Base(pkg), "_")
}

func abs(path string) string {
absPath, err := filepath.Abs(path)
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions codegen/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
)

type Import struct {
Name string
Alias string
Path string
}
Expand Down
54 changes: 26 additions & 28 deletions codegen/import_build.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
package codegen

import (
"fmt"
"go/build"
"path/filepath"
"regexp"
"sort"
"strconv"
"strings"
Expand Down Expand Up @@ -44,12 +43,6 @@ func buildImports(types NamedTypes, destDir string) *Imports {
return &imports
}

var invalidPackageNameChar = regexp.MustCompile(`[^\w]`)

func sanitizePackageName(pkg string) string {
return invalidPackageNameChar.ReplaceAllLiteralString(filepath.Base(pkg), "_")
}

func (s *Imports) add(path string) *Import {
if path == "" {
return nil
Expand All @@ -64,35 +57,40 @@ func (s *Imports) add(path string) *Import {
panic(err)
}

alias := ""
if !strings.HasSuffix(s.destDir, path) {
if pkg == nil {
panic(path + " was not loaded")
imp := &Import{
Name: pkg.Name,
Path: path,
}
s.imports = append(s.imports, imp)

return imp
}

func (s Imports) finalize() []*Import {
// ensure stable ordering by sorting
sort.Slice(s.imports, func(i, j int) bool {
return s.imports[i].Path > s.imports[j].Path
})

for _, imp := range s.imports {
if strings.HasSuffix(s.destDir, imp.Path) {
imp.Alias = ""
continue
}
alias := imp.Name

alias = pkg.Name
i := 1
imp := s.findByAlias(alias)
for imp != nil && imp.Path != path {
alias = pkg.Name + strconv.Itoa(i)
imp = s.findByAlias(alias)
for s.findByAlias(alias) != nil {
alias = imp.Name + strconv.Itoa(i)
i++
if i > 10 {
panic("too many collisions")
panic(fmt.Errorf("too many collisions, last attempt was %s", imp.Alias))
}
}
imp.Alias = alias
}

imp := &Import{
Alias: alias,
Path: path,
}
s.imports = append(s.imports, imp)
sort.Slice(s.imports, func(i, j int) bool {
return s.imports[i].Alias > s.imports[j].Alias
})

return imp
return s.imports
}

func (s Imports) findByPath(importPath string) *Import {
Expand Down
18 changes: 18 additions & 0 deletions codegen/import_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,21 @@ func TestImportCollisions(t *testing.T) {

require.NoError(t, err)
}

func TestDeterministicDecollisioning(t *testing.T) {
a := Imports{
imports: []*Import{
{Name: "types", Path: "foobar/types"},
{Name: "types", Path: "bazfoo/types"},
},
}.finalize()

b := Imports{
imports: []*Import{
{Name: "types", Path: "bazfoo/types"},
{Name: "types", Path: "foobar/types"},
},
}.finalize()

require.EqualValues(t, a, b)
}
2 changes: 1 addition & 1 deletion example/scalars/generated.go

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

2 changes: 1 addition & 1 deletion example/scalars/models_gen.go

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

2 changes: 1 addition & 1 deletion test/generated.go

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

0 comments on commit c0158f5

Please sign in to comment.