diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index be0c36f9..91538b5f 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -27,11 +27,13 @@ When releasing a new version: - The new `optional: generic` allows using a generic type to represent optionality. See the [documentation](genqlient.yaml) for details. - For schemas with enum values that differ only in casing, it's now possible to disable smart-casing in genqlient.yaml; see the [documentation](genqlient.yaml) for `casing` for details. - Support .graphqls and .gql file extensions +- More accurately guess the package name for generated code (and warn if the config option -- now almost never needed -- looks wrong). ### Bug fixes: - The presence of negative pointer directives, i.e., `# @genqlient(pointer: false)` are now respected even in the when `optional: pointer` is set in the configuration file. - Made name collisions between query/mutation arguments and local function variables less likely. - Fix generation issue related to golang type implementation of complex graphql union fragments +- Bind correctly to types in the same package as the generated code. ## v0.6.0 diff --git a/docs/genqlient.yaml b/docs/genqlient.yaml index ddfb760b..f31b251a 100644 --- a/docs/genqlient.yaml +++ b/docs/genqlient.yaml @@ -29,8 +29,12 @@ operations: # genqlient.yaml. Default: generated.go. generated: generated/genqlient.go -# The package name for the output code; defaults to the directory name of -# the generated-code file. +# The package name for the output code; defaults to the package-name +# corresponding to the setting of `generated`, above. +# +# This is rarely needed: only if you want the package-name to differ from the +# suffix of the package-path, and there are no other Go files in the package +# already. package: mygenerated # If set, a file at this path (relative to genqlient.yaml) will be generated diff --git a/example/genqlient.yaml b/example/genqlient.yaml index 11cd0348..1fe772a5 100644 --- a/example/genqlient.yaml +++ b/example/genqlient.yaml @@ -2,8 +2,6 @@ schema: schema.graphql operations: - genqlient.graphql generated: generated.go -# needed since it doesn't match the directory name: -package: main # We bind github's DateTime scalar type to Go's time.Time (which conveniently # already defines MarshalJSON and UnmarshalJSON). This means genqlient will diff --git a/generate/config.go b/generate/config.go index 94ee12c4..7116d4ed 100644 --- a/generate/config.go +++ b/generate/config.go @@ -47,6 +47,8 @@ type Config struct { // The directory of the config-file (relative to which all the other paths // are resolved). Set by ValidateAndFillDefaults. baseDir string + // The package-path into which we are generating. + pkgPath string } // A TypeBinding represents a Go type to which genqlient will bind a particular @@ -132,6 +134,46 @@ func pathJoin(a, b string) string { return filepath.Join(a, b) } +func (c *Config) getPackageNameAndPath() (pkgName, pkgPath string, err error) { + abs, err := filepath.Abs(c.Generated) + if err != nil { + return "", "", err + } + + dir := filepath.Dir(abs) + pkgNameGuess := filepath.Base(dir) + if !token.IsIdentifier(pkgNameGuess) { + pkgNameGuess = "" + } + + pkgs, err := packages.Load(&packages.Config{Mode: packages.NeedName}, dir) + if err != nil { + return pkgNameGuess, "", err + } else if len(pkgs) != 1 { + return pkgNameGuess, "", fmt.Errorf("found %v packages in %v, expected 1", len(pkgs), dir) + } + + pkg := pkgs[0] + // TODO(benkraft): Can PkgPath ever be empty without error? If so, we could + // warn. + if pkg.Name != "" { + return pkg.Name, pkg.PkgPath, nil + } + + // e.g. empty package yet to be created, see if we can just guess a + // reasonable name. + pathSuffix := filepath.Base(pkg.PkgPath) + if token.IsIdentifier(pathSuffix) { + pkgNameGuess = pathSuffix + } + + if pkgNameGuess != "" { + return pkgNameGuess, pkg.PkgPath, nil + } else { + return "", "", fmt.Errorf("no package found in %v", dir) + } +} + // ValidateAndFillDefaults ensures that the configuration is valid, and fills // in any options that were unspecified. // @@ -167,29 +209,40 @@ func (c *Config) ValidateAndFillDefaults(baseDir string) error { "\nExample: \"github.com/Org/Repo/optional.Value\"") } - if c.Package != "" { - if !token.IsIdentifier(c.Package) { - // No need for link here -- if you're already setting the package - // you know where to set the package. - return errorf(nil, "invalid package in genqlient.yaml: '%v' is not a valid identifier", c.Package) - } - } else { - abs, err := filepath.Abs(c.Generated) - if err != nil { - return errorf(nil, "unable to guess package-name: %v"+ - "\nSet package name in genqlient.yaml"+ - "\nExample: https://github.com/Khan/genqlient/blob/main/example/genqlient.yaml#L6", err) - } + if c.Package != "" && !token.IsIdentifier(c.Package) { + // No need for link here -- if you're already setting the package + // you know where to set the package. + return errorf(nil, "invalid package in genqlient.yaml: '%v' is not a valid identifier", c.Package) + } - base := filepath.Base(filepath.Dir(abs)) - if !token.IsIdentifier(base) { - return errorf(nil, "unable to guess package-name: '%v' is not a valid identifier"+ - "\nSet package name in genqlient.yaml"+ - "\nExample: https://github.com/Khan/genqlient/blob/main/example/genqlient.yaml#L6", base) + pkgName, pkgPath, err := c.getPackageNameAndPath() + if err == nil { + if c.Package == pkgName || c.Package == "" { + c.Package = pkgName + } else { + fmt.Printf("warning: package setting in genqlient.yaml '%v' looks wrong "+ + "('%v' is in package '%v') but proceeding with '%v' anyway\n", + c.Package, c.Generated, pkgName, c.Package) } - - c.Package = base + } else if c.Package != "" { + // If you specified a valid package, at least try to use that. + // But we can't set pkgPath, which means you'll run into trouble + // binding against the generated package, so at least warn. + fmt.Printf("warning: unable to identify current package-path (using 'package' config '%v'): %v\n", c.Package, err) + } else if pkgName != "" { + // If the directory-name is valid, use that. This is useful if you + // somehow can't build, and especially for tests. + fmt.Printf("warning: unable to identify current package-path (using directory name '%v': %v\n", pkgName, err) + c.Package = pkgName + } else { + return errorf(nil, "unable to guess package-name: %v"+ + "\nSet package name in genqlient.yaml"+ + "\nExample: https://github.com/Khan/genqlient/blob/main/example/genqlient.yaml#L6", err) } + // This is not likely to work if we got an error, especially if we did the + // c.Package fallback. But it's more likely to work than nothing, so we may + // as well. + c.pkgPath = pkgPath if len(c.PackageBindings) > 0 { for _, binding := range c.PackageBindings { diff --git a/generate/config_test.go b/generate/config_test.go index 004c8f49..d3ea4dbe 100644 --- a/generate/config_test.go +++ b/generate/config_test.go @@ -11,9 +11,9 @@ import ( ) const ( - findConfigDir = "testdata/find-config" - validConfigDir = "testdata/valid-config" - invalidConfigDir = "testdata/invalid-config" + findConfigDir = "testdata/findConfig" + validConfigDir = "testdata/validConfig" + invalidConfigDir = "testdata/invalidConfig" ) func TestFindCfg(t *testing.T) { diff --git a/generate/imports.go b/generate/imports.go index 5d6f0a29..5daee2cd 100644 --- a/generate/imports.go +++ b/generate/imports.go @@ -99,6 +99,9 @@ func (g *generator) ref(fullyQualifiedName string) (qualifiedName string, err er pkgPath := nameToImport[:i] localName := nameToImport[i+1:] + if pkgPath == g.Config.pkgPath { + return prefix + localName, nil + } alias, ok := g.imports[pkgPath] if !ok { if g.importsLocked { diff --git a/generate/testdata/find-config/current/genqlient.yaml b/generate/testdata/findConfig/current/genqlient.yaml similarity index 100% rename from generate/testdata/find-config/current/genqlient.yaml rename to generate/testdata/findConfig/current/genqlient.yaml diff --git a/generate/testdata/find-config/filenames/dotyaml/.genqlient.yaml b/generate/testdata/findConfig/filenames/dotyaml/.genqlient.yaml similarity index 100% rename from generate/testdata/find-config/filenames/dotyaml/.genqlient.yaml rename to generate/testdata/findConfig/filenames/dotyaml/.genqlient.yaml diff --git a/generate/testdata/find-config/filenames/dotyml/.genqlient.yml b/generate/testdata/findConfig/filenames/dotyml/.genqlient.yml similarity index 100% rename from generate/testdata/find-config/filenames/dotyml/.genqlient.yml rename to generate/testdata/findConfig/filenames/dotyml/.genqlient.yml diff --git a/generate/testdata/find-config/filenames/none/.gitkeep b/generate/testdata/findConfig/filenames/none/.gitkeep similarity index 100% rename from generate/testdata/find-config/filenames/none/.gitkeep rename to generate/testdata/findConfig/filenames/none/.gitkeep diff --git a/generate/testdata/find-config/filenames/yaml/genqlient.yaml b/generate/testdata/findConfig/filenames/yaml/genqlient.yaml similarity index 100% rename from generate/testdata/find-config/filenames/yaml/genqlient.yaml rename to generate/testdata/findConfig/filenames/yaml/genqlient.yaml diff --git a/generate/testdata/find-config/filenames/yml/genqlient.yml b/generate/testdata/findConfig/filenames/yml/genqlient.yml similarity index 100% rename from generate/testdata/find-config/filenames/yml/genqlient.yml rename to generate/testdata/findConfig/filenames/yml/genqlient.yml diff --git a/generate/testdata/find-config/none/.gitkeep b/generate/testdata/findConfig/none/.gitkeep similarity index 100% rename from generate/testdata/find-config/none/.gitkeep rename to generate/testdata/findConfig/none/.gitkeep diff --git a/generate/testdata/find-config/none/child/.gitkeep b/generate/testdata/findConfig/none/child/.gitkeep similarity index 100% rename from generate/testdata/find-config/none/child/.gitkeep rename to generate/testdata/findConfig/none/child/.gitkeep diff --git a/generate/testdata/find-config/parent/child/.gitkeep b/generate/testdata/findConfig/parent/child/.gitkeep similarity index 100% rename from generate/testdata/find-config/parent/child/.gitkeep rename to generate/testdata/findConfig/parent/child/.gitkeep diff --git a/generate/testdata/find-config/parent/genqlient.yaml b/generate/testdata/findConfig/parent/genqlient.yaml similarity index 100% rename from generate/testdata/find-config/parent/genqlient.yaml rename to generate/testdata/findConfig/parent/genqlient.yaml diff --git a/generate/testdata/invalid-config/InvalidCasing.yaml b/generate/testdata/invalidConfig/InvalidCasing.yaml similarity index 100% rename from generate/testdata/invalid-config/InvalidCasing.yaml rename to generate/testdata/invalidConfig/InvalidCasing.yaml diff --git a/generate/testdata/invalid-config/InvalidOptional.yaml b/generate/testdata/invalidConfig/InvalidOptional.yaml similarity index 100% rename from generate/testdata/invalid-config/InvalidOptional.yaml rename to generate/testdata/invalidConfig/InvalidOptional.yaml diff --git a/generate/testdata/invalid-config/InvalidPackage.yaml b/generate/testdata/invalidConfig/InvalidPackage.yaml similarity index 100% rename from generate/testdata/invalid-config/InvalidPackage.yaml rename to generate/testdata/invalidConfig/InvalidPackage.yaml diff --git a/generate/testdata/snapshots/TestInvalidConfigs-CantGuessPackage.yaml b/generate/testdata/snapshots/TestInvalidConfigs-CantGuessPackage.yaml deleted file mode 100644 index 2571f712..00000000 --- a/generate/testdata/snapshots/TestInvalidConfigs-CantGuessPackage.yaml +++ /dev/null @@ -1,3 +0,0 @@ -invalid config file testdata/invalid-config/CantGuessPackage.yaml: unable to guess package-name: 'invalid-config' is not a valid identifier -Set package name in genqlient.yaml -Example: https://github.com/Khan/genqlient/blob/main/example/genqlient.yaml#L6 diff --git a/generate/testdata/snapshots/TestInvalidConfigs-InvalidCasing.yaml b/generate/testdata/snapshots/TestInvalidConfigs-InvalidCasing.yaml index 2bcb5e06..6b2cf919 100644 --- a/generate/testdata/snapshots/TestInvalidConfigs-InvalidCasing.yaml +++ b/generate/testdata/snapshots/TestInvalidConfigs-InvalidCasing.yaml @@ -1 +1 @@ -invalid config file testdata/invalid-config/InvalidCasing.yaml: unknown casing algorithm: bogus +invalid config file testdata/invalidConfig/InvalidCasing.yaml: unknown casing algorithm: bogus diff --git a/generate/testdata/snapshots/TestInvalidConfigs-InvalidOptional.yaml b/generate/testdata/snapshots/TestInvalidConfigs-InvalidOptional.yaml index fc5394bf..b6addeb0 100644 --- a/generate/testdata/snapshots/TestInvalidConfigs-InvalidOptional.yaml +++ b/generate/testdata/snapshots/TestInvalidConfigs-InvalidOptional.yaml @@ -1 +1 @@ -invalid config file testdata/invalid-config/InvalidOptional.yaml: optional must be one of: 'value' (default), 'pointer', or 'generic' +invalid config file testdata/invalidConfig/InvalidOptional.yaml: optional must be one of: 'value' (default), 'pointer', or 'generic' diff --git a/generate/testdata/snapshots/TestInvalidConfigs-InvalidPackage.yaml b/generate/testdata/snapshots/TestInvalidConfigs-InvalidPackage.yaml index a3d047a2..28af6380 100644 --- a/generate/testdata/snapshots/TestInvalidConfigs-InvalidPackage.yaml +++ b/generate/testdata/snapshots/TestInvalidConfigs-InvalidPackage.yaml @@ -1 +1 @@ -invalid config file testdata/invalid-config/InvalidPackage.yaml: invalid package in genqlient.yaml: 'bogus-package-name' is not a valid identifier +invalid config file testdata/invalidConfig/InvalidPackage.yaml: invalid package in genqlient.yaml: 'bogus-package-name' is not a valid identifier diff --git a/generate/testdata/snapshots/TestValidConfigs-Simple.yaml b/generate/testdata/snapshots/TestValidConfigs-Empty.yml similarity index 76% rename from generate/testdata/snapshots/TestValidConfigs-Simple.yaml rename to generate/testdata/snapshots/TestValidConfigs-Empty.yml index 77cc1b32..709dea13 100644 --- a/generate/testdata/snapshots/TestValidConfigs-Simple.yaml +++ b/generate/testdata/snapshots/TestValidConfigs-Empty.yml @@ -1,7 +1,7 @@ (*generate.Config)({ Schema: (generate.StringList) , Operations: (generate.StringList) , - Generated: (string) (len=34) "testdata/valid-config/generated.go", + Generated: (string) (len=33) "testdata/validConfig/generated.go", Package: (string) (len=11) "validConfig", ExportOperations: (string) "", ContextType: (string) (len=15) "context.Context", @@ -17,5 +17,6 @@ StructReferences: (bool) false, Extensions: (bool) false, AllowBrokenFeatures: (bool) false, - baseDir: (string) (len=21) "testdata/valid-config" + baseDir: (string) (len=20) "testdata/validConfig", + pkgPath: (string) (len=55) "github.com/Khan/genqlient/generate/testdata/validConfig" }) diff --git a/generate/testdata/snapshots/TestValidConfigs-Lists.yaml b/generate/testdata/snapshots/TestValidConfigs-Lists.yaml index 7ff70462..1c10e82a 100644 --- a/generate/testdata/snapshots/TestValidConfigs-Lists.yaml +++ b/generate/testdata/snapshots/TestValidConfigs-Lists.yaml @@ -1,13 +1,13 @@ (*generate.Config)({ Schema: (generate.StringList) (len=2) { - (string) (len=42) "testdata/valid-config/first_schema.graphql", - (string) (len=43) "testdata/valid-config/second_schema.graphql" + (string) (len=41) "testdata/validConfig/first_schema.graphql", + (string) (len=42) "testdata/validConfig/second_schema.graphql" }, Operations: (generate.StringList) (len=2) { - (string) (len=46) "testdata/valid-config/first_operations.graphql", - (string) (len=47) "testdata/valid-config/second_operations.graphql" + (string) (len=45) "testdata/validConfig/first_operations.graphql", + (string) (len=46) "testdata/validConfig/second_operations.graphql" }, - Generated: (string) (len=34) "testdata/valid-config/generated.go", + Generated: (string) (len=33) "testdata/validConfig/generated.go", Package: (string) (len=11) "validConfig", ExportOperations: (string) "", ContextType: (string) (len=15) "context.Context", @@ -23,5 +23,6 @@ StructReferences: (bool) false, Extensions: (bool) false, AllowBrokenFeatures: (bool) false, - baseDir: (string) (len=21) "testdata/valid-config" + baseDir: (string) (len=20) "testdata/validConfig", + pkgPath: (string) (len=55) "github.com/Khan/genqlient/generate/testdata/validConfig" }) diff --git a/generate/testdata/snapshots/TestValidConfigs-Strings.yaml b/generate/testdata/snapshots/TestValidConfigs-Strings.yaml index 1638e8da..c47d4ad2 100644 --- a/generate/testdata/snapshots/TestValidConfigs-Strings.yaml +++ b/generate/testdata/snapshots/TestValidConfigs-Strings.yaml @@ -1,11 +1,11 @@ (*generate.Config)({ Schema: (generate.StringList) (len=1) { - (string) (len=36) "testdata/valid-config/schema.graphql" + (string) (len=35) "testdata/validConfig/schema.graphql" }, Operations: (generate.StringList) (len=1) { - (string) (len=40) "testdata/valid-config/operations.graphql" + (string) (len=39) "testdata/validConfig/operations.graphql" }, - Generated: (string) (len=34) "testdata/valid-config/generated.go", + Generated: (string) (len=33) "testdata/validConfig/generated.go", Package: (string) (len=11) "validConfig", ExportOperations: (string) "", ContextType: (string) (len=15) "context.Context", @@ -21,5 +21,6 @@ StructReferences: (bool) false, Extensions: (bool) false, AllowBrokenFeatures: (bool) false, - baseDir: (string) (len=21) "testdata/valid-config" + baseDir: (string) (len=20) "testdata/validConfig", + pkgPath: (string) (len=55) "github.com/Khan/genqlient/generate/testdata/validConfig" }) diff --git a/generate/testdata/valid-config/Simple.yaml b/generate/testdata/valid-config/Simple.yaml deleted file mode 100644 index 3084ef55..00000000 --- a/generate/testdata/valid-config/Simple.yaml +++ /dev/null @@ -1 +0,0 @@ -package: validConfig diff --git a/generate/testdata/invalid-config/CantGuessPackage.yaml b/generate/testdata/validConfig/Empty.yml similarity index 100% rename from generate/testdata/invalid-config/CantGuessPackage.yaml rename to generate/testdata/validConfig/Empty.yml diff --git a/generate/testdata/valid-config/Lists.yaml b/generate/testdata/validConfig/Lists.yaml similarity index 84% rename from generate/testdata/valid-config/Lists.yaml rename to generate/testdata/validConfig/Lists.yaml index 8348498b..e3a8af11 100644 --- a/generate/testdata/valid-config/Lists.yaml +++ b/generate/testdata/validConfig/Lists.yaml @@ -5,5 +5,3 @@ schema: operations: - first_operations.graphql - second_operations.graphql - -package: validConfig diff --git a/generate/testdata/valid-config/Strings.yaml b/generate/testdata/validConfig/Strings.yaml similarity index 72% rename from generate/testdata/valid-config/Strings.yaml rename to generate/testdata/validConfig/Strings.yaml index 7830e0f9..d4a4957f 100644 --- a/generate/testdata/valid-config/Strings.yaml +++ b/generate/testdata/validConfig/Strings.yaml @@ -1,3 +1,2 @@ schema: schema.graphql operations: operations.graphql -package: validConfig diff --git a/internal/integration/generated.go b/internal/integration/generated.go index 1f0e079d..2183ce82 100644 --- a/internal/integration/generated.go +++ b/internal/integration/generated.go @@ -3056,9 +3056,10 @@ func (v *simpleQueryExtResponse) GetMe() simpleQueryExtMeUser { return v.Me } // simpleQueryMeUser includes the requested fields of the GraphQL type User. type simpleQueryMeUser struct { - Id string `json:"id"` - Name string `json:"name"` - LuckyNumber int `json:"luckyNumber"` + Id string `json:"id"` + Name string `json:"name"` + LuckyNumber int `json:"luckyNumber"` + GreatScalar MyGreatScalar `json:"greatScalar"` } // GetId returns simpleQueryMeUser.Id, and is useful for accessing the field via an interface. @@ -3070,6 +3071,9 @@ func (v *simpleQueryMeUser) GetName() string { return v.Name } // GetLuckyNumber returns simpleQueryMeUser.LuckyNumber, and is useful for accessing the field via an interface. func (v *simpleQueryMeUser) GetLuckyNumber() int { return v.LuckyNumber } +// GetGreatScalar returns simpleQueryMeUser.GreatScalar, and is useful for accessing the field via an interface. +func (v *simpleQueryMeUser) GetGreatScalar() MyGreatScalar { return v.GreatScalar } + // simpleQueryResponse is returned by simpleQuery on success. type simpleQueryResponse struct { Me simpleQueryMeUser `json:"me"` @@ -3656,6 +3660,7 @@ query simpleQuery { id name luckyNumber + greatScalar } } ` diff --git a/internal/integration/genqlient.yaml b/internal/integration/genqlient.yaml index db6f988f..8f57602a 100644 --- a/internal/integration/genqlient.yaml +++ b/internal/integration/genqlient.yaml @@ -8,3 +8,5 @@ bindings: type: time.Time marshaler: "github.com/Khan/genqlient/internal/testutil.MarshalDate" unmarshaler: "github.com/Khan/genqlient/internal/testutil.UnmarshalDate" + MyGreatScalar: + type: github.com/Khan/genqlient/internal/integration.MyGreatScalar diff --git a/internal/integration/integration_test.go b/internal/integration/integration_test.go index 0e056fab..37b02425 100644 --- a/internal/integration/integration_test.go +++ b/internal/integration/integration_test.go @@ -20,7 +20,7 @@ import ( func TestSimpleQuery(t *testing.T) { _ = `# @genqlient - query simpleQuery { me { id name luckyNumber } }` + query simpleQuery { me { id name luckyNumber greatScalar } }` ctx := context.Background() server := server.RunServer() diff --git a/internal/integration/schema.graphql b/internal/integration/schema.graphql index 7857a4a7..17e20e2d 100644 --- a/internal/integration/schema.graphql +++ b/internal/integration/schema.graphql @@ -1,4 +1,5 @@ scalar Date +scalar MyGreatScalar type Query { me: User @@ -23,6 +24,7 @@ type User implements Being & Lucky { hair: Hair birthdate: Date friends: [User!]! + greatScalar: MyGreatScalar } input NewUser { diff --git a/internal/integration/server/gqlgen_exec.go b/internal/integration/server/gqlgen_exec.go index 10b07b03..e1dce252 100644 --- a/internal/integration/server/gqlgen_exec.go +++ b/internal/integration/server/gqlgen_exec.go @@ -78,6 +78,7 @@ type ComplexityRoot struct { User struct { Birthdate func(childComplexity int) int Friends func(childComplexity int) int + GreatScalar func(childComplexity int) int Hair func(childComplexity int) int ID func(childComplexity int) int LuckyNumber func(childComplexity int) int @@ -288,6 +289,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.User.Friends(childComplexity), true + case "User.greatScalar": + if e.complexity.User.GreatScalar == nil { + break + } + + return e.complexity.User.GreatScalar(childComplexity), true + case "User.hair": if e.complexity.User.Hair == nil { break @@ -423,6 +431,7 @@ func (ec *executionContext) introspectType(name string) (*introspection.Type, er var sources = []*ast.Source{ {Name: "../schema.graphql", Input: `scalar Date +scalar MyGreatScalar type Query { me: User @@ -447,6 +456,7 @@ type User implements Being & Lucky { hair: Hair birthdate: Date friends: [User!]! + greatScalar: MyGreatScalar } input NewUser { @@ -1022,6 +1032,8 @@ func (ec *executionContext) fieldContext_Mutation_createUser(ctx context.Context return ec.fieldContext_User_birthdate(ctx, field) case "friends": return ec.fieldContext_User_friends(ctx, field) + case "greatScalar": + return ec.fieldContext_User_greatScalar(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type User", field.Name) }, @@ -1088,6 +1100,8 @@ func (ec *executionContext) fieldContext_Query_me(ctx context.Context, field gra return ec.fieldContext_User_birthdate(ctx, field) case "friends": return ec.fieldContext_User_friends(ctx, field) + case "greatScalar": + return ec.fieldContext_User_greatScalar(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type User", field.Name) }, @@ -1143,6 +1157,8 @@ func (ec *executionContext) fieldContext_Query_user(ctx context.Context, field g return ec.fieldContext_User_birthdate(ctx, field) case "friends": return ec.fieldContext_User_friends(ctx, field) + case "greatScalar": + return ec.fieldContext_User_greatScalar(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type User", field.Name) }, @@ -1371,6 +1387,8 @@ func (ec *executionContext) fieldContext_Query_usersBornOn(ctx context.Context, return ec.fieldContext_User_birthdate(ctx, field) case "friends": return ec.fieldContext_User_friends(ctx, field) + case "greatScalar": + return ec.fieldContext_User_greatScalar(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type User", field.Name) }, @@ -1440,6 +1458,8 @@ func (ec *executionContext) fieldContext_Query_usersBornOnDates(ctx context.Cont return ec.fieldContext_User_birthdate(ctx, field) case "friends": return ec.fieldContext_User_friends(ctx, field) + case "greatScalar": + return ec.fieldContext_User_greatScalar(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type User", field.Name) }, @@ -1506,6 +1526,8 @@ func (ec *executionContext) fieldContext_Query_userSearch(ctx context.Context, f return ec.fieldContext_User_birthdate(ctx, field) case "friends": return ec.fieldContext_User_friends(ctx, field) + case "greatScalar": + return ec.fieldContext_User_greatScalar(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type User", field.Name) }, @@ -1960,6 +1982,8 @@ func (ec *executionContext) fieldContext_User_friends(ctx context.Context, field return ec.fieldContext_User_birthdate(ctx, field) case "friends": return ec.fieldContext_User_friends(ctx, field) + case "greatScalar": + return ec.fieldContext_User_greatScalar(ctx, field) } return nil, fmt.Errorf("no field named %q was found under type User", field.Name) }, @@ -1967,6 +1991,47 @@ func (ec *executionContext) fieldContext_User_friends(ctx context.Context, field return fc, nil } +func (ec *executionContext) _User_greatScalar(ctx context.Context, field graphql.CollectedField, obj *User) (ret graphql.Marshaler) { + fc, err := ec.fieldContext_User_greatScalar(ctx, field) + if err != nil { + return graphql.Null + } + ctx = graphql.WithFieldContext(ctx, fc) + defer func() { + if r := recover(); r != nil { + ec.Error(ctx, ec.Recover(ctx, r)) + ret = graphql.Null + } + }() + resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.GreatScalar, nil + }) + if err != nil { + ec.Error(ctx, err) + return graphql.Null + } + if resTmp == nil { + return graphql.Null + } + res := resTmp.(*string) + fc.Result = res + return ec.marshalOMyGreatScalar2ᚖstring(ctx, field.Selections, res) +} + +func (ec *executionContext) fieldContext_User_greatScalar(ctx context.Context, field graphql.CollectedField) (fc *graphql.FieldContext, err error) { + fc = &graphql.FieldContext{ + Object: "User", + Field: field, + IsMethod: false, + IsResolver: false, + Child: func(ctx context.Context, field graphql.CollectedField) (*graphql.FieldContext, error) { + return nil, errors.New("field of type MyGreatScalar does not have child fields") + }, + } + return fc, nil +} + func (ec *executionContext) ___Directive_name(ctx context.Context, field graphql.CollectedField, obj *introspection.Directive) (ret graphql.Marshaler) { fc, err := ec.fieldContext___Directive_name(ctx, field) if err != nil { @@ -4255,6 +4320,8 @@ func (ec *executionContext) _User(ctx context.Context, sel ast.SelectionSet, obj if out.Values[i] == graphql.Null { out.Invalids++ } + case "greatScalar": + out.Values[i] = ec._User_greatScalar(ctx, field, obj) default: panic("unknown field " + strconv.Quote(field.Name)) } @@ -5209,6 +5276,22 @@ func (ec *executionContext) marshalOLucky2githubᚗcomᚋKhanᚋgenqlientᚋinte return ec._Lucky(ctx, sel, v) } +func (ec *executionContext) unmarshalOMyGreatScalar2ᚖstring(ctx context.Context, v interface{}) (*string, error) { + if v == nil { + return nil, nil + } + res, err := graphql.UnmarshalString(v) + return &res, graphql.ErrorOnPath(ctx, err) +} + +func (ec *executionContext) marshalOMyGreatScalar2ᚖstring(ctx context.Context, sel ast.SelectionSet, v *string) graphql.Marshaler { + if v == nil { + return graphql.Null + } + res := graphql.MarshalString(*v) + return res +} + func (ec *executionContext) unmarshalOString2ᚖstring(ctx context.Context, v interface{}) (*string, error) { if v == nil { return nil, nil diff --git a/internal/integration/server/gqlgen_models.go b/internal/integration/server/gqlgen_models.go index 1ac2e113..0c28bc55 100644 --- a/internal/integration/server/gqlgen_models.go +++ b/internal/integration/server/gqlgen_models.go @@ -50,6 +50,7 @@ type User struct { Hair *Hair `json:"hair,omitempty"` Birthdate *string `json:"birthdate,omitempty"` Friends []*User `json:"friends"` + GreatScalar *string `json:"greatScalar,omitempty"` } func (User) IsBeing() {} diff --git a/internal/integration/server/server.go b/internal/integration/server/server.go index 00dbb308..a8a45a72 100644 --- a/internal/integration/server/server.go +++ b/internal/integration/server/server.go @@ -17,10 +17,11 @@ func intptr(v int) *int { return &v } var users = []*User{ { ID: "1", Name: "Yours Truly", LuckyNumber: intptr(17), - Birthdate: strptr("2025-01-01"), - Hair: &Hair{Color: strptr("Black")}, + Birthdate: strptr("2025-01-01"), + Hair: &Hair{Color: strptr("Black")}, + GreatScalar: strptr("cool value"), }, - {ID: "2", Name: "Raven", LuckyNumber: intptr(-1), Hair: nil}, + {ID: "2", Name: "Raven", LuckyNumber: intptr(-1), Hair: nil, GreatScalar: strptr("cool value")}, } func init() { @@ -177,4 +178,4 @@ func (r *resolver) Mutation() MutationResolver { func (r *resolver) Query() QueryResolver { return &queryResolver{} } -//go:generate go run github.com/99designs/gqlgen +//go:generate go run github.com/99designs/gqlgen@v0.17.35 diff --git a/internal/integration/util.go b/internal/integration/util.go index 0e0a5127..b55e9b60 100644 --- a/internal/integration/util.go +++ b/internal/integration/util.go @@ -62,3 +62,9 @@ func RunGenerateTest(t *testing.T, relConfigFilename string) { } } } + +// Used for a binding in genqlient.yaml. +// +// This is here rather than in testutil to test the case where the generated +// code and the bound type are in the same package. +type MyGreatScalar string