diff options
Diffstat (limited to 'vendor/github.com/99designs/gqlgen/internal')
5 files changed, 282 insertions, 56 deletions
diff --git a/vendor/github.com/99designs/gqlgen/internal/code/compare.go b/vendor/github.com/99designs/gqlgen/internal/code/compare.go new file mode 100644 index 00000000..dce9aea5 --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/internal/code/compare.go @@ -0,0 +1,163 @@ +package code + +import ( + "fmt" + "go/types" +) + +// CompatibleTypes isnt a strict comparison, it allows for pointer differences +func CompatibleTypes(expected types.Type, actual types.Type) error { + //fmt.Println("Comparing ", expected.String(), actual.String()) + + // Special case to deal with pointer mismatches + { + expectedPtr, expectedIsPtr := expected.(*types.Pointer) + actualPtr, actualIsPtr := actual.(*types.Pointer) + + if expectedIsPtr && actualIsPtr { + return CompatibleTypes(expectedPtr.Elem(), actualPtr.Elem()) + } + if expectedIsPtr && !actualIsPtr { + return CompatibleTypes(expectedPtr.Elem(), actual) + } + if !expectedIsPtr && actualIsPtr { + return CompatibleTypes(expected, actualPtr.Elem()) + } + } + + switch expected := expected.(type) { + case *types.Slice: + if actual, ok := actual.(*types.Slice); ok { + return CompatibleTypes(expected.Elem(), actual.Elem()) + } + + case *types.Array: + if actual, ok := actual.(*types.Array); ok { + if expected.Len() != actual.Len() { + return fmt.Errorf("array length differs") + } + + return CompatibleTypes(expected.Elem(), actual.Elem()) + } + + case *types.Basic: + if actual, ok := actual.(*types.Basic); ok { + if actual.Kind() != expected.Kind() { + return fmt.Errorf("basic kind differs, %s != %s", expected.Name(), actual.Name()) + } + + return nil + } + + case *types.Struct: + if actual, ok := actual.(*types.Struct); ok { + if expected.NumFields() != actual.NumFields() { + return fmt.Errorf("number of struct fields differ") + } + + for i := 0; i < expected.NumFields(); i++ { + if expected.Field(i).Name() != actual.Field(i).Name() { + return fmt.Errorf("struct field %d name differs, %s != %s", i, expected.Field(i).Name(), actual.Field(i).Name()) + } + if err := CompatibleTypes(expected.Field(i).Type(), actual.Field(i).Type()); err != nil { + return err + } + } + return nil + } + + case *types.Tuple: + if actual, ok := actual.(*types.Tuple); ok { + if expected.Len() != actual.Len() { + return fmt.Errorf("tuple length differs, %d != %d", expected.Len(), actual.Len()) + } + + for i := 0; i < expected.Len(); i++ { + if err := CompatibleTypes(expected.At(i).Type(), actual.At(i).Type()); err != nil { + return err + } + } + + return nil + } + + case *types.Signature: + if actual, ok := actual.(*types.Signature); ok { + if err := CompatibleTypes(expected.Params(), actual.Params()); err != nil { + return err + } + if err := CompatibleTypes(expected.Results(), actual.Results()); err != nil { + return err + } + + return nil + } + case *types.Interface: + if actual, ok := actual.(*types.Interface); ok { + if expected.NumMethods() != actual.NumMethods() { + return fmt.Errorf("interface method count differs, %d != %d", expected.NumMethods(), actual.NumMethods()) + } + + for i := 0; i < expected.NumMethods(); i++ { + if expected.Method(i).Name() != actual.Method(i).Name() { + return fmt.Errorf("interface method %d name differs, %s != %s", i, expected.Method(i).Name(), actual.Method(i).Name()) + } + if err := CompatibleTypes(expected.Method(i).Type(), actual.Method(i).Type()); err != nil { + return err + } + } + + return nil + } + + case *types.Map: + if actual, ok := actual.(*types.Map); ok { + if err := CompatibleTypes(expected.Key(), actual.Key()); err != nil { + return err + } + + if err := CompatibleTypes(expected.Elem(), actual.Elem()); err != nil { + return err + } + + return nil + } + + case *types.Chan: + if actual, ok := actual.(*types.Chan); ok { + return CompatibleTypes(expected.Elem(), actual.Elem()) + } + + case *types.Named: + if actual, ok := actual.(*types.Named); ok { + if NormalizeVendor(expected.Obj().Pkg().Path()) != NormalizeVendor(actual.Obj().Pkg().Path()) { + return fmt.Errorf( + "package name of named type differs, %s != %s", + NormalizeVendor(expected.Obj().Pkg().Path()), + NormalizeVendor(actual.Obj().Pkg().Path()), + ) + } + + if expected.Obj().Name() != actual.Obj().Name() { + return fmt.Errorf( + "named type name differs, %s != %s", + NormalizeVendor(expected.Obj().Name()), + NormalizeVendor(actual.Obj().Name()), + ) + } + + return nil + } + + // Before models are generated all missing references will be Invalid Basic references. + // lets assume these are valid too. + if actual, ok := actual.(*types.Basic); ok && actual.Kind() == types.Invalid { + return nil + } + + default: + return fmt.Errorf("missing support for %T", expected) + } + + return fmt.Errorf("type mismatch %T != %T", expected, actual) +} diff --git a/vendor/github.com/99designs/gqlgen/internal/code/imports.go b/vendor/github.com/99designs/gqlgen/internal/code/imports.go new file mode 100644 index 00000000..2384e87d --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/internal/code/imports.go @@ -0,0 +1,60 @@ +package code + +import ( + "errors" + "path/filepath" + "sync" + + "golang.org/x/tools/go/packages" +) + +var pathForDirCache = sync.Map{} + +// ImportPathFromDir takes an *absolute* path and returns a golang import path for the package, and returns an error if it isn't on the gopath +func ImportPathForDir(dir string) string { + if v, ok := pathForDirCache.Load(dir); ok { + return v.(string) + } + + p, _ := packages.Load(&packages.Config{ + Dir: dir, + }, ".") + + // If the dir dosent exist yet, keep walking up the directory tree trying to find a match + if len(p) != 1 { + parent, err := filepath.Abs(filepath.Join(dir, "..")) + if err != nil { + panic(err) + } + // Walked all the way to the root and didnt find anything :'( + if parent == dir { + return "" + } + return ImportPathForDir(parent) + "/" + filepath.Base(dir) + } + + pathForDirCache.Store(dir, p[0].PkgPath) + + return p[0].PkgPath +} + +var nameForPackageCache = sync.Map{} + +func NameForPackage(importPath string) string { + if importPath == "" { + panic(errors.New("import path can not be empty")) + } + 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 == "" { + return SanitizePackageName(filepath.Base(importPath)) + } + + nameForPackageCache.Store(importPath, p[0].Name) + + return p[0].Name +} diff --git a/vendor/github.com/99designs/gqlgen/internal/code/util.go b/vendor/github.com/99designs/gqlgen/internal/code/util.go new file mode 100644 index 00000000..2be83a23 --- /dev/null +++ b/vendor/github.com/99designs/gqlgen/internal/code/util.go @@ -0,0 +1,56 @@ +package code + +import ( + "go/build" + "os" + "path/filepath" + "regexp" + "strings" +) + +// take a string in the form github.com/package/blah.Type and split it into package and type +func PkgAndType(name string) (string, string) { + parts := strings.Split(name, ".") + if len(parts) == 1 { + return "", name + } + + 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) + parts := strings.Split(pkg, "/vendor/") + 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 { + return invalidPackageNameChar.ReplaceAllLiteralString(filepath.Base(pkg), "_") +} diff --git a/vendor/github.com/99designs/gqlgen/internal/gopath/gopath.go b/vendor/github.com/99designs/gqlgen/internal/gopath/gopath.go deleted file mode 100644 index c9b66167..00000000 --- a/vendor/github.com/99designs/gqlgen/internal/gopath/gopath.go +++ /dev/null @@ -1,37 +0,0 @@ -package gopath - -import ( - "fmt" - "go/build" - "path/filepath" - "strings" -) - -var NotFound = fmt.Errorf("not on GOPATH") - -// Contains returns true if the given directory is in the GOPATH -func Contains(dir string) bool { - _, err := Dir2Import(dir) - return err == nil -} - -// Dir2Import takes an *absolute* path and returns a golang import path for the package, and returns an error if it isn't on the gopath -func Dir2Import(dir string) (string, error) { - dir = filepath.ToSlash(dir) - for _, gopath := range filepath.SplitList(build.Default.GOPATH) { - gopath = filepath.ToSlash(filepath.Join(gopath, "src")) - if len(gopath) < len(dir) && strings.EqualFold(gopath, dir[0:len(gopath)]) { - return dir[len(gopath)+1:], nil - } - } - return "", NotFound -} - -// MustDir2Import takes an *absolute* path and returns a golang import path for the package, and panics if it isn't on the gopath -func MustDir2Import(dir string) string { - pkg, err := Dir2Import(dir) - if err != nil { - panic(err) - } - return pkg -} diff --git a/vendor/github.com/99designs/gqlgen/internal/imports/prune.go b/vendor/github.com/99designs/gqlgen/internal/imports/prune.go index d2469e83..d678870e 100644 --- a/vendor/github.com/99designs/gqlgen/internal/imports/prune.go +++ b/vendor/github.com/99designs/gqlgen/internal/imports/prune.go @@ -5,16 +5,15 @@ package imports import ( "bytes" "go/ast" - "go/build" "go/parser" "go/printer" "go/token" - "path/filepath" "strings" - "golang.org/x/tools/imports" + "github.com/99designs/gqlgen/internal/code" "golang.org/x/tools/go/ast/astutil" + "golang.org/x/tools/imports" ) type visitFn func(node ast.Node) @@ -54,12 +53,6 @@ func getUnusedImports(file ast.Node, filename string) (map[string]string, error) imported := map[string]*ast.ImportSpec{} used := map[string]bool{} - abs, err := filepath.Abs(filename) - if err != nil { - return nil, err - } - srcDir := filepath.Dir(abs) - ast.Walk(visitFn(func(node ast.Node) { if node == nil { return @@ -75,7 +68,7 @@ func getUnusedImports(file ast.Node, filename string) (map[string]string, error) break } - local := importPathToName(ipath, srcDir) + local := code.NameForPackage(ipath) imported[local] = v case *ast.SelectorExpr: @@ -108,12 +101,3 @@ func getUnusedImports(file ast.Node, filename string) (map[string]string, error) return unusedImport, nil } - -func importPathToName(importPath, srcDir string) (packageName string) { - pkg, err := build.Default.Import(importPath, srcDir, 0) - if err != nil { - return "" - } - - return pkg.Name -} |