Support Go 1.18: Upgrade gqlgen to v0.17.2 (#2443)

* Upgrade gqlgen to v0.17.2

This enables builds on Go 1.18. github.com/vektah/gqlparser is upgraded
to the newest version too.

Getting this to work is a bit of a hazzle. I had to first remove
vendoring from the repository, perform the upgrade and then re-introduce
the vendor directory. I think gqlgens analysis went wrong for some
reason on the upgrade. It would seem a clean-room installation fixed it.

* Bump project to 1.18

* Update all packages, address gqlgenc breaking changes

* Let `go mod tidy` handle the go.mod file

* Upgrade linter to 1.45.2

* Introduce v1.45.2 of the linter

The linter now correctly warns on `strings.Title` because it isn't
unicode-aware. Fix this by using the suggested fix from x/text/cases
to produce unicode-aware strings.

The mapping isn't entirely 1-1 as this new approach has a larger iface:
it spans all of unicode rather than just ASCII. It coincides for ASCII
however, so things should be largely the same.

* Ready ourselves for errchkjson and contextcheck.

* Revert dockerfile golang version changes for now

Co-authored-by: Kermie <kermie@isinthe.house>
Co-authored-by: WithoutPants <53250216+WithoutPants@users.noreply.github.com>
This commit is contained in:
SmallCoccinelle
2022-04-02 09:08:14 +02:00
committed by GitHub
parent e5c4241180
commit 45f700d6ea
516 changed files with 43496 additions and 10015 deletions

View File

@@ -1,10 +1,34 @@
package codegen
import (
"errors"
"fmt"
"io/ioutil"
"path/filepath"
"runtime"
"strings"
"github.com/99designs/gqlgen/codegen/config"
"github.com/99designs/gqlgen/codegen/templates"
"github.com/vektah/gqlparser/v2/ast"
)
func GenerateCode(data *Data) error {
if !data.Config.Exec.IsDefined() {
return fmt.Errorf("missing exec config")
}
switch data.Config.Exec.Layout {
case config.ExecLayoutSingleFile:
return generateSingleFile(data)
case config.ExecLayoutFollowSchema:
return generatePerSchema(data)
}
return fmt.Errorf("unrecognized exec layout %s", data.Config.Exec.Layout)
}
func generateSingleFile(data *Data) error {
return templates.Render(templates.Options{
PackageName: data.Config.Exec.Package,
Filename: data.Config.Exec.Filename,
@@ -14,3 +38,176 @@ func GenerateCode(data *Data) error {
Packages: data.Config.Packages,
})
}
func generatePerSchema(data *Data) error {
err := generateRootFile(data)
if err != nil {
return err
}
builds := map[string]*Data{}
err = addObjects(data, &builds)
if err != nil {
return err
}
err = addInputs(data, &builds)
if err != nil {
return err
}
err = addInterfaces(data, &builds)
if err != nil {
return err
}
err = addReferencedTypes(data, &builds)
if err != nil {
return err
}
for filename, build := range builds {
if filename == "" {
continue
}
dir := data.Config.Exec.DirName
path := filepath.Join(dir, filename)
err = templates.Render(templates.Options{
PackageName: data.Config.Exec.Package,
Filename: path,
Data: build,
RegionTags: true,
GeneratedHeader: true,
Packages: data.Config.Packages,
})
if err != nil {
return err
}
}
return nil
}
func filename(p *ast.Position, config *config.Config) string {
name := "common!"
if p != nil && p.Src != nil {
gqlname := filepath.Base(p.Src.Name)
ext := filepath.Ext(p.Src.Name)
name = strings.TrimSuffix(gqlname, ext)
}
filenameTempl := config.Exec.FilenameTemplate
if filenameTempl == "" {
filenameTempl = "{name}.generated.go"
}
return strings.ReplaceAll(filenameTempl, "{name}", name)
}
func addBuild(filename string, p *ast.Position, data *Data, builds *map[string]*Data) {
buildConfig := *data.Config
if p != nil {
buildConfig.Sources = []*ast.Source{p.Src}
}
(*builds)[filename] = &Data{
Config: &buildConfig,
QueryRoot: data.QueryRoot,
MutationRoot: data.MutationRoot,
SubscriptionRoot: data.SubscriptionRoot,
AllDirectives: data.AllDirectives,
}
}
// Root file contains top-level definitions that should not be duplicated across the generated
// files for each schema file.
func generateRootFile(data *Data) error {
dir := data.Config.Exec.DirName
path := filepath.Join(dir, "root_.generated.go")
_, thisFile, _, _ := runtime.Caller(0)
rootDir := filepath.Dir(thisFile)
templatePath := filepath.Join(rootDir, "root_.gotpl")
templateBytes, err := ioutil.ReadFile(templatePath)
if err != nil {
return err
}
template := string(templateBytes)
return templates.Render(templates.Options{
PackageName: data.Config.Exec.Package,
Template: template,
Filename: path,
Data: data,
RegionTags: false,
GeneratedHeader: true,
Packages: data.Config.Packages,
})
}
func addObjects(data *Data, builds *map[string]*Data) error {
for _, o := range data.Objects {
filename := filename(o.Position, data.Config)
if (*builds)[filename] == nil {
addBuild(filename, o.Position, data, builds)
}
(*builds)[filename].Objects = append((*builds)[filename].Objects, o)
}
return nil
}
func addInputs(data *Data, builds *map[string]*Data) error {
for _, in := range data.Inputs {
filename := filename(in.Position, data.Config)
if (*builds)[filename] == nil {
addBuild(filename, in.Position, data, builds)
}
(*builds)[filename].Inputs = append((*builds)[filename].Inputs, in)
}
return nil
}
func addInterfaces(data *Data, builds *map[string]*Data) error {
for k, inf := range data.Interfaces {
filename := filename(inf.Position, data.Config)
if (*builds)[filename] == nil {
addBuild(filename, inf.Position, data, builds)
}
build := (*builds)[filename]
if build.Interfaces == nil {
build.Interfaces = map[string]*Interface{}
}
if build.Interfaces[k] != nil {
return errors.New("conflicting interface keys")
}
build.Interfaces[k] = inf
}
return nil
}
func addReferencedTypes(data *Data, builds *map[string]*Data) error {
for k, rt := range data.ReferencedTypes {
filename := filename(rt.Definition.Position, data.Config)
if (*builds)[filename] == nil {
addBuild(filename, rt.Definition.Position, data, builds)
}
build := (*builds)[filename]
if build.ReferencedTypes == nil {
build.ReferencedTypes = map[string]*config.TypeReference{}
}
if build.ReferencedTypes[k] != nil {
return errors.New("conflicting referenced type keys")
}
build.ReferencedTypes[k] = rt
}
return nil
}