From 77f2e2847d8c171563e824cfadc402e8001882ac Mon Sep 17 00:00:00 2001 From: Adam Scarr Date: Tue, 13 Nov 2018 20:42:46 +1100 Subject: [PATCH] Start moving import management to templates --- codegen/templates/import.go | 96 +++++++++++++++++++ codegen/templates/import_test.go | 56 +++++++++++ codegen/templates/testdata/a/bar/bar.go | 1 + codegen/templates/testdata/b/bar/bar.go | 1 + .../testdata/pkg_mismatch/turtles.go | 1 + 5 files changed, 155 insertions(+) create mode 100644 codegen/templates/import.go create mode 100644 codegen/templates/import_test.go create mode 100644 codegen/templates/testdata/a/bar/bar.go create mode 100644 codegen/templates/testdata/b/bar/bar.go create mode 100644 codegen/templates/testdata/pkg_mismatch/turtles.go diff --git a/codegen/templates/import.go b/codegen/templates/import.go new file mode 100644 index 00000000000..29aa6f90dbf --- /dev/null +++ b/codegen/templates/import.go @@ -0,0 +1,96 @@ +package templates + +import ( + "fmt" + "go/build" + "strconv" + + "github.com/99designs/gqlgen/internal/gopath" +) + +type Import struct { + Name string + Path string + Alias string +} + +type Imports struct { + imports []*Import + destDir string +} + +func (i *Import) String() string { + if i.Alias == i.Name { + return strconv.Quote(i.Path) + } + + return i.Alias + " " + strconv.Quote(i.Path) +} + +func (s *Imports) String() string { + res := "" + for i, imp := range s.imports { + if i != 0 { + res += "\n" + } + res += imp.String() + } + return res +} + +func (s *Imports) Lookup(path string) string { + if path == "" { + return "" + } + + // if we are referencing our own package we dont need an import + if gopath.MustDir2Import(s.destDir) == path { + return "" + } + + if existing := s.findByPath(path); existing != nil { + return existing.Alias + } + + pkg, err := build.Default.Import(path, s.destDir, 0) + if err != nil { + panic(err) + } + + imp := &Import{ + Name: pkg.Name, + Path: path, + } + s.imports = append(s.imports, imp) + + alias := imp.Name + i := 1 + for s.findByAlias(alias) != nil { + alias = imp.Name + strconv.Itoa(i) + i++ + if i > 10 { + panic(fmt.Errorf("too many collisions, last attempt was %s", alias)) + } + } + imp.Alias = alias + + return imp.Alias +} + +func (s Imports) findByPath(importPath string) *Import { + for _, imp := range s.imports { + if imp.Path == importPath { + return imp + } + } + return nil +} + +func (s Imports) findByAlias(alias string) *Import { + for _, imp := range s.imports { + if imp.Alias == alias { + return imp + } + } + return nil +} diff --git a/codegen/templates/import_test.go b/codegen/templates/import_test.go new file mode 100644 index 00000000000..16ec405dec5 --- /dev/null +++ b/codegen/templates/import_test.go @@ -0,0 +1,56 @@ +package templates + +import ( + "os" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestImports(t *testing.T) { + wd, err := os.Getwd() + require.NoError(t, err) + + aBar := "github.com/99designs/gqlgen/codegen/templates/testdata/a/bar" + bBar := "github.com/99designs/gqlgen/codegen/templates/testdata/b/bar" + mismatch := "github.com/99designs/gqlgen/codegen/templates/testdata/pkg_mismatch" + + t.Run("multiple lookups is ok", func(t *testing.T) { + a := Imports{destDir: wd} + + require.Equal(t, "bar", a.Lookup(aBar)) + require.Equal(t, "bar", a.Lookup(aBar)) + }) + + t.Run("duplicates are decollisioned", func(t *testing.T) { + a := Imports{destDir: wd} + + require.Equal(t, "bar", a.Lookup(aBar)) + require.Equal(t, "bar1", a.Lookup(bBar)) + + t.Run("additionial calls get decollisioned name", func(t *testing.T) { + require.Equal(t, "bar1", a.Lookup(bBar)) + }) + }) + + t.Run("package name defined in code will be used", func(t *testing.T) { + a := Imports{destDir: wd} + + require.Equal(t, "turtles", a.Lookup(mismatch)) + }) + + t.Run("string printing for import block", func(t *testing.T) { + a := Imports{destDir: wd} + a.Lookup(aBar) + a.Lookup(bBar) + a.Lookup(mismatch) + + require.Equal( + t, + `"github.com/99designs/gqlgen/codegen/templates/testdata/a/bar" +bar1 "github.com/99designs/gqlgen/codegen/templates/testdata/b/bar" +"github.com/99designs/gqlgen/codegen/templates/testdata/pkg_mismatch"`, + a.String(), + ) + }) +} diff --git a/codegen/templates/testdata/a/bar/bar.go b/codegen/templates/testdata/a/bar/bar.go new file mode 100644 index 00000000000..ddac0faf273 --- /dev/null +++ b/codegen/templates/testdata/a/bar/bar.go @@ -0,0 +1 @@ +package bar diff --git a/codegen/templates/testdata/b/bar/bar.go b/codegen/templates/testdata/b/bar/bar.go new file mode 100644 index 00000000000..ddac0faf273 --- /dev/null +++ b/codegen/templates/testdata/b/bar/bar.go @@ -0,0 +1 @@ +package bar diff --git a/codegen/templates/testdata/pkg_mismatch/turtles.go b/codegen/templates/testdata/pkg_mismatch/turtles.go new file mode 100644 index 00000000000..a90e7072717 --- /dev/null +++ b/codegen/templates/testdata/pkg_mismatch/turtles.go @@ -0,0 +1 @@ +package turtles