diff --git a/codegen/config/binder.go b/codegen/config/binder.go index 15e456c52e..0c8c7d614c 100644 --- a/codegen/config/binder.go +++ b/codegen/config/binder.go @@ -4,11 +4,8 @@ import ( "fmt" "go/token" "go/types" - "regexp" - "strings" "github.com/99designs/gqlgen/codegen/templates" - "github.com/99designs/gqlgen/internal/code" "github.com/pkg/errors" "github.com/vektah/gqlparser/ast" @@ -29,6 +26,14 @@ func (c *Config) NewBinder(s *ast.Schema) (*Binder, error) { return nil, err } + for _, p := range pkgs { + for _, e := range p.Errors { + if e.Kind == packages.ListError { + return nil, p.Errors[0] + } + } + } + return &Binder{ pkgs: pkgs, schema: s, @@ -71,7 +76,7 @@ func (b *Binder) FindType(pkgName string, typeName string) (types.Type, error) { func (b *Binder) getPkg(find string) *packages.Package { for _, p := range b.pkgs { - if normalizeVendor(find) == normalizeVendor(p.PkgPath) { + if code.NormalizeVendor(find) == code.NormalizeVendor(p.PkgPath) { return p } } @@ -162,15 +167,6 @@ func (b *Binder) PointerTo(ref *TypeReference) *TypeReference { return newRef } -var modsRegex = regexp.MustCompile(`^(\*|\[\])*`) - -func normalizeVendor(pkg string) string { - modifiers := modsRegex.FindAllString(pkg, 1)[0] - pkg = strings.TrimPrefix(pkg, modifiers) - parts := strings.Split(pkg, "/vendor/") - return modifiers + parts[len(parts)-1] -} - // TypeReference is used by args and field types. The Definition can refer to both input and output types. type TypeReference struct { Definition *ast.Definition diff --git a/codegen/config/config.go b/codegen/config/config.go index 1638239d00..5bdc5063d5 100644 --- a/codegen/config/config.go +++ b/codegen/config/config.go @@ -249,7 +249,7 @@ func (tm TypeMap) ReferencedPackages() []string { if pkg == "" || inStrSlice(pkgs, pkg) { continue } - pkgs = append(pkgs, pkg) + pkgs = append(pkgs, code.QualifyPackagePath(pkg)) } } diff --git a/internal/code/imports.go b/internal/code/imports.go index 2734321279..ecfe9dbc9f 100644 --- a/internal/code/imports.go +++ b/internal/code/imports.go @@ -33,6 +33,7 @@ func NameForPackage(importPath string) string { if v, ok := nameForPackageCache.Load(importPath); ok { return v.(string) } + importPath = QualifyPackagePath(importPath) p, _ := packages.Load(nil, importPath) if len(p) != 1 || p[0].Name == "" { diff --git a/internal/code/util.go b/internal/code/util.go index 6e06e4cc18..2be83a23ce 100644 --- a/internal/code/util.go +++ b/internal/code/util.go @@ -1,6 +1,8 @@ package code import ( + "go/build" + "os" "path/filepath" "regexp" "strings" @@ -13,11 +15,15 @@ func PkgAndType(name string) (string, string) { return "", name } - return NormalizeVendor(strings.Join(parts[:len(parts)-1], ".")), parts[len(parts)-1] + return strings.Join(parts[:len(parts)-1], "."), parts[len(parts)-1] } var modsRegex = regexp.MustCompile(`^(\*|\[\])*`) +// NormalizeVendor takes a qualified package path and turns it into normal one. +// eg . +// github.com/foo/vendor/github.com/99designs/gqlgen/graphql becomes +// github.com/99designs/gqlgen/graphql func NormalizeVendor(pkg string) string { modifiers := modsRegex.FindAllString(pkg, 1)[0] pkg = strings.TrimPrefix(pkg, modifiers) @@ -25,6 +31,24 @@ func NormalizeVendor(pkg string) string { return modifiers + parts[len(parts)-1] } +// QualifyPackagePath takes an import and fully qualifies it with a vendor dir, if one is required. +// eg . +// github.com/99designs/gqlgen/graphql becomes +// github.com/foo/vendor/github.com/99designs/gqlgen/graphql +// +// x/tools/packages only supports 'qualified package paths' so this will need to be done prior to calling it +// See https://github.com/golang/go/issues/30289 +func QualifyPackagePath(importPath string) string { + wd, _ := os.Getwd() + + pkg, err := build.Import(importPath, wd, 0) + if err != nil { + return importPath + } + + return pkg.ImportPath +} + var invalidPackageNameChar = regexp.MustCompile(`[^\w]`) func SanitizePackageName(pkg string) string {