From 9ef174c8fd53a25873bce40bad42cafdd469bd06 Mon Sep 17 00:00:00 2001 From: igaryo0506 Date: Wed, 4 Dec 2024 15:02:03 +0900 Subject: [PATCH 01/16] fix typo --- clientgenv2/source_generator.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clientgenv2/source_generator.go b/clientgenv2/source_generator.go index 63f41ea..dbda224 100644 --- a/clientgenv2/source_generator.go +++ b/clientgenv2/source_generator.go @@ -39,10 +39,10 @@ func (rs ResponseFieldList) IsFragmentSpread() bool { func (rs ResponseFieldList) StructType() *types.Struct { vars := make([]*types.Var, 0) structTags := make([]string, 0) - for _, filed := range rs { + for _, field := range rs { // クエリーのフィールドの子階層がFragmentの場合、このフィールドにそのFragmentの型を追加する - if filed.IsFragmentSpread { - typ, ok := filed.ResponseFields.StructType().Underlying().(*types.Struct) + if field.IsFragmentSpread { + typ, ok := field.ResponseFields.StructType().Underlying().(*types.Struct) if !ok { continue } @@ -51,8 +51,8 @@ func (rs ResponseFieldList) StructType() *types.Struct { structTags = append(structTags, typ.Tag(j)) } } else { - vars = append(vars, types.NewVar(0, nil, templates.ToGo(filed.Name), filed.Type)) - structTags = append(structTags, strings.Join(filed.Tags, " ")) + vars = append(vars, types.NewVar(0, nil, templates.ToGo(field.Name), field.Type)) + structTags = append(structTags, strings.Join(field.Tags, " ")) } } From 6fa033c1fd1b787021a382b0d8f0d856b498f80a Mon Sep 17 00:00:00 2001 From: igaryo0506 Date: Wed, 18 Dec 2024 18:44:53 +0900 Subject: [PATCH 02/16] fix source_generator.go --- clientgenv2/source_generator.go | 64 ++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 12 deletions(-) diff --git a/clientgenv2/source_generator.go b/clientgenv2/source_generator.go index dbda224..a3c0c3c 100644 --- a/clientgenv2/source_generator.go +++ b/clientgenv2/source_generator.go @@ -26,6 +26,12 @@ type ResponseField struct { ResponseFields ResponseFieldList } +func (r ResponseField) FieldTypeString() string { + fullFieldType := r.Type.String() + parts := strings.Split(fullFieldType, ".") + return parts[len(parts)-1] +} + type ResponseFieldList []*ResponseField func (rs ResponseFieldList) IsFragmentSpread() bool { @@ -40,23 +46,39 @@ func (rs ResponseFieldList) StructType() *types.Struct { vars := make([]*types.Var, 0) structTags := make([]string, 0) for _, field := range rs { - // クエリーのフィールドの子階層がFragmentの場合、このフィールドにそのFragmentの型を追加する + vars = append(vars, types.NewVar(0, nil, templates.ToGo(field.Name), field.Type)) + structTags = append(structTags, strings.Join(field.Tags, " ")) + } + return types.NewStruct(vars, structTags) +} + +// MergeFragmentFields returns merged ResponseFieldList, post-merged ResponseFieldList, and remove type names +func (rs ResponseFieldList) MergeFragmentFields() (ResponseFieldList, map[string]*ResponseFieldList, []string) { + res := make(ResponseFieldList, 0) + fragmentChildrenFields := make(ResponseFieldList, 0) + removeTypeNames := make([]string, 0) + for _, field := range rs { if field.IsFragmentSpread { - typ, ok := field.ResponseFields.StructType().Underlying().(*types.Struct) - if !ok { - continue - } - for j := range typ.NumFields() { - vars = append(vars, typ.Field(j)) - structTags = append(structTags, typ.Tag(j)) - } + fragmentChildrenFields = append(fragmentChildrenFields, field.ResponseFields...) + removeTypeNames = append(removeTypeNames, field.FieldTypeString()) } else { - vars = append(vars, types.NewVar(0, nil, templates.ToGo(field.Name), field.Type)) - structTags = append(structTags, strings.Join(field.Tags, " ")) + res = append(res, field) } } - return types.NewStruct(vars, structTags) + postMergedResponseFields := make(map[string]*ResponseFieldList) + for _, field := range fragmentChildrenFields { + for _, resField := range res { + if field.Name == resField.Name { + resField.ResponseFields = append(resField.ResponseFields, field.ResponseFields...) + postMergedResponseFields[resField.FieldTypeString()] = &resField.ResponseFields + removeTypeNames = append(removeTypeNames, field.FieldTypeString()) + removeTypeNames = append(removeTypeNames, resField.FieldTypeString()) + break + } + } + } + return res, postMergedResponseFields, removeTypeNames } func (rs ResponseFieldList) IsFragment() bool { @@ -127,6 +149,24 @@ func (r *SourceGenerator) NewResponseField(selection ast.Selection, typeName str // if a child field is fragment, this field type became fragment. baseType = fieldsResponseFields[0].Type case fieldsResponseFields.IsStructType(): + fieldsResponseFields, postMergedResponseFields, preMergedTypeNames := fieldsResponseFields.MergeFragmentFields() + // remove pre-merged struct + for _, preMergedTypeName := range preMergedTypeNames { + for i, source := range r.StructSources { + if source.Name == preMergedTypeName { + r.StructSources = append(r.StructSources[:i], r.StructSources[i+1:]...) + break + } + } + } + // append post-merged struct + for postMergedName, responseFieldList := range postMergedResponseFields { + postMergedStructType := responseFieldList.StructType() + r.StructSources = append(r.StructSources, &StructSource{ + Name: postMergedName, + Type: postMergedStructType, + }) + } structType := fieldsResponseFields.StructType() r.StructSources = append(r.StructSources, &StructSource{ Name: typeName, From ad7dba4f867576cc684db3c8cb50bbd5db87dc28 Mon Sep 17 00:00:00 2001 From: igaryo0506 Date: Thu, 19 Dec 2024 12:44:18 +0900 Subject: [PATCH 03/16] add example --- example/custom-fragment/.gqlgenc.yml | 17 +++ example/custom-fragment/gen/client.go | 129 ++++++++++++++++++ example/custom-fragment/model/models_gen.go | 3 + example/custom-fragment/query/query.graphql | 16 +++ example/custom-fragment/schema/schema.graphql | 18 +++ 5 files changed, 183 insertions(+) create mode 100644 example/custom-fragment/.gqlgenc.yml create mode 100644 example/custom-fragment/gen/client.go create mode 100644 example/custom-fragment/model/models_gen.go create mode 100644 example/custom-fragment/query/query.graphql create mode 100644 example/custom-fragment/schema/schema.graphql diff --git a/example/custom-fragment/.gqlgenc.yml b/example/custom-fragment/.gqlgenc.yml new file mode 100644 index 0000000..12f1359 --- /dev/null +++ b/example/custom-fragment/.gqlgenc.yml @@ -0,0 +1,17 @@ +model: + package: generated + filename: ./model/models_gen.go +client: + package: generated + filename: ./gen/client.go +models: + Int: + model: github.com/99designs/gqlgen/graphql.Int64 + Date: + model: github.com/99designs/gqlgen/graphql.Time +schema: + - "./schema/**/*.graphql" +query: + - "./query/*.graphql" +generate: + onlyUsedModels: true diff --git a/example/custom-fragment/gen/client.go b/example/custom-fragment/gen/client.go new file mode 100644 index 0000000..1149093 --- /dev/null +++ b/example/custom-fragment/gen/client.go @@ -0,0 +1,129 @@ +// Code generated by github.com/Yamashou/gqlgenc, DO NOT EDIT. + +package generated + +import ( + "context" + + "github.com/Yamashou/gqlgenc/clientv2" +) + +type Client struct { + Client *clientv2.Client +} + +func NewClient(cli clientv2.HttpClient, baseURL string, options *clientv2.Options, interceptors ...clientv2.RequestInterceptor) *Client { + return &Client{Client: clientv2.NewClient(cli, baseURL, options, interceptors...)} +} + +type UserFragment struct { + ID string "json:\"id\" graphql:\"id\"" + Profile UserFragment_Profile "json:\"profile\" graphql:\"profile\"" +} + +func (t *UserFragment) GetID() string { + if t == nil { + t = &UserFragment{} + } + return t.ID +} +func (t *UserFragment) GetProfile() *UserFragment_Profile { + if t == nil { + t = &UserFragment{} + } + return &t.Profile +} + +type UserFragment_Profile struct { + ID string "json:\"id\" graphql:\"id\"" +} + +func (t *UserFragment_Profile) GetID() string { + if t == nil { + t = &UserFragment_Profile{} + } + return t.ID +} + +type UserDetail_User_Profile struct { + Name string "json:\"name\" graphql:\"name\"" + Company string "json:\"company\" graphql:\"company\"" + ID string "json:\"id\" graphql:\"id\"" +} + +func (t *UserDetail_User_Profile) GetName() string { + if t == nil { + t = &UserDetail_User_Profile{} + } + return t.Name +} +func (t *UserDetail_User_Profile) GetCompany() string { + if t == nil { + t = &UserDetail_User_Profile{} + } + return t.Company +} +func (t *UserDetail_User_Profile) GetID() string { + if t == nil { + t = &UserDetail_User_Profile{} + } + return t.ID +} + +type UserDetail_User struct { + Profile UserDetail_User_Profile "json:\"profile\" graphql:\"profile\"" +} + +func (t *UserDetail_User) GetProfile() *UserDetail_User_Profile { + if t == nil { + t = &UserDetail_User{} + } + return &t.Profile +} + +type UserDetail struct { + User UserDetail_User "json:\"user\" graphql:\"user\"" +} + +func (t *UserDetail) GetUser() *UserDetail_User { + if t == nil { + t = &UserDetail{} + } + return &t.User +} + +const UserDetailDocument = `query UserDetail { + user { + ... UserFragment + profile { + name + company + } + } +} +fragment UserFragment on User { + id + profile { + id + } +} +` + +func (c *Client) UserDetail(ctx context.Context, interceptors ...clientv2.RequestInterceptor) (*UserDetail, error) { + vars := map[string]any{} + + var res UserDetail + if err := c.Client.Post(ctx, "UserDetail", UserDetailDocument, &res, vars, interceptors...); err != nil { + if c.Client.ParseDataWhenErrors { + return &res, err + } + + return nil, err + } + + return &res, nil +} + +var DocumentOperationNames = map[string]string{ + UserDetailDocument: "UserDetail", +} diff --git a/example/custom-fragment/model/models_gen.go b/example/custom-fragment/model/models_gen.go new file mode 100644 index 0000000..6fdd9c0 --- /dev/null +++ b/example/custom-fragment/model/models_gen.go @@ -0,0 +1,3 @@ +// Code generated by github.com/99designs/gqlgen, DO NOT EDIT. + +package generated diff --git a/example/custom-fragment/query/query.graphql b/example/custom-fragment/query/query.graphql new file mode 100644 index 0000000..b5f2c8a --- /dev/null +++ b/example/custom-fragment/query/query.graphql @@ -0,0 +1,16 @@ +fragment UserFragment on User { + id + profile { + id + } +} + +query UserDetail { + user { + ...UserFragment + profile { + name + company + } + } +} diff --git a/example/custom-fragment/schema/schema.graphql b/example/custom-fragment/schema/schema.graphql new file mode 100644 index 0000000..79e43bf --- /dev/null +++ b/example/custom-fragment/schema/schema.graphql @@ -0,0 +1,18 @@ +schema { + query: Query +} + +type Query { + user: User! +} + +type User { + id: ID! + profile: Profile! +} + +type Profile { + id: ID! + name: String! + company: String! +} From b1cbb79e7632e6b922ddd2c70bf6da0e24de1db1 Mon Sep 17 00:00:00 2001 From: igaryo0506 Date: Thu, 19 Dec 2024 12:49:06 +0900 Subject: [PATCH 04/16] divide two for logics --- clientgenv2/source_generator.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/clientgenv2/source_generator.go b/clientgenv2/source_generator.go index 06d55fa..5bd969a 100644 --- a/clientgenv2/source_generator.go +++ b/clientgenv2/source_generator.go @@ -57,16 +57,21 @@ func (rs ResponseFieldList) StructType() *types.Struct { func (rs ResponseFieldList) MergeFragmentFields() (ResponseFieldList, map[string]*ResponseFieldList, []string) { res := make(ResponseFieldList, 0) fragmentChildrenFields := make(ResponseFieldList, 0) - removeTypeNames := make([]string, 0) for _, field := range rs { if field.IsFragmentSpread { fragmentChildrenFields = append(fragmentChildrenFields, field.ResponseFields...) - removeTypeNames = append(removeTypeNames, field.FieldTypeString()) } else { res = append(res, field) } } + removeTypeNames := make([]string, 0) + for _, field := range rs { + if field.IsFragmentSpread { + removeTypeNames = append(removeTypeNames, field.FieldTypeString()) + } + } + postMergedResponseFields := make(map[string]*ResponseFieldList) for _, field := range fragmentChildrenFields { for _, resField := range res { @@ -79,6 +84,7 @@ func (rs ResponseFieldList) MergeFragmentFields() (ResponseFieldList, map[string } } } + return res, postMergedResponseFields, removeTypeNames } From 0ff4a3fd15c0da0bccb00b70b170abce05003202 Mon Sep 17 00:00:00 2001 From: igaryo0506 Date: Thu, 19 Dec 2024 12:52:59 +0900 Subject: [PATCH 05/16] add comment --- clientgenv2/source_generator.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clientgenv2/source_generator.go b/clientgenv2/source_generator.go index 5bd969a..e9b37cd 100644 --- a/clientgenv2/source_generator.go +++ b/clientgenv2/source_generator.go @@ -72,9 +72,11 @@ func (rs ResponseFieldList) MergeFragmentFields() (ResponseFieldList, map[string } } + // Child fields of fragment spread are inserted into the parent field postMergedResponseFields := make(map[string]*ResponseFieldList) for _, field := range fragmentChildrenFields { for _, resField := range res { + // if there is a field with the same name, merge the fields if field.Name == resField.Name { resField.ResponseFields = append(resField.ResponseFields, field.ResponseFields...) postMergedResponseFields[resField.FieldTypeString()] = &resField.ResponseFields From 8c2a7514d8284501008036f20d861072d5fa7aa9 Mon Sep 17 00:00:00 2001 From: igaryo0506 Date: Thu, 19 Dec 2024 17:07:35 +0900 Subject: [PATCH 06/16] use struct generator --- clientgenv2/source_generator.go | 112 +++++++++++++++++++++----------- 1 file changed, 75 insertions(+), 37 deletions(-) diff --git a/clientgenv2/source_generator.go b/clientgenv2/source_generator.go index e9b37cd..f4d218f 100644 --- a/clientgenv2/source_generator.go +++ b/clientgenv2/source_generator.go @@ -53,57 +53,96 @@ func (rs ResponseFieldList) StructType() *types.Struct { return types.NewStruct(vars, structTags) } -// MergeFragmentFields returns merged ResponseFieldList, post-merged ResponseFieldList, and remove type names -func (rs ResponseFieldList) MergeFragmentFields() (ResponseFieldList, map[string]*ResponseFieldList, []string) { - res := make(ResponseFieldList, 0) +func (rs ResponseFieldList) IsFragment() bool { + if len(rs) != 1 { + return false + } + + return rs[0].IsInlineFragment || rs[0].IsFragmentSpread +} + +func (rs ResponseFieldList) IsBasicType() bool { + return len(rs) == 0 +} + +func (rs ResponseFieldList) IsStructType() bool { + return len(rs) > 0 && !rs.IsFragment() +} + +type StructGenerator struct { + currentResponseFieldList *ResponseFieldList + fragmentStructSources []*StructSource + preMergedStructSources []*StructSource + postMergedStructSources []*StructSource +} + +func NewStructGenerator(responseFieldList ResponseFieldList) *StructGenerator { + currentFields := make(ResponseFieldList, 0) fragmentChildrenFields := make(ResponseFieldList, 0) - for _, field := range rs { + for _, field := range responseFieldList { if field.IsFragmentSpread { fragmentChildrenFields = append(fragmentChildrenFields, field.ResponseFields...) } else { - res = append(res, field) + currentFields = append(currentFields, field) } } - removeTypeNames := make([]string, 0) - for _, field := range rs { + fragmentStructSources := make([]*StructSource, 0) + for _, field := range responseFieldList { if field.IsFragmentSpread { - removeTypeNames = append(removeTypeNames, field.FieldTypeString()) + fragmentStructSources = append(fragmentStructSources, &StructSource{ + Name: field.FieldTypeString(), + Type: field.ResponseFields.StructType(), + }) } } - // Child fields of fragment spread are inserted into the parent field - postMergedResponseFields := make(map[string]*ResponseFieldList) + preMergedStructSources := make([]*StructSource, 0) + postMergedStructSources := make([]*StructSource, 0) for _, field := range fragmentChildrenFields { - for _, resField := range res { - // if there is a field with the same name, merge the fields - if field.Name == resField.Name { - resField.ResponseFields = append(resField.ResponseFields, field.ResponseFields...) - postMergedResponseFields[resField.FieldTypeString()] = &resField.ResponseFields - removeTypeNames = append(removeTypeNames, field.FieldTypeString()) - removeTypeNames = append(removeTypeNames, resField.FieldTypeString()) + for _, currentField := range currentFields { + if field.Name == currentField.Name { + preMergedStructSources = append(preMergedStructSources, &StructSource{ + Name: field.FieldTypeString(), + Type: field.ResponseFields.StructType(), + }) + postMergedStructSources = append(postMergedStructSources, &StructSource{ + Name: currentField.FieldTypeString(), + Type: currentField.ResponseFields.StructType(), + }) + + currentField.ResponseFields = append(currentField.ResponseFields, field.ResponseFields...) + postMergedStructSources = append(postMergedStructSources, &StructSource{ + Name: currentField.FieldTypeString(), + Type: currentField.ResponseFields.StructType(), + }) break } } } - return res, postMergedResponseFields, removeTypeNames + return &StructGenerator{ + currentResponseFieldList: ¤tFields, + fragmentStructSources: fragmentStructSources, + preMergedStructSources: preMergedStructSources, + postMergedStructSources: postMergedStructSources, + } } -func (rs ResponseFieldList) IsFragment() bool { - if len(rs) != 1 { - return false - } +func (g *StructGenerator) GetCurrentResponseFieldList() *ResponseFieldList { + return g.currentResponseFieldList +} - return rs[0].IsInlineFragment || rs[0].IsFragmentSpread +func (g *StructGenerator) GetFragmentStructSources() []*StructSource { + return g.fragmentStructSources } -func (rs ResponseFieldList) IsBasicType() bool { - return len(rs) == 0 +func (g *StructGenerator) GetPreMergedStructSources() []*StructSource { + return g.preMergedStructSources } -func (rs ResponseFieldList) IsStructType() bool { - return len(rs) > 0 && !rs.IsFragment() +func (g *StructGenerator) GetPostMergedStructSources() []*StructSource { + return g.postMergedStructSources } type StructSource struct { @@ -160,24 +199,23 @@ func (r *SourceGenerator) NewResponseField(selection ast.Selection, typeName str // if a child field is fragment, this field type became fragment. baseType = fieldsResponseFields[0].Type case fieldsResponseFields.IsStructType(): - fieldsResponseFields, postMergedResponseFields, preMergedTypeNames := fieldsResponseFields.MergeFragmentFields() + generator := NewStructGenerator(fieldsResponseFields) + // remove pre-merged struct - for _, preMergedTypeName := range preMergedTypeNames { + for _, preMergedTypeName := range generator.GetPreMergedStructSources() { for i, source := range r.StructSources { - if source.Name == preMergedTypeName { + // when name is same, remove it + if source.Name == preMergedTypeName.Name { r.StructSources = append(r.StructSources[:i], r.StructSources[i+1:]...) break } } } + // append post-merged struct - for postMergedName, responseFieldList := range postMergedResponseFields { - postMergedStructType := responseFieldList.StructType() - r.StructSources = append(r.StructSources, &StructSource{ - Name: postMergedName, - Type: postMergedStructType, - }) - } + r.StructSources = append(r.StructSources, generator.GetPostMergedStructSources()...) + + // append current struct structType := fieldsResponseFields.StructType() r.StructSources = append(r.StructSources, &StructSource{ Name: typeName, From 2c1de307e7044838d74c5aa3f49f9861a74e4975 Mon Sep 17 00:00:00 2001 From: igaryo0506 Date: Thu, 19 Dec 2024 22:17:54 +0900 Subject: [PATCH 07/16] add comment --- clientgenv2/source_generator.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clientgenv2/source_generator.go b/clientgenv2/source_generator.go index f4d218f..dae34a2 100644 --- a/clientgenv2/source_generator.go +++ b/clientgenv2/source_generator.go @@ -199,6 +199,8 @@ func (r *SourceGenerator) NewResponseField(selection ast.Selection, typeName str // if a child field is fragment, this field type became fragment. baseType = fieldsResponseFields[0].Type case fieldsResponseFields.IsStructType(): + // 子フィールドにFragmentがある場合は、現在のフィールドとマージする + // if there is a fragment in child fields, merge it with the current field generator := NewStructGenerator(fieldsResponseFields) // remove pre-merged struct From f43b1b6f3d4f637536d26c74f9d1c395cad5b780 Mon Sep 17 00:00:00 2001 From: igaryo0506 Date: Thu, 19 Dec 2024 22:52:36 +0900 Subject: [PATCH 08/16] add recursively merge --- clientgenv2/source_generator.go | 52 +++++++++------ example/custom-fragment/gen/client.go | 66 +++++++++++++++++-- example/custom-fragment/query/query.graphql | 6 ++ example/custom-fragment/schema/schema.graphql | 6 ++ 4 files changed, 105 insertions(+), 25 deletions(-) diff --git a/clientgenv2/source_generator.go b/clientgenv2/source_generator.go index dae34a2..987678e 100644 --- a/clientgenv2/source_generator.go +++ b/clientgenv2/source_generator.go @@ -99,27 +99,8 @@ func NewStructGenerator(responseFieldList ResponseFieldList) *StructGenerator { preMergedStructSources := make([]*StructSource, 0) postMergedStructSources := make([]*StructSource, 0) - for _, field := range fragmentChildrenFields { - for _, currentField := range currentFields { - if field.Name == currentField.Name { - preMergedStructSources = append(preMergedStructSources, &StructSource{ - Name: field.FieldTypeString(), - Type: field.ResponseFields.StructType(), - }) - postMergedStructSources = append(postMergedStructSources, &StructSource{ - Name: currentField.FieldTypeString(), - Type: currentField.ResponseFields.StructType(), - }) - currentField.ResponseFields = append(currentField.ResponseFields, field.ResponseFields...) - postMergedStructSources = append(postMergedStructSources, &StructSource{ - Name: currentField.FieldTypeString(), - Type: currentField.ResponseFields.StructType(), - }) - break - } - } - } + currentFields = mergeFieldsRecursively(currentFields, fragmentChildrenFields, &preMergedStructSources, &postMergedStructSources) return &StructGenerator{ currentResponseFieldList: ¤tFields, @@ -129,6 +110,37 @@ func NewStructGenerator(responseFieldList ResponseFieldList) *StructGenerator { } } +func mergeFieldsRecursively(targetFields ResponseFieldList, sourceFields ResponseFieldList, preMerged, postMerged *[]*StructSource) ResponseFieldList { + for _, sourceField := range sourceFields { + sameNameFieldFlag := false + for _, targetField := range targetFields { + if sourceField.Name == targetField.Name { + *preMerged = append(*preMerged, &StructSource{ + Name: sourceField.FieldTypeString(), + Type: sourceField.ResponseFields.StructType(), + }) + *preMerged = append(*preMerged, &StructSource{ + Name: targetField.FieldTypeString(), + Type: targetField.ResponseFields.StructType(), + }) + + targetField.ResponseFields = mergeFieldsRecursively(targetField.ResponseFields, sourceField.ResponseFields, preMerged, postMerged) + *postMerged = append(*postMerged, &StructSource{ + Name: targetField.FieldTypeString(), + Type: targetField.ResponseFields.StructType(), + }) + sameNameFieldFlag = true + break + } + } + // if there is no same name field, append it + if !sameNameFieldFlag { + targetFields = append(targetFields, sourceField) + } + } + return targetFields +} + func (g *StructGenerator) GetCurrentResponseFieldList() *ResponseFieldList { return g.currentResponseFieldList } diff --git a/example/custom-fragment/gen/client.go b/example/custom-fragment/gen/client.go index 1149093..9d6b2ae 100644 --- a/example/custom-fragment/gen/client.go +++ b/example/custom-fragment/gen/client.go @@ -34,8 +34,20 @@ func (t *UserFragment) GetProfile() *UserFragment_Profile { return &t.Profile } +type UserFragment_Profile_Detail struct { + BirthDate string "json:\"birthDate\" graphql:\"birthDate\"" +} + +func (t *UserFragment_Profile_Detail) GetBirthDate() string { + if t == nil { + t = &UserFragment_Profile_Detail{} + } + return t.BirthDate +} + type UserFragment_Profile struct { - ID string "json:\"id\" graphql:\"id\"" + ID string "json:\"id\" graphql:\"id\"" + Detail UserFragment_Profile_Detail "json:\"detail\" graphql:\"detail\"" } func (t *UserFragment_Profile) GetID() string { @@ -44,11 +56,36 @@ func (t *UserFragment_Profile) GetID() string { } return t.ID } +func (t *UserFragment_Profile) GetDetail() *UserFragment_Profile_Detail { + if t == nil { + t = &UserFragment_Profile{} + } + return &t.Detail +} + +type UserDetail_User_Profile_Detail struct { + ID string "json:\"id\" graphql:\"id\"" + BirthDate string "json:\"birthDate\" graphql:\"birthDate\"" +} + +func (t *UserDetail_User_Profile_Detail) GetID() string { + if t == nil { + t = &UserDetail_User_Profile_Detail{} + } + return t.ID +} +func (t *UserDetail_User_Profile_Detail) GetBirthDate() string { + if t == nil { + t = &UserDetail_User_Profile_Detail{} + } + return t.BirthDate +} type UserDetail_User_Profile struct { - Name string "json:\"name\" graphql:\"name\"" - Company string "json:\"company\" graphql:\"company\"" - ID string "json:\"id\" graphql:\"id\"" + Name string "json:\"name\" graphql:\"name\"" + Company string "json:\"company\" graphql:\"company\"" + Detail UserDetail_User_Profile_Detail "json:\"detail\" graphql:\"detail\"" + ID string "json:\"id\" graphql:\"id\"" } func (t *UserDetail_User_Profile) GetName() string { @@ -63,6 +100,12 @@ func (t *UserDetail_User_Profile) GetCompany() string { } return t.Company } +func (t *UserDetail_User_Profile) GetDetail() *UserDetail_User_Profile_Detail { + if t == nil { + t = &UserDetail_User_Profile{} + } + return &t.Detail +} func (t *UserDetail_User_Profile) GetID() string { if t == nil { t = &UserDetail_User_Profile{} @@ -71,9 +114,16 @@ func (t *UserDetail_User_Profile) GetID() string { } type UserDetail_User struct { - Profile UserDetail_User_Profile "json:\"profile\" graphql:\"profile\"" + UserFragment *UserFragment + Profile UserDetail_User_Profile "json:\"profile\" graphql:\"profile\"" } +func (t *UserDetail_User) GetUserFragment() *UserFragment { + if t == nil { + t = &UserDetail_User{} + } + return t.UserFragment +} func (t *UserDetail_User) GetProfile() *UserDetail_User_Profile { if t == nil { t = &UserDetail_User{} @@ -98,6 +148,9 @@ const UserDetailDocument = `query UserDetail { profile { name company + detail { + id + } } } } @@ -105,6 +158,9 @@ fragment UserFragment on User { id profile { id + detail { + birthDate + } } } ` diff --git a/example/custom-fragment/query/query.graphql b/example/custom-fragment/query/query.graphql index b5f2c8a..3645dcd 100644 --- a/example/custom-fragment/query/query.graphql +++ b/example/custom-fragment/query/query.graphql @@ -2,6 +2,9 @@ fragment UserFragment on User { id profile { id + detail { + birthDate + } } } @@ -11,6 +14,9 @@ query UserDetail { profile { name company + detail { + id + } } } } diff --git a/example/custom-fragment/schema/schema.graphql b/example/custom-fragment/schema/schema.graphql index 79e43bf..6d85a8d 100644 --- a/example/custom-fragment/schema/schema.graphql +++ b/example/custom-fragment/schema/schema.graphql @@ -15,4 +15,10 @@ type Profile { id: ID! name: String! company: String! + detail: ProfileDetail! +} + +type ProfileDetail { + id: ID! + birthDate: String! } From 3b09a085facd01b9a9af75f45248589a7754a8c1 Mon Sep 17 00:00:00 2001 From: igaryo0506 Date: Fri, 20 Dec 2024 11:43:15 +0900 Subject: [PATCH 09/16] use MergedStructSource --- clientgenv2/source_generator.go | 42 +++++++++++++-------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/clientgenv2/source_generator.go b/clientgenv2/source_generator.go index 987678e..9093c5a 100644 --- a/clientgenv2/source_generator.go +++ b/clientgenv2/source_generator.go @@ -141,20 +141,23 @@ func mergeFieldsRecursively(targetFields ResponseFieldList, sourceFields Respons return targetFields } -func (g *StructGenerator) GetCurrentResponseFieldList() *ResponseFieldList { - return g.currentResponseFieldList -} - -func (g *StructGenerator) GetFragmentStructSources() []*StructSource { - return g.fragmentStructSources -} +func (g *StructGenerator) MergedStructSources(sources []*StructSource) []*StructSource { + res := sources + // remove pre-merged struct + for _, preMergedTypeName := range g.preMergedStructSources { + for i, source := range res { + // when name is same, remove it + if source.Name == preMergedTypeName.Name { + res = append(res[:i], res[i+1:]...) + break + } + } + } -func (g *StructGenerator) GetPreMergedStructSources() []*StructSource { - return g.preMergedStructSources -} + // append post-merged struct + res = append(res, g.postMergedStructSources...) -func (g *StructGenerator) GetPostMergedStructSources() []*StructSource { - return g.postMergedStructSources + return res } type StructSource struct { @@ -215,19 +218,8 @@ func (r *SourceGenerator) NewResponseField(selection ast.Selection, typeName str // if there is a fragment in child fields, merge it with the current field generator := NewStructGenerator(fieldsResponseFields) - // remove pre-merged struct - for _, preMergedTypeName := range generator.GetPreMergedStructSources() { - for i, source := range r.StructSources { - // when name is same, remove it - if source.Name == preMergedTypeName.Name { - r.StructSources = append(r.StructSources[:i], r.StructSources[i+1:]...) - break - } - } - } - - // append post-merged struct - r.StructSources = append(r.StructSources, generator.GetPostMergedStructSources()...) + // restruct struct sources + r.StructSources = generator.MergedStructSources(r.StructSources) // append current struct structType := fieldsResponseFields.StructType() From 4d5423b15c3084ec257bb008f25a5d305b5ca1a3 Mon Sep 17 00:00:00 2001 From: igaryo0506 Date: Fri, 20 Dec 2024 14:45:31 +0900 Subject: [PATCH 10/16] fix bug --- clientgenv2/source_generator.go | 20 ++++++++++---------- example/custom-fragment/gen/client.go | 12 ++++++------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/clientgenv2/source_generator.go b/clientgenv2/source_generator.go index 9093c5a..671b251 100644 --- a/clientgenv2/source_generator.go +++ b/clientgenv2/source_generator.go @@ -71,7 +71,6 @@ func (rs ResponseFieldList) IsStructType() bool { type StructGenerator struct { currentResponseFieldList *ResponseFieldList - fragmentStructSources []*StructSource preMergedStructSources []*StructSource postMergedStructSources []*StructSource } @@ -87,24 +86,21 @@ func NewStructGenerator(responseFieldList ResponseFieldList) *StructGenerator { } } - fragmentStructSources := make([]*StructSource, 0) + preMergedStructSources := make([]*StructSource, 0) + postMergedStructSources := make([]*StructSource, 0) + for _, field := range responseFieldList { if field.IsFragmentSpread { - fragmentStructSources = append(fragmentStructSources, &StructSource{ + preMergedStructSources = append(preMergedStructSources, &StructSource{ Name: field.FieldTypeString(), Type: field.ResponseFields.StructType(), }) } } - preMergedStructSources := make([]*StructSource, 0) - postMergedStructSources := make([]*StructSource, 0) - currentFields = mergeFieldsRecursively(currentFields, fragmentChildrenFields, &preMergedStructSources, &postMergedStructSources) - return &StructGenerator{ currentResponseFieldList: ¤tFields, - fragmentStructSources: fragmentStructSources, preMergedStructSources: preMergedStructSources, postMergedStructSources: postMergedStructSources, } @@ -114,7 +110,7 @@ func mergeFieldsRecursively(targetFields ResponseFieldList, sourceFields Respons for _, sourceField := range sourceFields { sameNameFieldFlag := false for _, targetField := range targetFields { - if sourceField.Name == targetField.Name { + if sourceField.Name == targetField.Name && !targetField.ResponseFields.IsBasicType() { *preMerged = append(*preMerged, &StructSource{ Name: sourceField.FieldTypeString(), Type: sourceField.ResponseFields.StructType(), @@ -160,6 +156,10 @@ func (g *StructGenerator) MergedStructSources(sources []*StructSource) []*Struct return res } +func (g *StructGenerator) GetCurrentResponseFieldList() ResponseFieldList { + return *g.currentResponseFieldList +} + type StructSource struct { Name string Type types.Type @@ -222,7 +222,7 @@ func (r *SourceGenerator) NewResponseField(selection ast.Selection, typeName str r.StructSources = generator.MergedStructSources(r.StructSources) // append current struct - structType := fieldsResponseFields.StructType() + structType := generator.GetCurrentResponseFieldList().StructType() r.StructSources = append(r.StructSources, &StructSource{ Name: typeName, Type: structType, diff --git a/example/custom-fragment/gen/client.go b/example/custom-fragment/gen/client.go index 9d6b2ae..f7bcea2 100644 --- a/example/custom-fragment/gen/client.go +++ b/example/custom-fragment/gen/client.go @@ -114,21 +114,21 @@ func (t *UserDetail_User_Profile) GetID() string { } type UserDetail_User struct { - UserFragment *UserFragment - Profile UserDetail_User_Profile "json:\"profile\" graphql:\"profile\"" + Profile UserDetail_User_Profile "json:\"profile\" graphql:\"profile\"" + ID string "json:\"id\" graphql:\"id\"" } -func (t *UserDetail_User) GetUserFragment() *UserFragment { +func (t *UserDetail_User) GetProfile() *UserDetail_User_Profile { if t == nil { t = &UserDetail_User{} } - return t.UserFragment + return &t.Profile } -func (t *UserDetail_User) GetProfile() *UserDetail_User_Profile { +func (t *UserDetail_User) GetID() string { if t == nil { t = &UserDetail_User{} } - return &t.Profile + return t.ID } type UserDetail struct { From 31d7966fe9c1c095c960ef41364a0e868294f1b5 Mon Sep 17 00:00:00 2001 From: igaryo0506 Date: Sun, 22 Dec 2024 23:25:02 +0900 Subject: [PATCH 11/16] fix query and fix bug --- clientgenv2/source_generator.go | 19 ++++++++++++------- example/custom-fragment/gen/client.go | 11 ++++++----- example/custom-fragment/query/query.graphql | 1 + 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/clientgenv2/source_generator.go b/clientgenv2/source_generator.go index 671b251..d697791 100644 --- a/clientgenv2/source_generator.go +++ b/clientgenv2/source_generator.go @@ -70,7 +70,7 @@ func (rs ResponseFieldList) IsStructType() bool { } type StructGenerator struct { - currentResponseFieldList *ResponseFieldList + currentResponseFieldList ResponseFieldList preMergedStructSources []*StructSource postMergedStructSources []*StructSource } @@ -100,17 +100,22 @@ func NewStructGenerator(responseFieldList ResponseFieldList) *StructGenerator { currentFields = mergeFieldsRecursively(currentFields, fragmentChildrenFields, &preMergedStructSources, &postMergedStructSources) return &StructGenerator{ - currentResponseFieldList: ¤tFields, + currentResponseFieldList: currentFields, preMergedStructSources: preMergedStructSources, postMergedStructSources: postMergedStructSources, } } func mergeFieldsRecursively(targetFields ResponseFieldList, sourceFields ResponseFieldList, preMerged, postMerged *[]*StructSource) ResponseFieldList { + res := targetFields for _, sourceField := range sourceFields { sameNameFieldFlag := false - for _, targetField := range targetFields { - if sourceField.Name == targetField.Name && !targetField.ResponseFields.IsBasicType() { + for _, targetField := range res { + if sourceField.Name == targetField.Name { + if targetField.ResponseFields.IsBasicType() { + sameNameFieldFlag = true + break + } *preMerged = append(*preMerged, &StructSource{ Name: sourceField.FieldTypeString(), Type: sourceField.ResponseFields.StructType(), @@ -131,10 +136,10 @@ func mergeFieldsRecursively(targetFields ResponseFieldList, sourceFields Respons } // if there is no same name field, append it if !sameNameFieldFlag { - targetFields = append(targetFields, sourceField) + res = append(res, sourceField) } } - return targetFields + return res } func (g *StructGenerator) MergedStructSources(sources []*StructSource) []*StructSource { @@ -157,7 +162,7 @@ func (g *StructGenerator) MergedStructSources(sources []*StructSource) []*Struct } func (g *StructGenerator) GetCurrentResponseFieldList() ResponseFieldList { - return *g.currentResponseFieldList + return g.currentResponseFieldList } type StructSource struct { diff --git a/example/custom-fragment/gen/client.go b/example/custom-fragment/gen/client.go index f7bcea2..99e69de 100644 --- a/example/custom-fragment/gen/client.go +++ b/example/custom-fragment/gen/client.go @@ -114,21 +114,21 @@ func (t *UserDetail_User_Profile) GetID() string { } type UserDetail_User struct { - Profile UserDetail_User_Profile "json:\"profile\" graphql:\"profile\"" ID string "json:\"id\" graphql:\"id\"" + Profile UserDetail_User_Profile "json:\"profile\" graphql:\"profile\"" } -func (t *UserDetail_User) GetProfile() *UserDetail_User_Profile { +func (t *UserDetail_User) GetID() string { if t == nil { t = &UserDetail_User{} } - return &t.Profile + return t.ID } -func (t *UserDetail_User) GetID() string { +func (t *UserDetail_User) GetProfile() *UserDetail_User_Profile { if t == nil { t = &UserDetail_User{} } - return t.ID + return &t.Profile } type UserDetail struct { @@ -145,6 +145,7 @@ func (t *UserDetail) GetUser() *UserDetail_User { const UserDetailDocument = `query UserDetail { user { ... UserFragment + id profile { name company diff --git a/example/custom-fragment/query/query.graphql b/example/custom-fragment/query/query.graphql index 3645dcd..aec1444 100644 --- a/example/custom-fragment/query/query.graphql +++ b/example/custom-fragment/query/query.graphql @@ -11,6 +11,7 @@ fragment UserFragment on User { query UserDetail { user { ...UserFragment + id profile { name company From 994046f2d756d4dfc557c1c220f4b5ffe3f05afe Mon Sep 17 00:00:00 2001 From: igaryo0506 Date: Sun, 22 Dec 2024 23:45:28 +0900 Subject: [PATCH 12/16] use map and sort --- clientgenv2/source_generator.go | 67 ++++++++++++++++----------- example/custom-fragment/gen/client.go | 34 +++++++------- 2 files changed, 57 insertions(+), 44 deletions(-) diff --git a/clientgenv2/source_generator.go b/clientgenv2/source_generator.go index d697791..317e5a6 100644 --- a/clientgenv2/source_generator.go +++ b/clientgenv2/source_generator.go @@ -3,6 +3,7 @@ package clientgenv2 import ( "fmt" "go/types" + "sort" "strings" "github.com/99designs/gqlgen/codegen/config" @@ -69,6 +70,21 @@ func (rs ResponseFieldList) IsStructType() bool { return len(rs) > 0 && !rs.IsFragment() } +func (rs ResponseFieldList) MapByName() map[string]*ResponseField { + res := make(map[string]*ResponseField) + for _, field := range rs { + res[field.Name] = field + } + return res +} + +func (rs ResponseFieldList) SortByName() ResponseFieldList { + sort.Slice(rs, func(i, j int) bool { + return rs[i].Name < rs[j].Name + }) + return rs +} + type StructGenerator struct { currentResponseFieldList ResponseFieldList preMergedStructSources []*StructSource @@ -107,38 +123,35 @@ func NewStructGenerator(responseFieldList ResponseFieldList) *StructGenerator { } func mergeFieldsRecursively(targetFields ResponseFieldList, sourceFields ResponseFieldList, preMerged, postMerged *[]*StructSource) ResponseFieldList { - res := targetFields + res := make(ResponseFieldList, 0) + targetFieldsMap := targetFields.MapByName() for _, sourceField := range sourceFields { - sameNameFieldFlag := false - for _, targetField := range res { - if sourceField.Name == targetField.Name { - if targetField.ResponseFields.IsBasicType() { - sameNameFieldFlag = true - break - } - *preMerged = append(*preMerged, &StructSource{ - Name: sourceField.FieldTypeString(), - Type: sourceField.ResponseFields.StructType(), - }) - *preMerged = append(*preMerged, &StructSource{ - Name: targetField.FieldTypeString(), - Type: targetField.ResponseFields.StructType(), - }) - - targetField.ResponseFields = mergeFieldsRecursively(targetField.ResponseFields, sourceField.ResponseFields, preMerged, postMerged) - *postMerged = append(*postMerged, &StructSource{ - Name: targetField.FieldTypeString(), - Type: targetField.ResponseFields.StructType(), - }) - sameNameFieldFlag = true - break + if targetField, ok := targetFieldsMap[sourceField.Name]; ok { + if targetField.ResponseFields.IsBasicType() { + continue } - } - // if there is no same name field, append it - if !sameNameFieldFlag { + *preMerged = append(*preMerged, &StructSource{ + Name: sourceField.FieldTypeString(), + Type: sourceField.ResponseFields.StructType(), + }) + *preMerged = append(*preMerged, &StructSource{ + Name: targetField.FieldTypeString(), + Type: targetField.ResponseFields.StructType(), + }) + + targetField.ResponseFields = mergeFieldsRecursively(targetField.ResponseFields, sourceField.ResponseFields, preMerged, postMerged) + *postMerged = append(*postMerged, &StructSource{ + Name: targetField.FieldTypeString(), + Type: targetField.ResponseFields.StructType(), + }) + } else { res = append(res, sourceField) } } + for _, field := range targetFieldsMap { + res = append(res, field) + } + res = res.SortByName() return res } diff --git a/example/custom-fragment/gen/client.go b/example/custom-fragment/gen/client.go index 99e69de..664d88f 100644 --- a/example/custom-fragment/gen/client.go +++ b/example/custom-fragment/gen/client.go @@ -46,54 +46,48 @@ func (t *UserFragment_Profile_Detail) GetBirthDate() string { } type UserFragment_Profile struct { - ID string "json:\"id\" graphql:\"id\"" Detail UserFragment_Profile_Detail "json:\"detail\" graphql:\"detail\"" + ID string "json:\"id\" graphql:\"id\"" } -func (t *UserFragment_Profile) GetID() string { +func (t *UserFragment_Profile) GetDetail() *UserFragment_Profile_Detail { if t == nil { t = &UserFragment_Profile{} } - return t.ID + return &t.Detail } -func (t *UserFragment_Profile) GetDetail() *UserFragment_Profile_Detail { +func (t *UserFragment_Profile) GetID() string { if t == nil { t = &UserFragment_Profile{} } - return &t.Detail + return t.ID } type UserDetail_User_Profile_Detail struct { - ID string "json:\"id\" graphql:\"id\"" BirthDate string "json:\"birthDate\" graphql:\"birthDate\"" + ID string "json:\"id\" graphql:\"id\"" } -func (t *UserDetail_User_Profile_Detail) GetID() string { +func (t *UserDetail_User_Profile_Detail) GetBirthDate() string { if t == nil { t = &UserDetail_User_Profile_Detail{} } - return t.ID + return t.BirthDate } -func (t *UserDetail_User_Profile_Detail) GetBirthDate() string { +func (t *UserDetail_User_Profile_Detail) GetID() string { if t == nil { t = &UserDetail_User_Profile_Detail{} } - return t.BirthDate + return t.ID } type UserDetail_User_Profile struct { - Name string "json:\"name\" graphql:\"name\"" Company string "json:\"company\" graphql:\"company\"" Detail UserDetail_User_Profile_Detail "json:\"detail\" graphql:\"detail\"" ID string "json:\"id\" graphql:\"id\"" + Name string "json:\"name\" graphql:\"name\"" } -func (t *UserDetail_User_Profile) GetName() string { - if t == nil { - t = &UserDetail_User_Profile{} - } - return t.Name -} func (t *UserDetail_User_Profile) GetCompany() string { if t == nil { t = &UserDetail_User_Profile{} @@ -112,6 +106,12 @@ func (t *UserDetail_User_Profile) GetID() string { } return t.ID } +func (t *UserDetail_User_Profile) GetName() string { + if t == nil { + t = &UserDetail_User_Profile{} + } + return t.Name +} type UserDetail_User struct { ID string "json:\"id\" graphql:\"id\"" From 713c3519c3b3bff00553f96d474b4baca66d212c Mon Sep 17 00:00:00 2001 From: igaryo0506 Date: Mon, 23 Dec 2024 15:45:09 +0900 Subject: [PATCH 13/16] delete side effect --- clientgenv2/source_generator.go | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/clientgenv2/source_generator.go b/clientgenv2/source_generator.go index 317e5a6..2c59e21 100644 --- a/clientgenv2/source_generator.go +++ b/clientgenv2/source_generator.go @@ -114,7 +114,7 @@ func NewStructGenerator(responseFieldList ResponseFieldList) *StructGenerator { } } - currentFields = mergeFieldsRecursively(currentFields, fragmentChildrenFields, &preMergedStructSources, &postMergedStructSources) + currentFields, preMergedStructSources, postMergedStructSources = mergeFieldsRecursively(currentFields, fragmentChildrenFields, preMergedStructSources, postMergedStructSources) return &StructGenerator{ currentResponseFieldList: currentFields, preMergedStructSources: preMergedStructSources, @@ -122,37 +122,40 @@ func NewStructGenerator(responseFieldList ResponseFieldList) *StructGenerator { } } -func mergeFieldsRecursively(targetFields ResponseFieldList, sourceFields ResponseFieldList, preMerged, postMerged *[]*StructSource) ResponseFieldList { - res := make(ResponseFieldList, 0) +func mergeFieldsRecursively(targetFields ResponseFieldList, sourceFields ResponseFieldList, preMerged, postMerged []*StructSource) (ResponseFieldList, []*StructSource, []*StructSource) { + responseFieldList := make(ResponseFieldList, 0) targetFieldsMap := targetFields.MapByName() + newPreMerged := preMerged + newPostMerged := postMerged + for _, sourceField := range sourceFields { if targetField, ok := targetFieldsMap[sourceField.Name]; ok { if targetField.ResponseFields.IsBasicType() { continue } - *preMerged = append(*preMerged, &StructSource{ + newPreMerged = append(newPreMerged, &StructSource{ Name: sourceField.FieldTypeString(), Type: sourceField.ResponseFields.StructType(), }) - *preMerged = append(*preMerged, &StructSource{ + newPreMerged = append(newPreMerged, &StructSource{ Name: targetField.FieldTypeString(), Type: targetField.ResponseFields.StructType(), }) - targetField.ResponseFields = mergeFieldsRecursively(targetField.ResponseFields, sourceField.ResponseFields, preMerged, postMerged) - *postMerged = append(*postMerged, &StructSource{ + targetField.ResponseFields, newPreMerged, newPostMerged = mergeFieldsRecursively(targetField.ResponseFields, sourceField.ResponseFields, newPreMerged, newPostMerged) + newPostMerged = append(newPostMerged, &StructSource{ Name: targetField.FieldTypeString(), Type: targetField.ResponseFields.StructType(), }) } else { - res = append(res, sourceField) + responseFieldList = append(responseFieldList, sourceField) } } for _, field := range targetFieldsMap { - res = append(res, field) + responseFieldList = append(responseFieldList, field) } - res = res.SortByName() - return res + responseFieldList = responseFieldList.SortByName() + return responseFieldList, newPreMerged, newPostMerged } func (g *StructGenerator) MergedStructSources(sources []*StructSource) []*StructSource { From c71d6885e5b0e3fdbc0196d09905f72f18e881bc Mon Sep 17 00:00:00 2001 From: igaryo0506 Date: Mon, 23 Dec 2024 15:49:14 +0900 Subject: [PATCH 14/16] add comment --- clientgenv2/source_generator.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clientgenv2/source_generator.go b/clientgenv2/source_generator.go index 2c59e21..8e6bcf4 100644 --- a/clientgenv2/source_generator.go +++ b/clientgenv2/source_generator.go @@ -86,9 +86,9 @@ func (rs ResponseFieldList) SortByName() ResponseFieldList { } type StructGenerator struct { - currentResponseFieldList ResponseFieldList - preMergedStructSources []*StructSource - postMergedStructSources []*StructSource + currentResponseFieldList ResponseFieldList // Create fields based on this ResponseFieldList + preMergedStructSources []*StructSource // Struct sources that will no longer be created due to merging + postMergedStructSources []*StructSource // Struct sources that will be created due to merging } func NewStructGenerator(responseFieldList ResponseFieldList) *StructGenerator { From c698679d8be08d646b345bca0dbefa006295a033 Mon Sep 17 00:00:00 2001 From: igaryo0506 Date: Mon, 23 Dec 2024 16:44:56 +0900 Subject: [PATCH 15/16] use map to avoid double loop --- clientgenv2/source_generator.go | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/clientgenv2/source_generator.go b/clientgenv2/source_generator.go index 8e6bcf4..9f3028c 100644 --- a/clientgenv2/source_generator.go +++ b/clientgenv2/source_generator.go @@ -158,17 +158,24 @@ func mergeFieldsRecursively(targetFields ResponseFieldList, sourceFields Respons return responseFieldList, newPreMerged, newPostMerged } +func structSourcesMapByTypeName(sources []*StructSource) map[string]*StructSource { + res := make(map[string]*StructSource) + for _, source := range sources { + res[source.Name] = source + } + return res +} + func (g *StructGenerator) MergedStructSources(sources []*StructSource) []*StructSource { - res := sources + preMergedStructSourcesMap := structSourcesMapByTypeName(g.preMergedStructSources) + res := make([]*StructSource, 0) // remove pre-merged struct - for _, preMergedTypeName := range g.preMergedStructSources { - for i, source := range res { - // when name is same, remove it - if source.Name == preMergedTypeName.Name { - res = append(res[:i], res[i+1:]...) - break - } + for _, source := range sources { + // when name is same, remove it + if _, ok := preMergedStructSourcesMap[source.Name]; ok { + continue } + res = append(res, source) } // append post-merged struct From 291997c8a4c8c45132fdb52cc6086e72b806123d Mon Sep 17 00:00:00 2001 From: igaryo0506 Date: Mon, 23 Dec 2024 18:01:50 +0900 Subject: [PATCH 16/16] fix nits --- clientgenv2/source_generator.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clientgenv2/source_generator.go b/clientgenv2/source_generator.go index 9f3028c..bf67fd3 100644 --- a/clientgenv2/source_generator.go +++ b/clientgenv2/source_generator.go @@ -103,7 +103,6 @@ func NewStructGenerator(responseFieldList ResponseFieldList) *StructGenerator { } preMergedStructSources := make([]*StructSource, 0) - postMergedStructSources := make([]*StructSource, 0) for _, field := range responseFieldList { if field.IsFragmentSpread { @@ -114,7 +113,7 @@ func NewStructGenerator(responseFieldList ResponseFieldList) *StructGenerator { } } - currentFields, preMergedStructSources, postMergedStructSources = mergeFieldsRecursively(currentFields, fragmentChildrenFields, preMergedStructSources, postMergedStructSources) + currentFields, preMergedStructSources, postMergedStructSources := mergeFieldsRecursively(currentFields, fragmentChildrenFields, preMergedStructSources, nil) return &StructGenerator{ currentResponseFieldList: currentFields, preMergedStructSources: preMergedStructSources,