From ec08a5a918729518c1bc1d4d84293bf29d0238f8 Mon Sep 17 00:00:00 2001 From: sunboyy Date: Tue, 18 Oct 2022 19:37:50 +0700 Subject: [PATCH] Segregate base code generation logic to a new package (#31) --- internal/code/extractor_test.go | 30 +- internal/code/models.go | 9 + internal/code/models_test.go | 16 +- internal/codegen/base.go | 41 ++ internal/codegen/builder.go | 83 +++ internal/codegen/builder_test.go | 102 +++ internal/codegen/function.go | 73 ++ internal/codegen/function_test.go | 125 ++++ internal/codegen/method.go | 66 ++ internal/codegen/method_test.go | 142 ++++ internal/codegen/struct.go | 63 ++ internal/codegen/struct_test.go | 73 ++ internal/generator/generator.go | 75 +- internal/generator/generator_test.go | 32 +- internal/generator/templates.go | 9 - internal/mongo/generator.go | 132 ++-- internal/mongo/generator_test.go | 1024 ++++++++++++++------------ internal/mongo/templates.go | 66 +- internal/spec/errors_test.go | 6 +- internal/spec/parser.go | 16 +- internal/spec/parser_test.go | 512 ++++++------- main.go | 3 +- 22 files changed, 1761 insertions(+), 937 deletions(-) create mode 100644 internal/codegen/base.go create mode 100644 internal/codegen/builder.go create mode 100644 internal/codegen/builder_test.go create mode 100644 internal/codegen/function.go create mode 100644 internal/codegen/function_test.go create mode 100644 internal/codegen/method.go create mode 100644 internal/codegen/method_test.go create mode 100644 internal/codegen/struct.go create mode 100644 internal/codegen/struct_test.go delete mode 100644 internal/generator/templates.go diff --git a/internal/code/extractor_test.go b/internal/code/extractor_test.go index 2b12c33..18551e5 100644 --- a/internal/code/extractor_test.go +++ b/internal/code/extractor_test.go @@ -78,7 +78,7 @@ type UserModel struct { }, code.StructField{ Name: "Username", - Type: code.SimpleType("string"), + Type: code.TypeString, Tags: map[string][]string{ "bson": {"username"}, "json": {"username"}, @@ -120,7 +120,7 @@ type UserRepository interface { }, Returns: []code.Type{ code.PointerType{ContainedType: code.SimpleType("UserModel")}, - code.SimpleType("error"), + code.TypeError, }, }, { @@ -130,19 +130,19 @@ type UserRepository interface { }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, { Name: "FindByAgeBetween", Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Name: "fromAge", Type: code.SimpleType("int")}, - {Name: "toAge", Type: code.SimpleType("int")}, + {Name: "fromAge", Type: code.TypeInt}, + {Name: "toAge", Type: code.TypeInt}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, { @@ -153,19 +153,19 @@ type UserRepository interface { }, Returns: []code.Type{ code.InterfaceType{}, - code.SimpleType("error"), + code.TypeError, }, }, { Name: "UpdateAgreementByID", Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Name: "agreement", Type: code.MapType{KeyType: code.SimpleType("string"), ValueType: code.SimpleType("bool")}}, + {Name: "agreement", Type: code.MapType{KeyType: code.TypeString, ValueType: code.TypeBool}}, {Name: "id", Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("error"), + code.TypeBool, + code.TypeError, }, }, { @@ -178,7 +178,7 @@ type UserRepository interface { { Name: "Run", Params: []code.Param{ - {Name: "arg1", Type: code.SimpleType("int")}, + {Name: "arg1", Type: code.TypeInt}, }, }, }, @@ -191,7 +191,7 @@ type UserRepository interface { { Name: "Do", Params: []code.Param{ - {Name: "arg2", Type: code.SimpleType("string")}, + {Name: "arg2", Type: code.TypeString}, }, }, }, @@ -243,7 +243,7 @@ type UserRepository interface { }, code.StructField{ Name: "Username", - Type: code.SimpleType("string"), + Type: code.TypeString, Tags: map[string][]string{ "bson": {"username"}, "json": {"username"}, @@ -264,7 +264,7 @@ type UserRepository interface { }, Returns: []code.Type{ code.PointerType{ContainedType: code.SimpleType("UserModel")}, - code.SimpleType("error"), + code.TypeError, }, }, { @@ -274,7 +274,7 @@ type UserRepository interface { }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, }, diff --git a/internal/code/models.go b/internal/code/models.go index 17062ed..1ecc762 100644 --- a/internal/code/models.go +++ b/internal/code/models.go @@ -100,6 +100,15 @@ func (t SimpleType) IsNumber() bool { t == "float32" || t == "float64" } +// commonly-used types +const ( + TypeBool = SimpleType("bool") + TypeInt = SimpleType("int") + TypeFloat64 = SimpleType("float64") + TypeString = SimpleType("string") + TypeError = SimpleType("error") +) + // ExternalType is a type that is called to another package type ExternalType struct { PackageAlias string diff --git a/internal/code/models_test.go b/internal/code/models_test.go index 2dd734b..b64a337 100644 --- a/internal/code/models_test.go +++ b/internal/code/models_test.go @@ -9,7 +9,7 @@ import ( func TestStructFieldsByName(t *testing.T) { idField := code.StructField{Name: "ID", Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}} - usernameField := code.StructField{Name: "Username", Type: code.SimpleType("string")} + usernameField := code.StructField{Name: "Username", Type: code.TypeString} fields := code.StructFields{idField, usernameField} t.Run("struct field found", func(t *testing.T) { @@ -91,7 +91,7 @@ func TestTypeIsNumber(t *testing.T) { testTable := []TypeIsNumberTestCase{ { Name: "simple type: int", - Type: code.SimpleType("int"), + Type: code.TypeInt, IsNumber: true, }, { @@ -116,12 +116,12 @@ func TestTypeIsNumber(t *testing.T) { }, { Name: "simple type: other float variants", - Type: code.SimpleType("float64"), + Type: code.TypeFloat64, IsNumber: true, }, { Name: "simple type: non-number primitive type", - Type: code.SimpleType("string"), + Type: code.TypeString, IsNumber: false, }, { @@ -136,22 +136,22 @@ func TestTypeIsNumber(t *testing.T) { }, { Name: "pointer type: number", - Type: code.PointerType{ContainedType: code.SimpleType("int")}, + Type: code.PointerType{ContainedType: code.TypeInt}, IsNumber: true, }, { Name: "pointer type: non-number", - Type: code.PointerType{ContainedType: code.SimpleType("string")}, + Type: code.PointerType{ContainedType: code.TypeString}, IsNumber: false, }, { Name: "array type", - Type: code.ArrayType{ContainedType: code.SimpleType("int")}, + Type: code.ArrayType{ContainedType: code.TypeInt}, IsNumber: false, }, { Name: "map type", - Type: code.MapType{KeyType: code.SimpleType("int"), ValueType: code.SimpleType("float64")}, + Type: code.MapType{KeyType: code.TypeInt, ValueType: code.TypeFloat64}, IsNumber: false, }, { diff --git a/internal/codegen/base.go b/internal/codegen/base.go new file mode 100644 index 0000000..5508dc7 --- /dev/null +++ b/internal/codegen/base.go @@ -0,0 +1,41 @@ +package codegen + +import ( + "fmt" + "strings" + + "github.com/sunboyy/repogen/internal/code" +) + +const baseTemplate = `// Code generated by {{.Program}}. DO NOT EDIT. +package {{.PackageName}} + +import ( +{{.GenImports}} +) +` + +type baseTemplateData struct { + Program string + PackageName string + Imports [][]code.Import +} + +func (data baseTemplateData) GenImports() string { + var sections []string + for _, importSection := range data.Imports { + var section []string + for _, imp := range importSection { + section = append(section, data.generateImportLine(imp)) + } + sections = append(sections, strings.Join(section, "\n")) + } + return strings.Join(sections, "\n\n") +} + +func (data baseTemplateData) generateImportLine(imp code.Import) string { + if imp.Name == "" { + return fmt.Sprintf("\t\"%s\"", imp.Path) + } + return fmt.Sprintf("\t%s \"%s\"", imp.Name, imp.Path) +} diff --git a/internal/codegen/builder.go b/internal/codegen/builder.go new file mode 100644 index 0000000..a080921 --- /dev/null +++ b/internal/codegen/builder.go @@ -0,0 +1,83 @@ +package codegen + +import ( + "bytes" + "text/template" + + "github.com/sunboyy/repogen/internal/code" + "golang.org/x/tools/imports" +) + +type Builder struct { + // Program defines generator program name in the generated file. + Program string + + // PackageName defines the package name of the generated file. + PackageName string + + // Imports defines necessary imports to reduce ambiguity when generating + // formatting the raw-generated code. + Imports [][]code.Import + + implementers []Implementer +} + +// Implementer is an interface that wraps the basic Impl method for code +// generation. +type Implementer interface { + Impl(buffer *bytes.Buffer) error +} + +// NewBuilder is a constructor of Builder struct. +func NewBuilder(program string, packageName string, imports [][]code.Import) *Builder { + return &Builder{ + Program: program, + PackageName: packageName, + Imports: imports, + } +} + +// AddImplementer appends a new implemeneter to the implementer list. +func (b *Builder) AddImplementer(implementer Implementer) { + b.implementers = append(b.implementers, implementer) +} + +// Build generates code from the previously provided specifications. +func (b Builder) Build() (string, error) { + buffer := new(bytes.Buffer) + + if err := b.buildBase(buffer); err != nil { + return "", err + } + + for _, impl := range b.implementers { + if err := impl.Impl(buffer); err != nil { + return "", err + } + } + + formattedCode, err := imports.Process("", buffer.Bytes(), nil) + if err != nil { + return "", err + } + + return string(formattedCode), nil +} + +func (b Builder) buildBase(buffer *bytes.Buffer) error { + tmpl, err := template.New("file_base").Parse(baseTemplate) + if err != nil { + return err + } + + tmplData := baseTemplateData{ + Program: b.Program, + PackageName: b.PackageName, + Imports: b.Imports, + } + + // writing to a buffer should not cause errors. + _ = tmpl.Execute(buffer, tmplData) + + return nil +} diff --git a/internal/codegen/builder_test.go b/internal/codegen/builder_test.go new file mode 100644 index 0000000..8f69ba6 --- /dev/null +++ b/internal/codegen/builder_test.go @@ -0,0 +1,102 @@ +package codegen_test + +import ( + "testing" + + "github.com/sunboyy/repogen/internal/code" + "github.com/sunboyy/repogen/internal/codegen" + "github.com/sunboyy/repogen/internal/testutils" +) + +const expectedBuildCode = `// Code generated by repogen. DO NOT EDIT. +package user + +import ( + _ "context" + + "go.mongodb.org/mongo-driver/bson/primitive" + _ "go.mongodb.org/mongo-driver/mongo/options" +) + +type User struct { + ID primitive.ObjectID ` + "`bson:\"id\" json:\"id,omitempty\"`" + ` + Username string +} + +func NewUser(username string) User { + return User{ + ID: primitive.NewObjectID(), + Username: username, + } +} + +func (u User) IDHex() string { + return u.ID.Hex() +} +` + +func TestBuilderBuild(t *testing.T) { + builder := codegen.NewBuilder("repogen", "user", [][]code.Import{ + { + { + Name: "_", + Path: "context", + }, + }, + { + { + Path: "go.mongodb.org/mongo-driver/bson/primitive", + }, + { + Name: "_", + Path: "go.mongodb.org/mongo-driver/mongo/options", + }, + }, + }) + builder.AddImplementer(codegen.StructBuilder{ + Name: "User", + Fields: code.StructFields{ + { + Name: "ID", + Type: code.ExternalType{ + PackageAlias: "primitive", + Name: "ObjectID", + }, + Tags: map[string][]string{ + "bson": {"id"}, + "json": {"id", "omitempty"}, + }, + }, + { + Name: "Username", + Type: code.TypeString, + }, + }, + }) + builder.AddImplementer(codegen.FunctionBuilder{ + Name: "NewUser", + Params: []code.Param{ + {Name: "username", Type: code.TypeString}, + }, + Returns: []code.Type{code.SimpleType("User")}, + Body: ` return User{ + ID: primitive.NewObjectID(), + Username: username, + }`, + }) + builder.AddImplementer(codegen.MethodBuilder{ + Receiver: codegen.MethodReceiver{Name: "u", Type: code.SimpleType("User")}, + Name: "IDHex", + Params: nil, + Returns: []code.Type{code.TypeString}, + Body: " return u.ID.Hex()", + }) + + generatedCode, err := builder.Build() + if err != nil { + t.Fatal(err) + } + if err := testutils.ExpectMultiLineString(expectedBuildCode, generatedCode); err != nil { + t.Error(err) + } +} diff --git a/internal/codegen/function.go b/internal/codegen/function.go new file mode 100644 index 0000000..8f469c3 --- /dev/null +++ b/internal/codegen/function.go @@ -0,0 +1,73 @@ +package codegen + +import ( + "bytes" + "fmt" + "strings" + "text/template" + + "github.com/sunboyy/repogen/internal/code" +) + +const functionTemplate = ` +func {{.Name}}({{.GenParams}}){{.GenReturns}} { +{{.Body}} +} +` + +// FunctionBuilder is an implementer of a function. +type FunctionBuilder struct { + Name string + Params []code.Param + Returns []code.Type + Body string +} + +// Impl writes function declatation code to the buffer. +func (fb FunctionBuilder) Impl(buffer *bytes.Buffer) error { + tmpl, err := template.New("function").Parse(functionTemplate) + if err != nil { + return err + } + + // writing to a buffer should not cause errors. + _ = tmpl.Execute(buffer, fb) + + return nil +} + +func (fb FunctionBuilder) GenParams() string { + return generateParams(fb.Params) +} + +func (fb FunctionBuilder) GenReturns() string { + return generateReturns(fb.Returns) +} + +func generateParams(params []code.Param) string { + var paramList []string + for _, param := range params { + paramList = append( + paramList, + fmt.Sprintf("%s %s", param.Name, param.Type.Code()), + ) + } + return strings.Join(paramList, ", ") +} + +func generateReturns(returns []code.Type) string { + if len(returns) == 0 { + return "" + } + + if len(returns) == 1 { + return " " + returns[0].Code() + } + + var returnList []string + for _, ret := range returns { + returnList = append(returnList, ret.Code()) + } + + return fmt.Sprintf(" (%s)", strings.Join(returnList, ", ")) +} diff --git a/internal/codegen/function_test.go b/internal/codegen/function_test.go new file mode 100644 index 0000000..e14932b --- /dev/null +++ b/internal/codegen/function_test.go @@ -0,0 +1,125 @@ +package codegen_test + +import ( + "bytes" + "testing" + + "github.com/sunboyy/repogen/internal/code" + "github.com/sunboyy/repogen/internal/codegen" + "github.com/sunboyy/repogen/internal/testutils" +) + +func TestFunctionBuilderBuild_NoReturn(t *testing.T) { + fb := codegen.FunctionBuilder{ + Name: "init", + Params: nil, + Returns: nil, + Body: ` logrus.SetLevel(logrus.DebugLevel)`, + } + expectedCode := ` +func init() { + logrus.SetLevel(logrus.DebugLevel) +} +` + buffer := new(bytes.Buffer) + + err := fb.Impl(buffer) + + if err != nil { + t.Fatal(err) + } + actual := buffer.String() + if err := testutils.ExpectMultiLineString( + expectedCode, + actual, + ); err != nil { + t.Error(err) + } +} + +func TestFunctionBuilderBuild_OneReturn(t *testing.T) { + fb := codegen.FunctionBuilder{ + Name: "NewUser", + Params: []code.Param{ + { + Name: "username", + Type: code.TypeString, + }, + { + Name: "age", + Type: code.TypeInt, + }, + { + Name: "parent", + Type: code.PointerType{ContainedType: code.SimpleType("User")}, + }, + }, + Returns: []code.Type{ + code.SimpleType("User"), + }, + Body: ` return User{ + Username: username, + Age: age, + Parent: parent + }`, + } + expectedCode := ` +func NewUser(username string, age int, parent *User) User { + return User{ + Username: username, + Age: age, + Parent: parent + } +} +` + buffer := new(bytes.Buffer) + + err := fb.Impl(buffer) + + if err != nil { + t.Fatal(err) + } + actual := buffer.String() + if err := testutils.ExpectMultiLineString( + expectedCode, + actual, + ); err != nil { + t.Error(err) + } +} + +func TestFunctionBuilderBuild_MultiReturn(t *testing.T) { + fb := codegen.FunctionBuilder{ + Name: "Save", + Params: []code.Param{ + { + Name: "user", + Type: code.SimpleType("User"), + }, + }, + Returns: []code.Type{ + code.SimpleType("User"), + code.TypeError, + }, + Body: ` return collection.Save(user)`, + } + expectedCode := ` +func Save(user User) (User, error) { + return collection.Save(user) +} +` + buffer := new(bytes.Buffer) + + err := fb.Impl(buffer) + + if err != nil { + t.Fatal(err) + } + actual := buffer.String() + if err := testutils.ExpectMultiLineString( + expectedCode, + actual, + ); err != nil { + t.Error(err) + } +} diff --git a/internal/codegen/method.go b/internal/codegen/method.go new file mode 100644 index 0000000..874aa87 --- /dev/null +++ b/internal/codegen/method.go @@ -0,0 +1,66 @@ +package codegen + +import ( + "bytes" + "fmt" + "text/template" + + "github.com/sunboyy/repogen/internal/code" +) + +const methodTemplate = ` +func ({{.GenReceiver}}) {{.Name}}({{.GenParams}}){{.GenReturns}} { +{{.Body}} +} +` + +// MethodBuilder is an implementer of a method. +type MethodBuilder struct { + Receiver MethodReceiver + Name string + Params []code.Param + Returns []code.Type + Body string +} + +// MethodReceiver describes a specification of a method receiver. +type MethodReceiver struct { + Name string + Type code.SimpleType + Pointer bool +} + +// Impl writes method declatation code to the buffer. +func (mb MethodBuilder) Impl(buffer *bytes.Buffer) error { + tmpl, err := template.New("function").Parse(methodTemplate) + if err != nil { + return err + } + + // writing to a buffer should not cause errors. + _ = tmpl.Execute(buffer, mb) + + return nil +} + +func (mb MethodBuilder) GenReceiver() string { + if mb.Receiver.Name == "" { + return mb.generateReceiverType() + } + return fmt.Sprintf("%s %s", mb.Receiver.Name, mb.generateReceiverType()) +} + +func (mb MethodBuilder) generateReceiverType() string { + if !mb.Receiver.Pointer { + return mb.Receiver.Type.Code() + } + return code.PointerType{ContainedType: mb.Receiver.Type}.Code() +} + +func (mb MethodBuilder) GenParams() string { + return generateParams(mb.Params) +} + +func (mb MethodBuilder) GenReturns() string { + return generateReturns(mb.Returns) +} diff --git a/internal/codegen/method_test.go b/internal/codegen/method_test.go new file mode 100644 index 0000000..db73ed3 --- /dev/null +++ b/internal/codegen/method_test.go @@ -0,0 +1,142 @@ +package codegen_test + +import ( + "bytes" + "testing" + + "github.com/sunboyy/repogen/internal/code" + "github.com/sunboyy/repogen/internal/codegen" + "github.com/sunboyy/repogen/internal/testutils" +) + +func TestMethodBuilderBuild_IgnoreReceiverNoReturn(t *testing.T) { + fb := codegen.MethodBuilder{ + Receiver: codegen.MethodReceiver{Type: "User"}, + Name: "Init", + Params: nil, + Returns: nil, + Body: ` db.Init(&User{})`, + } + expectedCode := ` +func (User) Init() { + db.Init(&User{}) +} +` + buffer := new(bytes.Buffer) + + err := fb.Impl(buffer) + + if err != nil { + t.Fatal(err) + } + actual := buffer.String() + if err := testutils.ExpectMultiLineString( + expectedCode, + actual, + ); err != nil { + t.Error(err) + } +} + +func TestMethodBuilderBuild_IgnorePoinerReceiverOneReturn(t *testing.T) { + fb := codegen.MethodBuilder{ + Receiver: codegen.MethodReceiver{ + Type: "User", + Pointer: true, + }, + Name: "Init", + Params: nil, + Returns: []code.Type{code.TypeError}, + Body: ` return db.Init(&User{})`, + } + expectedCode := ` +func (*User) Init() error { + return db.Init(&User{}) +} +` + buffer := new(bytes.Buffer) + + err := fb.Impl(buffer) + + if err != nil { + t.Fatal(err) + } + actual := buffer.String() + if err := testutils.ExpectMultiLineString( + expectedCode, + actual, + ); err != nil { + t.Error(err) + } +} + +func TestMethodBuilderBuild_UseReceiverMultiReturn(t *testing.T) { + fb := codegen.MethodBuilder{ + Receiver: codegen.MethodReceiver{ + Name: "u", + Type: "User", + }, + Name: "WithAge", + Params: []code.Param{ + {Name: "age", Type: code.TypeInt}, + }, + Returns: []code.Type{code.SimpleType("User"), code.TypeError}, + Body: ` u.Age = age + return u`, + } + expectedCode := ` +func (u User) WithAge(age int) (User, error) { + u.Age = age + return u +} +` + buffer := new(bytes.Buffer) + + err := fb.Impl(buffer) + + if err != nil { + t.Fatal(err) + } + actual := buffer.String() + if err := testutils.ExpectMultiLineString( + expectedCode, + actual, + ); err != nil { + t.Error(err) + } +} + +func TestMethodBuilderBuild_UsePointerReceiverNoReturn(t *testing.T) { + fb := codegen.MethodBuilder{ + Receiver: codegen.MethodReceiver{ + Name: "u", + Type: "User", + Pointer: true, + }, + Name: "SetAge", + Params: []code.Param{ + {Name: "age", Type: code.TypeInt}, + }, + Returns: nil, + Body: ` u.Age = age`, + } + expectedCode := ` +func (u *User) SetAge(age int) { + u.Age = age +} +` + buffer := new(bytes.Buffer) + + err := fb.Impl(buffer) + + if err != nil { + t.Fatal(err) + } + actual := buffer.String() + if err := testutils.ExpectMultiLineString( + expectedCode, + actual, + ); err != nil { + t.Error(err) + } +} diff --git a/internal/codegen/struct.go b/internal/codegen/struct.go new file mode 100644 index 0000000..300468d --- /dev/null +++ b/internal/codegen/struct.go @@ -0,0 +1,63 @@ +package codegen + +import ( + "bytes" + "fmt" + "sort" + "strings" + "text/template" + + "github.com/sunboyy/repogen/internal/code" +) + +const structTemplate = ` +type {{.Name}} struct { +{{.GenFields}} +} +` + +// StructBuilder is an implementer of a struct. +type StructBuilder struct { + Name string + Fields code.StructFields +} + +// Impl writes struct declatation code to the buffer. +func (sb StructBuilder) Impl(buffer *bytes.Buffer) error { + tmpl, err := template.New("struct").Parse(structTemplate) + if err != nil { + return err + } + + // writing to a buffer should not cause errors. + _ = tmpl.Execute(buffer, sb) + + return nil +} + +func (sb StructBuilder) GenFields() string { + var fieldLines []string + for _, field := range sb.Fields { + fieldLine := fmt.Sprintf("\t%s %s", field.Name, field.Type.Code()) + if len(field.Tags) > 0 { + fieldLine += fmt.Sprintf(" `%s`", sb.generateStructTag(field.Tags)) + } + fieldLines = append(fieldLines, fieldLine) + } + return strings.Join(fieldLines, "\n") +} + +func (sb StructBuilder) generateStructTag(tags map[string][]string) string { + var tagKeys []string + for key := range tags { + tagKeys = append(tagKeys, key) + } + sort.Strings(tagKeys) + + var tagGroups []string + for _, key := range tagKeys { + tagValue := strings.Join(tags[key], ",") + tagGroups = append(tagGroups, fmt.Sprintf("%s:\"%s\"", key, tagValue)) + } + return strings.Join(tagGroups, " ") +} diff --git a/internal/codegen/struct_test.go b/internal/codegen/struct_test.go new file mode 100644 index 0000000..588366c --- /dev/null +++ b/internal/codegen/struct_test.go @@ -0,0 +1,73 @@ +package codegen_test + +import ( + "bytes" + "testing" + + "github.com/sunboyy/repogen/internal/code" + "github.com/sunboyy/repogen/internal/codegen" + "github.com/sunboyy/repogen/internal/testutils" +) + +const expectedStructBuilderCode = ` +type User struct { + ID primitive.ObjectID ` + "`bson:\"id,omitempty\" json:\"id,omitempty\"`" + ` + Username string ` + "`bson:\"username\" json:\"username\"`" + ` + Age int ` + "`bson:\"age\"`" + ` + orderCount *int +} +` + +func TestStructBuilderBuild(t *testing.T) { + sb := codegen.StructBuilder{ + Name: "User", + Fields: []code.StructField{ + { + Name: "ID", + Type: code.ExternalType{ + PackageAlias: "primitive", + Name: "ObjectID", + }, + Tags: map[string][]string{ + "json": {"id", "omitempty"}, + "bson": {"id", "omitempty"}, + }, + }, + { + Name: "Username", + Type: code.TypeString, + Tags: map[string][]string{ + "json": {"username"}, + "bson": {"username"}, + }, + }, + { + Name: "Age", + Type: code.TypeInt, + Tags: map[string][]string{ + "bson": {"age"}, + }, + }, + { + Name: "orderCount", + Type: code.PointerType{ + ContainedType: code.TypeInt, + }, + }, + }, + } + buffer := new(bytes.Buffer) + + err := sb.Impl(buffer) + + if err != nil { + t.Fatal(err) + } + actual := buffer.String() + if err := testutils.ExpectMultiLineString( + expectedStructBuilderCode, + actual, + ); err != nil { + t.Error(err) + } +} diff --git a/internal/generator/generator.go b/internal/generator/generator.go index 42cc54d..1fa7d4b 100644 --- a/internal/generator/generator.go +++ b/internal/generator/generator.go @@ -1,75 +1,40 @@ package generator import ( - "bytes" - "html/template" - "github.com/sunboyy/repogen/internal/code" + "github.com/sunboyy/repogen/internal/codegen" "github.com/sunboyy/repogen/internal/mongo" "github.com/sunboyy/repogen/internal/spec" - "golang.org/x/tools/imports" ) -// GenerateRepository generates repository implementation from repository interface specification -func GenerateRepository(packageName string, structModel code.Struct, interfaceName string, - methodSpecs []spec.MethodSpec) (string, error) { +// GenerateRepository generates repository implementation code from repository +// interface specification. +func GenerateRepository(packageName string, structModel code.Struct, + interfaceName string, methodSpecs []spec.MethodSpec) (string, error) { - repositoryGenerator := repositoryGenerator{ - PackageName: packageName, - StructModel: structModel, - InterfaceName: interfaceName, - MethodSpecs: methodSpecs, - Generator: mongo.NewGenerator(structModel, interfaceName), - } + generator := mongo.NewGenerator(structModel, interfaceName) - return repositoryGenerator.Generate() -} + codeBuilder := codegen.NewBuilder( + "repogen", + packageName, + generator.Imports(), + ) -type repositoryGenerator struct { - PackageName string - StructModel code.Struct - InterfaceName string - MethodSpecs []spec.MethodSpec - Generator mongo.RepositoryGenerator -} - -func (g repositoryGenerator) Generate() (string, error) { - buffer := new(bytes.Buffer) - if err := g.generateBase(buffer); err != nil { + constructorBuilder, err := generator.GenerateConstructor() + if err != nil { return "", err } - if err := g.Generator.GenerateConstructor(buffer); err != nil { - return "", err - } + codeBuilder.AddImplementer(constructorBuilder) + codeBuilder.AddImplementer(generator.GenerateStruct()) - for _, method := range g.MethodSpecs { - if err := g.Generator.GenerateMethod(method, buffer); err != nil { + for _, method := range methodSpecs { + methodBuilder, err := generator.GenerateMethod(method) + if err != nil { return "", err } + codeBuilder.AddImplementer(methodBuilder) } - formattedCode, err := imports.Process("", buffer.Bytes(), nil) - if err != nil { - return "", err - } - - return string(formattedCode), nil -} - -func (g repositoryGenerator) generateBase(buffer *bytes.Buffer) error { - tmpl, err := template.New("file_base").Parse(baseTemplate) - if err != nil { - return err - } - - tmplData := baseTemplateData{ - PackageName: g.PackageName, - } - - if err := tmpl.Execute(buffer, tmplData); err != nil { - return err - } - - return nil + return codeBuilder.Build() } diff --git a/internal/generator/generator_test.go b/internal/generator/generator_test.go index 0e2a981..e0b67e7 100644 --- a/internal/generator/generator_test.go +++ b/internal/generator/generator_test.go @@ -22,7 +22,7 @@ var ( } ageField = code.StructField{ Name: "Age", - Type: code.SimpleType("int"), + Type: code.TypeInt, Tags: map[string][]string{"bson": {"age"}}, } ) @@ -34,7 +34,7 @@ func TestGenerateMongoRepository(t *testing.T) { idField, code.StructField{ Name: "Username", - Type: code.SimpleType("string"), + Type: code.TypeString, Tags: map[string][]string{"bson": {"username"}}, }, genderField, @@ -49,7 +49,7 @@ func TestGenerateMongoRepository(t *testing.T) { {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, {Name: "id", Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, - Returns: []code.Type{code.PointerType{ContainedType: code.SimpleType("UserModel")}, code.SimpleType("error")}, + Returns: []code.Type{code.PointerType{ContainedType: code.SimpleType("UserModel")}, code.TypeError}, Operation: spec.FindOperation{ Mode: spec.QueryModeOne, Query: spec.QuerySpec{ @@ -65,11 +65,11 @@ func TestGenerateMongoRepository(t *testing.T) { Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, {Name: "gender", Type: code.SimpleType("Gender")}, - {Name: "age", Type: code.SimpleType("int")}, + {Name: "age", Type: code.TypeInt}, }, Returns: []code.Type{ code.PointerType{ContainedType: code.SimpleType("UserModel")}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeMany, @@ -86,11 +86,11 @@ func TestGenerateMongoRepository(t *testing.T) { Name: "FindByAgeLessThanEqualOrderByAge", Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Name: "age", Type: code.SimpleType("int")}, + {Name: "age", Type: code.TypeInt}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeMany, @@ -108,11 +108,11 @@ func TestGenerateMongoRepository(t *testing.T) { Name: "FindByAgeGreaterThanOrderByAgeAsc", Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Name: "age", Type: code.SimpleType("int")}, + {Name: "age", Type: code.TypeInt}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeMany, @@ -130,11 +130,11 @@ func TestGenerateMongoRepository(t *testing.T) { Name: "FindByAgeGreaterThanEqualOrderByAgeDesc", Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Name: "age", Type: code.SimpleType("int")}, + {Name: "age", Type: code.TypeInt}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeMany, @@ -152,12 +152,12 @@ func TestGenerateMongoRepository(t *testing.T) { Name: "FindByAgeBetween", Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Name: "fromAge", Type: code.SimpleType("int")}, - {Name: "toAge", Type: code.SimpleType("int")}, + {Name: "fromAge", Type: code.TypeInt}, + {Name: "toAge", Type: code.TypeInt}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeMany, @@ -173,11 +173,11 @@ func TestGenerateMongoRepository(t *testing.T) { Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, {Name: "gender", Type: code.SimpleType("Gender")}, - {Name: "age", Type: code.SimpleType("int")}, + {Name: "age", Type: code.TypeInt}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeMany, diff --git a/internal/generator/templates.go b/internal/generator/templates.go deleted file mode 100644 index 3fb9b3d..0000000 --- a/internal/generator/templates.go +++ /dev/null @@ -1,9 +0,0 @@ -package generator - -const baseTemplate = `// Code generated by repogen. DO NOT EDIT. -package {{.PackageName}} -` - -type baseTemplateData struct { - PackageName string -} diff --git a/internal/mongo/generator.go b/internal/mongo/generator.go index bde2b5a..19d3b85 100644 --- a/internal/mongo/generator.go +++ b/internal/mongo/generator.go @@ -2,11 +2,12 @@ package mongo import ( "bytes" - "io" + "fmt" "strings" "text/template" "github.com/sunboyy/repogen/internal/code" + "github.com/sunboyy/repogen/internal/codegen" "github.com/sunboyy/repogen/internal/spec" ) @@ -24,55 +25,104 @@ type RepositoryGenerator struct { InterfaceName string } -// GenerateConstructor generates mongo repository struct implementation and constructor for the struct -func (g RepositoryGenerator) GenerateConstructor(buffer io.Writer) error { - tmpl, err := template.New("mongo_repository_base").Parse(constructorTemplate) - if err != nil { - return err +// Imports returns necessary imports for the mongo repository implementation. +func (g RepositoryGenerator) Imports() [][]code.Import { + return [][]code.Import{ + { + {Path: "context"}, + }, + { + {Path: "go.mongodb.org/mongo-driver/bson"}, + {Path: "go.mongodb.org/mongo-driver/bson/primitive"}, + {Path: "go.mongodb.org/mongo-driver/mongo"}, + {Path: "go.mongodb.org/mongo-driver/mongo/options"}, + }, } - - tmplData := mongoConstructorTemplateData{ - InterfaceName: g.InterfaceName, - ImplStructName: g.structName(), - } - - if err := tmpl.Execute(buffer, tmplData); err != nil { - return err - } - - return nil } -// GenerateMethod generates implementation of from provided method specification -func (g RepositoryGenerator) GenerateMethod(methodSpec spec.MethodSpec, buffer io.Writer) error { - tmpl, err := template.New("mongo_repository_method").Parse(methodTemplate) +// GenerateStruct creates codegen.StructBuilder of mongo repository +// implementation struct. +func (g RepositoryGenerator) GenerateStruct() codegen.StructBuilder { + return codegen.StructBuilder{ + Name: g.repoImplStructName(), + Fields: code.StructFields{ + { + Name: "collection", + Type: code.PointerType{ + ContainedType: code.ExternalType{ + PackageAlias: "mongo", + Name: "Collection", + }, + }, + }, + }, + } +} + +// GenerateConstructor creates codegen.FunctionBuilder of a constructor for +// mongo repository implementation struct. +func (g RepositoryGenerator) GenerateConstructor() (codegen.FunctionBuilder, error) { + tmpl, err := template.New("mongo_constructor_body").Parse(constructorBody) if err != nil { - return err + return codegen.FunctionBuilder{}, err + } + + tmplData := constructorBodyData{ + ImplStructName: g.repoImplStructName(), + } + + buffer := new(bytes.Buffer) + if err := tmpl.Execute(buffer, tmplData); err != nil { + return codegen.FunctionBuilder{}, err + } + + return codegen.FunctionBuilder{ + Name: "New" + g.InterfaceName, + Params: []code.Param{ + { + Name: "collection", + Type: code.PointerType{ + ContainedType: code.ExternalType{ + PackageAlias: "mongo", + Name: "Collection", + }, + }, + }, + }, + Returns: []code.Type{ + code.SimpleType(g.InterfaceName), + }, + Body: buffer.String(), + }, nil +} + +// GenerateMethod creates codegen.MethodBuilder of repository method from the +// provided method specification. +func (g RepositoryGenerator) GenerateMethod(methodSpec spec.MethodSpec) (codegen.MethodBuilder, error) { + var params []code.Param + for i, param := range methodSpec.Params { + params = append(params, code.Param{ + Name: fmt.Sprintf("arg%d", i), + Type: param.Type, + }) } implementation, err := g.generateMethodImplementation(methodSpec) if err != nil { - return err + return codegen.MethodBuilder{}, err } - var paramTypes []code.Type - for _, param := range methodSpec.Params { - paramTypes = append(paramTypes, param.Type) - } - - tmplData := mongoMethodTemplateData{ - StructName: g.structName(), - MethodName: methodSpec.Name, - ParamTypes: paramTypes, - ReturnTypes: methodSpec.Returns, - Implementation: implementation, - } - - if err := tmpl.Execute(buffer, tmplData); err != nil { - return err - } - - return nil + return codegen.MethodBuilder{ + Receiver: codegen.MethodReceiver{ + Name: "r", + Type: code.SimpleType(g.repoImplStructName()), + Pointer: true, + }, + Name: methodSpec.Name, + Params: params, + Returns: methodSpec.Returns, + Body: implementation, + }, nil } func (g RepositoryGenerator) generateMethodImplementation(methodSpec spec.MethodSpec) (string, error) { @@ -275,7 +325,7 @@ func (g RepositoryGenerator) bsonTagFromField(field code.StructField) (string, e return bsonTag[0], nil } -func (g RepositoryGenerator) structName() string { +func (g RepositoryGenerator) repoImplStructName() string { return g.InterfaceName + "Mongo" } diff --git a/internal/mongo/generator_test.go b/internal/mongo/generator_test.go index c6d2092..bc9490f 100644 --- a/internal/mongo/generator_test.go +++ b/internal/mongo/generator_test.go @@ -1,10 +1,12 @@ package mongo_test import ( - "bytes" + "fmt" + "reflect" "testing" "github.com/sunboyy/repogen/internal/code" + "github.com/sunboyy/repogen/internal/codegen" "github.com/sunboyy/repogen/internal/mongo" "github.com/sunboyy/repogen/internal/spec" "github.com/sunboyy/repogen/internal/testutils" @@ -23,7 +25,7 @@ var ( } ageField = code.StructField{ Name: "Age", - Type: code.SimpleType("int"), + Type: code.TypeInt, Tags: map[string][]string{"bson": {"age"}}, } nameField = code.StructField{ @@ -38,17 +40,17 @@ var ( } enabledField = code.StructField{ Name: "Enabled", - Type: code.SimpleType("bool"), + Type: code.TypeBool, Tags: map[string][]string{"bson": {"enabled"}}, } accessTokenField = code.StructField{ Name: "AccessToken", - Type: code.SimpleType("string"), + Type: code.TypeString, } firstNameField = code.StructField{ Name: "First", - Type: code.SimpleType("string"), + Type: code.TypeString, Tags: map[string][]string{"bson": {"first"}}, } ) @@ -59,7 +61,7 @@ var userModel = code.Struct{ idField, code.StructField{ Name: "Username", - Type: code.SimpleType("string"), + Type: code.TypeString, Tags: map[string][]string{"bson": {"username"}}, }, genderField, @@ -71,37 +73,107 @@ var userModel = code.Struct{ }, } -const expectedConstructorResult = ` -import ( - "context" - - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" -) - -func NewUserRepository(collection *mongo.Collection) UserRepository { - return &UserRepositoryMongo{ +const expectedConstructorBody = ` return &UserRepositoryMongo{ collection: collection, + }` + +func TestImports(t *testing.T) { + generator := mongo.NewGenerator(userModel, "UserRepository") + expected := [][]code.Import{ + { + {Path: "context"}, + }, + { + {Path: "go.mongodb.org/mongo-driver/bson"}, + {Path: "go.mongodb.org/mongo-driver/bson/primitive"}, + {Path: "go.mongodb.org/mongo-driver/mongo"}, + {Path: "go.mongodb.org/mongo-driver/mongo/options"}, + }, + } + + actual := generator.Imports() + + if !reflect.DeepEqual(expected, actual) { + t.Errorf("incorrect imports: expected %+v, got %+v", expected, actual) } } -type UserRepositoryMongo struct { - collection *mongo.Collection +func TestGenerateStruct(t *testing.T) { + generator := mongo.NewGenerator(userModel, "UserRepository") + expected := codegen.StructBuilder{ + Name: "UserRepositoryMongo", + Fields: []code.StructField{ + { + Name: "collection", + Type: code.PointerType{ + ContainedType: code.ExternalType{ + PackageAlias: "mongo", + Name: "Collection", + }, + }, + }, + }, + } + + actual := generator.GenerateStruct() + + if expected.Name != actual.Name { + t.Errorf( + "incorrect struct name: expected %s, got %s", + expected.Name, + actual.Name, + ) + } + if !reflect.DeepEqual(expected.Fields, actual.Fields) { + t.Errorf( + "incorrect struct fields: expected %+v, got %+v", + expected.Fields, + actual.Fields, + ) + } } -` func TestGenerateConstructor(t *testing.T) { generator := mongo.NewGenerator(userModel, "UserRepository") - buffer := new(bytes.Buffer) + expected := codegen.FunctionBuilder{ + Name: "NewUserRepository", + Params: []code.Param{ + { + Name: "collection", + Type: code.PointerType{ + ContainedType: code.ExternalType{ + PackageAlias: "mongo", + Name: "Collection", + }, + }, + }, + }, + Returns: []code.Type{ + code.SimpleType("UserRepository"), + }, + Body: expectedConstructorBody, + } - err := generator.GenerateConstructor(buffer) + actual, err := generator.GenerateConstructor() if err != nil { - t.Error(err) + t.Fatal(err) } - if err := testutils.ExpectMultiLineString(expectedConstructorResult, buffer.String()); err != nil { + if expected.Name != actual.Name { + t.Errorf( + "incorrect function name: expected %s, got %s", + expected.Name, + actual.Name, + ) + } + if !reflect.DeepEqual(expected.Params, actual.Params) { + t.Errorf( + "incorrect struct params: expected %+v, got %+v", + expected.Params, + actual.Params, + ) + } + if err := testutils.ExpectMultiLineString(expected.Body, actual.Body); err != nil { t.Error(err) } } @@ -109,7 +181,7 @@ func TestGenerateConstructor(t *testing.T) { type GenerateMethodTestCase struct { Name string MethodSpec spec.MethodSpec - ExpectedCode string + ExpectedBody string } func TestGenerateMethod_Insert(t *testing.T) { @@ -124,21 +196,17 @@ func TestGenerateMethod_Insert(t *testing.T) { }, Returns: []code.Type{ code.InterfaceType{}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.InsertOperation{ Mode: spec.QueryModeOne, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) InsertOne(arg0 context.Context, arg1 *UserModel) (interface{}, error) { - result, err := r.collection.InsertOne(arg0, arg1) + ExpectedBody: ` result, err := r.collection.InsertOne(arg0, arg1) if err != nil { return nil, err } - return result.InsertedID, nil -} -`, + return result.InsertedID, nil`, }, { Name: "insert many method", @@ -152,15 +220,13 @@ func (r *UserRepositoryMongo) InsertOne(arg0 context.Context, arg1 *UserModel) ( }, Returns: []code.Type{ code.ArrayType{ContainedType: code.InterfaceType{}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.InsertOperation{ Mode: spec.QueryModeMany, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) Insert(arg0 context.Context, arg1 []*UserModel) ([]interface{}, error) { - var entities []interface{} + ExpectedBody: ` var entities []interface{} for _, model := range arg1 { entities = append(entities, model) } @@ -168,23 +234,66 @@ func (r *UserRepositoryMongo) Insert(arg0 context.Context, arg1 []*UserModel) ([ if err != nil { return nil, err } - return result.InsertedIDs, nil -} -`, + return result.InsertedIDs, nil`, }, } for _, testCase := range testTable { t.Run(testCase.Name, func(t *testing.T) { generator := mongo.NewGenerator(userModel, "UserRepository") - buffer := new(bytes.Buffer) + var expectedParams []code.Param + for i, param := range testCase.MethodSpec.Params { + expectedParams = append(expectedParams, code.Param{ + Name: fmt.Sprintf("arg%d", i), + Type: param.Type, + }) + } + expected := codegen.MethodBuilder{ + Receiver: codegen.MethodReceiver{ + Name: "r", + Type: "UserRepositoryMongo", + Pointer: true, + }, + Name: testCase.MethodSpec.Name, + Params: expectedParams, + Returns: testCase.MethodSpec.Returns, + Body: testCase.ExpectedBody, + } - err := generator.GenerateMethod(testCase.MethodSpec, buffer) + actual, err := generator.GenerateMethod(testCase.MethodSpec) if err != nil { - t.Error(err) + t.Fatal(err) } - if err := testutils.ExpectMultiLineString(testCase.ExpectedCode, buffer.String()); err != nil { + if expected.Receiver != actual.Receiver { + t.Errorf( + "incorrect method receiver: expected %+v, got %+v", + expected.Receiver, + actual.Receiver, + ) + } + if expected.Name != actual.Name { + t.Errorf( + "incorrect method name: expected %s, got %s", + expected.Name, + actual.Name, + ) + } + if !reflect.DeepEqual(expected.Params, actual.Params) { + t.Errorf( + "incorrect struct params: expected %+v, got %+v", + expected.Params, + actual.Params, + ) + } + if !reflect.DeepEqual(expected.Returns, actual.Returns) { + t.Errorf( + "incorrect struct returns: expected %+v, got %+v", + expected.Returns, + actual.Returns, + ) + } + if err := testutils.ExpectMultiLineString(expected.Body, actual.Body); err != nil { t.Error(err) } }) @@ -203,7 +312,7 @@ func TestGenerateMethod_Find(t *testing.T) { }, Returns: []code.Type{ code.PointerType{ContainedType: code.SimpleType("UserModel")}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeOne, @@ -214,18 +323,14 @@ func TestGenerateMethod_Find(t *testing.T) { }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) FindByID(arg0 context.Context, arg1 primitive.ObjectID) (*UserModel, error) { - var entity UserModel + ExpectedBody: ` var entity UserModel if err := r.collection.FindOne(arg0, bson.M{ "_id": arg1, }, options.FindOne().SetSort(bson.M{ })).Decode(&entity); err != nil { return nil, err } - return &entity, nil -} -`, + return &entity, nil`, }, { Name: "simple find many method", @@ -237,7 +342,7 @@ func (r *UserRepositoryMongo) FindByID(arg0 context.Context, arg1 primitive.Obje }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeMany, @@ -248,9 +353,7 @@ func (r *UserRepositoryMongo) FindByID(arg0 context.Context, arg1 primitive.Obje }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) FindByGender(arg0 context.Context, arg1 Gender) ([]*UserModel, error) { - cursor, err := r.collection.Find(arg0, bson.M{ + ExpectedBody: ` cursor, err := r.collection.Find(arg0, bson.M{ "gender": arg1, }, options.Find().SetSort(bson.M{ })) @@ -261,9 +364,7 @@ func (r *UserRepositoryMongo) FindByGender(arg0 context.Context, arg1 Gender) ([ if err := cursor.All(arg0, &entities); err != nil { return nil, err } - return entities, nil -} -`, + return entities, nil`, }, { Name: "find with deep field reference", @@ -271,11 +372,11 @@ func (r *UserRepositoryMongo) FindByGender(arg0 context.Context, arg1 Gender) ([ Name: "FindByNameFirst", Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Name: "firstName", Type: code.SimpleType("string")}, + {Name: "firstName", Type: code.TypeString}, }, Returns: []code.Type{ code.PointerType{ContainedType: code.SimpleType("UserModel")}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeOne, @@ -290,18 +391,14 @@ func (r *UserRepositoryMongo) FindByGender(arg0 context.Context, arg1 Gender) ([ }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) FindByNameFirst(arg0 context.Context, arg1 string) (*UserModel, error) { - var entity UserModel + ExpectedBody: ` var entity UserModel if err := r.collection.FindOne(arg0, bson.M{ "name.first": arg1, }, options.FindOne().SetSort(bson.M{ })).Decode(&entity); err != nil { return nil, err } - return &entity, nil -} -`, + return &entity, nil`, }, { Name: "find with And operator", @@ -310,11 +407,11 @@ func (r *UserRepositoryMongo) FindByNameFirst(arg0 context.Context, arg1 string) Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, {Name: "gender", Type: code.SimpleType("Gender")}, - {Name: "age", Type: code.SimpleType("int")}, + {Name: "age", Type: code.TypeInt}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeMany, @@ -327,9 +424,7 @@ func (r *UserRepositoryMongo) FindByNameFirst(arg0 context.Context, arg1 string) }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) FindByGenderAndAge(arg0 context.Context, arg1 Gender, arg2 int) ([]*UserModel, error) { - cursor, err := r.collection.Find(arg0, bson.M{ + ExpectedBody: ` cursor, err := r.collection.Find(arg0, bson.M{ "$and": []bson.M{ {"gender": arg1}, {"age": arg2}, @@ -343,9 +438,7 @@ func (r *UserRepositoryMongo) FindByGenderAndAge(arg0 context.Context, arg1 Gend if err := cursor.All(arg0, &entities); err != nil { return nil, err } - return entities, nil -} -`, + return entities, nil`, }, { Name: "find with Or operator", @@ -354,11 +447,11 @@ func (r *UserRepositoryMongo) FindByGenderAndAge(arg0 context.Context, arg1 Gend Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, {Name: "gender", Type: code.SimpleType("Gender")}, - {Name: "age", Type: code.SimpleType("int")}, + {Name: "age", Type: code.TypeInt}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeMany, @@ -371,9 +464,7 @@ func (r *UserRepositoryMongo) FindByGenderAndAge(arg0 context.Context, arg1 Gend }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) FindByGenderOrAge(arg0 context.Context, arg1 Gender, arg2 int) ([]*UserModel, error) { - cursor, err := r.collection.Find(arg0, bson.M{ + ExpectedBody: ` cursor, err := r.collection.Find(arg0, bson.M{ "$or": []bson.M{ {"gender": arg1}, {"age": arg2}, @@ -387,9 +478,7 @@ func (r *UserRepositoryMongo) FindByGenderOrAge(arg0 context.Context, arg1 Gende if err := cursor.All(arg0, &entities); err != nil { return nil, err } - return entities, nil -} -`, + return entities, nil`, }, { Name: "find with Not comparator", @@ -401,7 +490,7 @@ func (r *UserRepositoryMongo) FindByGenderOrAge(arg0 context.Context, arg1 Gende }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeMany, @@ -412,9 +501,7 @@ func (r *UserRepositoryMongo) FindByGenderOrAge(arg0 context.Context, arg1 Gende }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) FindByGenderNot(arg0 context.Context, arg1 Gender) ([]*UserModel, error) { - cursor, err := r.collection.Find(arg0, bson.M{ + ExpectedBody: ` cursor, err := r.collection.Find(arg0, bson.M{ "gender": bson.M{"$ne": arg1}, }, options.Find().SetSort(bson.M{ })) @@ -425,9 +512,7 @@ func (r *UserRepositoryMongo) FindByGenderNot(arg0 context.Context, arg1 Gender) if err := cursor.All(arg0, &entities); err != nil { return nil, err } - return entities, nil -} -`, + return entities, nil`, }, { Name: "find with LessThan comparator", @@ -435,11 +520,11 @@ func (r *UserRepositoryMongo) FindByGenderNot(arg0 context.Context, arg1 Gender) Name: "FindByAgeLessThan", Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Name: "age", Type: code.SimpleType("int")}, + {Name: "age", Type: code.TypeInt}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeMany, @@ -450,9 +535,7 @@ func (r *UserRepositoryMongo) FindByGenderNot(arg0 context.Context, arg1 Gender) }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) FindByAgeLessThan(arg0 context.Context, arg1 int) ([]*UserModel, error) { - cursor, err := r.collection.Find(arg0, bson.M{ + ExpectedBody: ` cursor, err := r.collection.Find(arg0, bson.M{ "age": bson.M{"$lt": arg1}, }, options.Find().SetSort(bson.M{ })) @@ -463,9 +546,7 @@ func (r *UserRepositoryMongo) FindByAgeLessThan(arg0 context.Context, arg1 int) if err := cursor.All(arg0, &entities); err != nil { return nil, err } - return entities, nil -} -`, + return entities, nil`, }, { Name: "find with LessThanEqual comparator", @@ -473,11 +554,11 @@ func (r *UserRepositoryMongo) FindByAgeLessThan(arg0 context.Context, arg1 int) Name: "FindByAgeLessThanEqual", Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Name: "age", Type: code.SimpleType("int")}, + {Name: "age", Type: code.TypeInt}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeMany, @@ -488,9 +569,7 @@ func (r *UserRepositoryMongo) FindByAgeLessThan(arg0 context.Context, arg1 int) }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) FindByAgeLessThanEqual(arg0 context.Context, arg1 int) ([]*UserModel, error) { - cursor, err := r.collection.Find(arg0, bson.M{ + ExpectedBody: ` cursor, err := r.collection.Find(arg0, bson.M{ "age": bson.M{"$lte": arg1}, }, options.Find().SetSort(bson.M{ })) @@ -501,9 +580,7 @@ func (r *UserRepositoryMongo) FindByAgeLessThanEqual(arg0 context.Context, arg1 if err := cursor.All(arg0, &entities); err != nil { return nil, err } - return entities, nil -} -`, + return entities, nil`, }, { Name: "find with GreaterThan comparator", @@ -511,11 +588,11 @@ func (r *UserRepositoryMongo) FindByAgeLessThanEqual(arg0 context.Context, arg1 Name: "FindByAgeGreaterThan", Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Name: "age", Type: code.SimpleType("int")}, + {Name: "age", Type: code.TypeInt}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeMany, @@ -526,9 +603,7 @@ func (r *UserRepositoryMongo) FindByAgeLessThanEqual(arg0 context.Context, arg1 }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) FindByAgeGreaterThan(arg0 context.Context, arg1 int) ([]*UserModel, error) { - cursor, err := r.collection.Find(arg0, bson.M{ + ExpectedBody: ` cursor, err := r.collection.Find(arg0, bson.M{ "age": bson.M{"$gt": arg1}, }, options.Find().SetSort(bson.M{ })) @@ -539,9 +614,7 @@ func (r *UserRepositoryMongo) FindByAgeGreaterThan(arg0 context.Context, arg1 in if err := cursor.All(arg0, &entities); err != nil { return nil, err } - return entities, nil -} -`, + return entities, nil`, }, { Name: "find with GreaterThanEqual comparator", @@ -549,11 +622,11 @@ func (r *UserRepositoryMongo) FindByAgeGreaterThan(arg0 context.Context, arg1 in Name: "FindByAgeGreaterThanEqual", Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Name: "age", Type: code.SimpleType("int")}, + {Name: "age", Type: code.TypeInt}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeMany, @@ -564,9 +637,7 @@ func (r *UserRepositoryMongo) FindByAgeGreaterThan(arg0 context.Context, arg1 in }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) FindByAgeGreaterThanEqual(arg0 context.Context, arg1 int) ([]*UserModel, error) { - cursor, err := r.collection.Find(arg0, bson.M{ + ExpectedBody: ` cursor, err := r.collection.Find(arg0, bson.M{ "age": bson.M{"$gte": arg1}, }, options.Find().SetSort(bson.M{ })) @@ -577,9 +648,7 @@ func (r *UserRepositoryMongo) FindByAgeGreaterThanEqual(arg0 context.Context, ar if err := cursor.All(arg0, &entities); err != nil { return nil, err } - return entities, nil -} -`, + return entities, nil`, }, { Name: "find with Between comparator", @@ -587,12 +656,12 @@ func (r *UserRepositoryMongo) FindByAgeGreaterThanEqual(arg0 context.Context, ar Name: "FindByAgeBetween", Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Name: "fromAge", Type: code.SimpleType("int")}, - {Name: "toAge", Type: code.SimpleType("int")}, + {Name: "fromAge", Type: code.TypeInt}, + {Name: "toAge", Type: code.TypeInt}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeMany, @@ -603,9 +672,7 @@ func (r *UserRepositoryMongo) FindByAgeGreaterThanEqual(arg0 context.Context, ar }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) FindByAgeBetween(arg0 context.Context, arg1 int, arg2 int) ([]*UserModel, error) { - cursor, err := r.collection.Find(arg0, bson.M{ + ExpectedBody: ` cursor, err := r.collection.Find(arg0, bson.M{ "age": bson.M{"$gte": arg1, "$lte": arg2}, }, options.Find().SetSort(bson.M{ })) @@ -616,9 +683,7 @@ func (r *UserRepositoryMongo) FindByAgeBetween(arg0 context.Context, arg1 int, a if err := cursor.All(arg0, &entities); err != nil { return nil, err } - return entities, nil -} -`, + return entities, nil`, }, { Name: "find with In comparator", @@ -630,7 +695,7 @@ func (r *UserRepositoryMongo) FindByAgeBetween(arg0 context.Context, arg1 int, a }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeMany, @@ -641,9 +706,7 @@ func (r *UserRepositoryMongo) FindByAgeBetween(arg0 context.Context, arg1 int, a }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) FindByGenderIn(arg0 context.Context, arg1 []Gender) ([]*UserModel, error) { - cursor, err := r.collection.Find(arg0, bson.M{ + ExpectedBody: ` cursor, err := r.collection.Find(arg0, bson.M{ "gender": bson.M{"$in": arg1}, }, options.Find().SetSort(bson.M{ })) @@ -654,9 +717,7 @@ func (r *UserRepositoryMongo) FindByGenderIn(arg0 context.Context, arg1 []Gender if err := cursor.All(arg0, &entities); err != nil { return nil, err } - return entities, nil -} -`, + return entities, nil`, }, { Name: "find with NotIn comparator", @@ -668,7 +729,7 @@ func (r *UserRepositoryMongo) FindByGenderIn(arg0 context.Context, arg1 []Gender }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeMany, @@ -679,9 +740,7 @@ func (r *UserRepositoryMongo) FindByGenderIn(arg0 context.Context, arg1 []Gender }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) FindByGenderNotIn(arg0 context.Context, arg1 []Gender) ([]*UserModel, error) { - cursor, err := r.collection.Find(arg0, bson.M{ + ExpectedBody: ` cursor, err := r.collection.Find(arg0, bson.M{ "gender": bson.M{"$nin": arg1}, }, options.Find().SetSort(bson.M{ })) @@ -692,9 +751,7 @@ func (r *UserRepositoryMongo) FindByGenderNotIn(arg0 context.Context, arg1 []Gen if err := cursor.All(arg0, &entities); err != nil { return nil, err } - return entities, nil -} -`, + return entities, nil`, }, { Name: "find with True comparator", @@ -705,7 +762,7 @@ func (r *UserRepositoryMongo) FindByGenderNotIn(arg0 context.Context, arg1 []Gen }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeMany, @@ -716,9 +773,7 @@ func (r *UserRepositoryMongo) FindByGenderNotIn(arg0 context.Context, arg1 []Gen }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) FindByEnabledTrue(arg0 context.Context) ([]*UserModel, error) { - cursor, err := r.collection.Find(arg0, bson.M{ + ExpectedBody: ` cursor, err := r.collection.Find(arg0, bson.M{ "enabled": true, }, options.Find().SetSort(bson.M{ })) @@ -729,9 +784,7 @@ func (r *UserRepositoryMongo) FindByEnabledTrue(arg0 context.Context) ([]*UserMo if err := cursor.All(arg0, &entities); err != nil { return nil, err } - return entities, nil -} -`, + return entities, nil`, }, { Name: "find with False comparator", @@ -742,7 +795,7 @@ func (r *UserRepositoryMongo) FindByEnabledTrue(arg0 context.Context) ([]*UserMo }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeMany, @@ -753,9 +806,7 @@ func (r *UserRepositoryMongo) FindByEnabledTrue(arg0 context.Context) ([]*UserMo }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) FindByEnabledFalse(arg0 context.Context) ([]*UserModel, error) { - cursor, err := r.collection.Find(arg0, bson.M{ + ExpectedBody: ` cursor, err := r.collection.Find(arg0, bson.M{ "enabled": false, }, options.Find().SetSort(bson.M{ })) @@ -766,9 +817,7 @@ func (r *UserRepositoryMongo) FindByEnabledFalse(arg0 context.Context) ([]*UserM if err := cursor.All(arg0, &entities); err != nil { return nil, err } - return entities, nil -} -`, + return entities, nil`, }, { Name: "find with sort ascending", @@ -779,7 +828,7 @@ func (r *UserRepositoryMongo) FindByEnabledFalse(arg0 context.Context) ([]*UserM }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeMany, @@ -788,9 +837,7 @@ func (r *UserRepositoryMongo) FindByEnabledFalse(arg0 context.Context) ([]*UserM }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) FindAllOrderByAge(arg0 context.Context) ([]*UserModel, error) { - cursor, err := r.collection.Find(arg0, bson.M{ + ExpectedBody: ` cursor, err := r.collection.Find(arg0, bson.M{ }, options.Find().SetSort(bson.M{ "age": 1, @@ -802,9 +849,7 @@ func (r *UserRepositoryMongo) FindAllOrderByAge(arg0 context.Context) ([]*UserMo if err := cursor.All(arg0, &entities); err != nil { return nil, err } - return entities, nil -} -`, + return entities, nil`, }, { Name: "find with sort descending", @@ -815,7 +860,7 @@ func (r *UserRepositoryMongo) FindAllOrderByAge(arg0 context.Context) ([]*UserMo }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeMany, @@ -824,9 +869,7 @@ func (r *UserRepositoryMongo) FindAllOrderByAge(arg0 context.Context) ([]*UserMo }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) FindAllOrderByAgeDesc(arg0 context.Context) ([]*UserModel, error) { - cursor, err := r.collection.Find(arg0, bson.M{ + ExpectedBody: ` cursor, err := r.collection.Find(arg0, bson.M{ }, options.Find().SetSort(bson.M{ "age": -1, @@ -838,9 +881,7 @@ func (r *UserRepositoryMongo) FindAllOrderByAgeDesc(arg0 context.Context) ([]*Us if err := cursor.All(arg0, &entities); err != nil { return nil, err } - return entities, nil -} -`, + return entities, nil`, }, { Name: "find with deep sort ascending", @@ -851,7 +892,7 @@ func (r *UserRepositoryMongo) FindAllOrderByAgeDesc(arg0 context.Context) ([]*Us }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeMany, @@ -860,9 +901,7 @@ func (r *UserRepositoryMongo) FindAllOrderByAgeDesc(arg0 context.Context) ([]*Us }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) FindAllOrderByNameFirst(arg0 context.Context) ([]*UserModel, error) { - cursor, err := r.collection.Find(arg0, bson.M{ + ExpectedBody: ` cursor, err := r.collection.Find(arg0, bson.M{ }, options.Find().SetSort(bson.M{ "name.first": 1, @@ -874,9 +913,7 @@ func (r *UserRepositoryMongo) FindAllOrderByNameFirst(arg0 context.Context) ([]* if err := cursor.All(arg0, &entities); err != nil { return nil, err } - return entities, nil -} -`, + return entities, nil`, }, { Name: "find with multiple sorts", @@ -887,7 +924,7 @@ func (r *UserRepositoryMongo) FindAllOrderByNameFirst(arg0 context.Context) ([]* }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeMany, @@ -897,9 +934,7 @@ func (r *UserRepositoryMongo) FindAllOrderByNameFirst(arg0 context.Context) ([]* }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) FindAllOrderByGenderAndAgeDesc(arg0 context.Context) ([]*UserModel, error) { - cursor, err := r.collection.Find(arg0, bson.M{ + ExpectedBody: ` cursor, err := r.collection.Find(arg0, bson.M{ }, options.Find().SetSort(bson.M{ "gender": 1, @@ -912,23 +947,66 @@ func (r *UserRepositoryMongo) FindAllOrderByGenderAndAgeDesc(arg0 context.Contex if err := cursor.All(arg0, &entities); err != nil { return nil, err } - return entities, nil -} -`, + return entities, nil`, }, } for _, testCase := range testTable { t.Run(testCase.Name, func(t *testing.T) { generator := mongo.NewGenerator(userModel, "UserRepository") - buffer := new(bytes.Buffer) + var expectedParams []code.Param + for i, param := range testCase.MethodSpec.Params { + expectedParams = append(expectedParams, code.Param{ + Name: fmt.Sprintf("arg%d", i), + Type: param.Type, + }) + } + expected := codegen.MethodBuilder{ + Receiver: codegen.MethodReceiver{ + Name: "r", + Type: "UserRepositoryMongo", + Pointer: true, + }, + Name: testCase.MethodSpec.Name, + Params: expectedParams, + Returns: testCase.MethodSpec.Returns, + Body: testCase.ExpectedBody, + } - err := generator.GenerateMethod(testCase.MethodSpec, buffer) + actual, err := generator.GenerateMethod(testCase.MethodSpec) if err != nil { - t.Error(err) + t.Fatal(err) } - if err := testutils.ExpectMultiLineString(testCase.ExpectedCode, buffer.String()); err != nil { + if expected.Receiver != actual.Receiver { + t.Errorf( + "incorrect method receiver: expected %+v, got %+v", + expected.Receiver, + actual.Receiver, + ) + } + if expected.Name != actual.Name { + t.Errorf( + "incorrect method name: expected %s, got %s", + expected.Name, + actual.Name, + ) + } + if !reflect.DeepEqual(expected.Params, actual.Params) { + t.Errorf( + "incorrect struct params: expected %+v, got %+v", + expected.Params, + actual.Params, + ) + } + if !reflect.DeepEqual(expected.Returns, actual.Returns) { + t.Errorf( + "incorrect struct returns: expected %+v, got %+v", + expected.Returns, + actual.Returns, + ) + } + if err := testutils.ExpectMultiLineString(expected.Body, actual.Body); err != nil { t.Error(err) } }) @@ -947,8 +1025,8 @@ func TestGenerateMethod_Update(t *testing.T) { {Name: "id", Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("error"), + code.TypeBool, + code.TypeError, }, Operation: spec.UpdateOperation{ Update: spec.UpdateModel{}, @@ -960,9 +1038,7 @@ func TestGenerateMethod_Update(t *testing.T) { }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) UpdateByID(arg0 context.Context, arg1 *UserModel, arg2 primitive.ObjectID) (bool, error) { - result, err := r.collection.UpdateOne(arg0, bson.M{ + ExpectedBody: ` result, err := r.collection.UpdateOne(arg0, bson.M{ "_id": arg2, }, bson.M{ "$set": arg1, @@ -970,9 +1046,7 @@ func (r *UserRepositoryMongo) UpdateByID(arg0 context.Context, arg1 *UserModel, if err != nil { return false, err } - return result.MatchedCount > 0, err -} -`, + return result.MatchedCount > 0, err`, }, { Name: "simple update one method", @@ -980,12 +1054,12 @@ func (r *UserRepositoryMongo) UpdateByID(arg0 context.Context, arg1 *UserModel, Name: "UpdateAgeByID", Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Name: "age", Type: code.SimpleType("int")}, + {Name: "age", Type: code.TypeInt}, {Name: "id", Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("error"), + code.TypeBool, + code.TypeError, }, Operation: spec.UpdateOperation{ Update: spec.UpdateFields{ @@ -999,9 +1073,7 @@ func (r *UserRepositoryMongo) UpdateByID(arg0 context.Context, arg1 *UserModel, }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) UpdateAgeByID(arg0 context.Context, arg1 int, arg2 primitive.ObjectID) (bool, error) { - result, err := r.collection.UpdateOne(arg0, bson.M{ + ExpectedBody: ` result, err := r.collection.UpdateOne(arg0, bson.M{ "_id": arg2, }, bson.M{ "$set": bson.M{ @@ -1011,9 +1083,7 @@ func (r *UserRepositoryMongo) UpdateAgeByID(arg0 context.Context, arg1 int, arg2 if err != nil { return false, err } - return result.MatchedCount > 0, err -} -`, + return result.MatchedCount > 0, err`, }, { Name: "simple update many method", @@ -1021,12 +1091,12 @@ func (r *UserRepositoryMongo) UpdateAgeByID(arg0 context.Context, arg1 int, arg2 Name: "UpdateAgeByGender", Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Name: "age", Type: code.SimpleType("int")}, + {Name: "age", Type: code.TypeInt}, {Name: "gender", Type: code.SimpleType("Gender")}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, Operation: spec.UpdateOperation{ Update: spec.UpdateFields{ @@ -1040,9 +1110,7 @@ func (r *UserRepositoryMongo) UpdateAgeByID(arg0 context.Context, arg1 int, arg2 }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) UpdateAgeByGender(arg0 context.Context, arg1 int, arg2 Gender) (int, error) { - result, err := r.collection.UpdateMany(arg0, bson.M{ + ExpectedBody: ` result, err := r.collection.UpdateMany(arg0, bson.M{ "gender": arg2, }, bson.M{ "$set": bson.M{ @@ -1052,9 +1120,7 @@ func (r *UserRepositoryMongo) UpdateAgeByGender(arg0 context.Context, arg1 int, if err != nil { return 0, err } - return int(result.MatchedCount), err -} -`, + return int(result.MatchedCount), err`, }, { Name: "simple update push method", @@ -1066,8 +1132,8 @@ func (r *UserRepositoryMongo) UpdateAgeByGender(arg0 context.Context, arg1 int, {Name: "id", Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("error"), + code.TypeBool, + code.TypeError, }, Operation: spec.UpdateOperation{ Update: spec.UpdateFields{ @@ -1081,9 +1147,7 @@ func (r *UserRepositoryMongo) UpdateAgeByGender(arg0 context.Context, arg1 int, }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) UpdateConsentHistoryPushByID(arg0 context.Context, arg1 ConsentHistory, arg2 primitive.ObjectID) (bool, error) { - result, err := r.collection.UpdateOne(arg0, bson.M{ + ExpectedBody: ` result, err := r.collection.UpdateOne(arg0, bson.M{ "_id": arg2, }, bson.M{ "$push": bson.M{ @@ -1093,9 +1157,7 @@ func (r *UserRepositoryMongo) UpdateConsentHistoryPushByID(arg0 context.Context, if err != nil { return false, err } - return result.MatchedCount > 0, err -} -`, + return result.MatchedCount > 0, err`, }, { Name: "simple update inc method", @@ -1103,12 +1165,12 @@ func (r *UserRepositoryMongo) UpdateConsentHistoryPushByID(arg0 context.Context, Name: "UpdateAgeIncByID", Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Name: "age", Type: code.SimpleType("int")}, + {Name: "age", Type: code.TypeInt}, {Name: "id", Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("error"), + code.TypeBool, + code.TypeError, }, Operation: spec.UpdateOperation{ Update: spec.UpdateFields{ @@ -1122,9 +1184,7 @@ func (r *UserRepositoryMongo) UpdateConsentHistoryPushByID(arg0 context.Context, }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) UpdateAgeIncByID(arg0 context.Context, arg1 int, arg2 primitive.ObjectID) (bool, error) { - result, err := r.collection.UpdateOne(arg0, bson.M{ + ExpectedBody: ` result, err := r.collection.UpdateOne(arg0, bson.M{ "_id": arg2, }, bson.M{ "$inc": bson.M{ @@ -1134,9 +1194,7 @@ func (r *UserRepositoryMongo) UpdateAgeIncByID(arg0 context.Context, arg1 int, a if err != nil { return false, err } - return result.MatchedCount > 0, err -} -`, + return result.MatchedCount > 0, err`, }, { Name: "simple update set and push method", @@ -1144,13 +1202,13 @@ func (r *UserRepositoryMongo) UpdateAgeIncByID(arg0 context.Context, arg1 int, a Name: "UpdateEnabledAndConsentHistoryPushByID", Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Name: "enabled", Type: code.SimpleType("bool")}, + {Name: "enabled", Type: code.TypeBool}, {Name: "consentHistory", Type: code.SimpleType("ConsentHistory")}, {Name: "gender", Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("error"), + code.TypeBool, + code.TypeError, }, Operation: spec.UpdateOperation{ Update: spec.UpdateFields{ @@ -1165,9 +1223,7 @@ func (r *UserRepositoryMongo) UpdateAgeIncByID(arg0 context.Context, arg1 int, a }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) UpdateEnabledAndConsentHistoryPushByID(arg0 context.Context, arg1 bool, arg2 ConsentHistory, arg3 primitive.ObjectID) (bool, error) { - result, err := r.collection.UpdateOne(arg0, bson.M{ + ExpectedBody: ` result, err := r.collection.UpdateOne(arg0, bson.M{ "_id": arg3, }, bson.M{ "$push": bson.M{ @@ -1180,9 +1236,7 @@ func (r *UserRepositoryMongo) UpdateEnabledAndConsentHistoryPushByID(arg0 contex if err != nil { return false, err } - return result.MatchedCount > 0, err -} -`, + return result.MatchedCount > 0, err`, }, { Name: "update with deeply referenced field", @@ -1190,12 +1244,12 @@ func (r *UserRepositoryMongo) UpdateEnabledAndConsentHistoryPushByID(arg0 contex Name: "UpdateNameFirstByID", Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Name: "firstName", Type: code.SimpleType("string")}, + {Name: "firstName", Type: code.TypeString}, {Name: "id", Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("error"), + code.TypeBool, + code.TypeError, }, Operation: spec.UpdateOperation{ Update: spec.UpdateFields{ @@ -1209,9 +1263,7 @@ func (r *UserRepositoryMongo) UpdateEnabledAndConsentHistoryPushByID(arg0 contex }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) UpdateNameFirstByID(arg0 context.Context, arg1 string, arg2 primitive.ObjectID) (bool, error) { - result, err := r.collection.UpdateOne(arg0, bson.M{ + ExpectedBody: ` result, err := r.collection.UpdateOne(arg0, bson.M{ "_id": arg2, }, bson.M{ "$set": bson.M{ @@ -1221,23 +1273,66 @@ func (r *UserRepositoryMongo) UpdateNameFirstByID(arg0 context.Context, arg1 str if err != nil { return false, err } - return result.MatchedCount > 0, err -} -`, + return result.MatchedCount > 0, err`, }, } for _, testCase := range testTable { t.Run(testCase.Name, func(t *testing.T) { generator := mongo.NewGenerator(userModel, "UserRepository") - buffer := new(bytes.Buffer) + var expectedParams []code.Param + for i, param := range testCase.MethodSpec.Params { + expectedParams = append(expectedParams, code.Param{ + Name: fmt.Sprintf("arg%d", i), + Type: param.Type, + }) + } + expected := codegen.MethodBuilder{ + Receiver: codegen.MethodReceiver{ + Name: "r", + Type: "UserRepositoryMongo", + Pointer: true, + }, + Name: testCase.MethodSpec.Name, + Params: expectedParams, + Returns: testCase.MethodSpec.Returns, + Body: testCase.ExpectedBody, + } - err := generator.GenerateMethod(testCase.MethodSpec, buffer) + actual, err := generator.GenerateMethod(testCase.MethodSpec) if err != nil { - t.Error(err) + t.Fatal(err) } - if err := testutils.ExpectMultiLineString(testCase.ExpectedCode, buffer.String()); err != nil { + if expected.Receiver != actual.Receiver { + t.Errorf( + "incorrect method receiver: expected %+v, got %+v", + expected.Receiver, + actual.Receiver, + ) + } + if expected.Name != actual.Name { + t.Errorf( + "incorrect method name: expected %s, got %s", + expected.Name, + actual.Name, + ) + } + if !reflect.DeepEqual(expected.Params, actual.Params) { + t.Errorf( + "incorrect struct params: expected %+v, got %+v", + expected.Params, + actual.Params, + ) + } + if !reflect.DeepEqual(expected.Returns, actual.Returns) { + t.Errorf( + "incorrect struct returns: expected %+v, got %+v", + expected.Returns, + actual.Returns, + ) + } + if err := testutils.ExpectMultiLineString(expected.Body, actual.Body); err != nil { t.Error(err) } }) @@ -1254,7 +1349,7 @@ func TestGenerateMethod_Delete(t *testing.T) { {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, {Name: "id", Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, - Returns: []code.Type{code.SimpleType("bool"), code.SimpleType("error")}, + Returns: []code.Type{code.TypeBool, code.TypeError}, Operation: spec.DeleteOperation{ Mode: spec.QueryModeOne, Query: spec.QuerySpec{ @@ -1264,17 +1359,13 @@ func TestGenerateMethod_Delete(t *testing.T) { }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) DeleteByID(arg0 context.Context, arg1 primitive.ObjectID) (bool, error) { - result, err := r.collection.DeleteOne(arg0, bson.M{ + ExpectedBody: ` result, err := r.collection.DeleteOne(arg0, bson.M{ "_id": arg1, }) if err != nil { return false, err } - return result.DeletedCount > 0, nil -} -`, + return result.DeletedCount > 0, nil`, }, { Name: "simple delete many method", @@ -1285,8 +1376,8 @@ func (r *UserRepositoryMongo) DeleteByID(arg0 context.Context, arg1 primitive.Ob {Name: "gender", Type: code.SimpleType("Gender")}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, Operation: spec.DeleteOperation{ Mode: spec.QueryModeMany, @@ -1297,17 +1388,13 @@ func (r *UserRepositoryMongo) DeleteByID(arg0 context.Context, arg1 primitive.Ob }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) DeleteByGender(arg0 context.Context, arg1 Gender) (int, error) { - result, err := r.collection.DeleteMany(arg0, bson.M{ + ExpectedBody: ` result, err := r.collection.DeleteMany(arg0, bson.M{ "gender": arg1, }) if err != nil { return 0, err } - return int(result.DeletedCount), nil -} -`, + return int(result.DeletedCount), nil`, }, { Name: "delete with And operator", @@ -1316,11 +1403,11 @@ func (r *UserRepositoryMongo) DeleteByGender(arg0 context.Context, arg1 Gender) Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, {Name: "gender", Type: code.SimpleType("Gender")}, - {Name: "age", Type: code.SimpleType("int")}, + {Name: "age", Type: code.TypeInt}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, Operation: spec.DeleteOperation{ Mode: spec.QueryModeMany, @@ -1333,9 +1420,7 @@ func (r *UserRepositoryMongo) DeleteByGender(arg0 context.Context, arg1 Gender) }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) DeleteByGenderAndAge(arg0 context.Context, arg1 Gender, arg2 int) (int, error) { - result, err := r.collection.DeleteMany(arg0, bson.M{ + ExpectedBody: ` result, err := r.collection.DeleteMany(arg0, bson.M{ "$and": []bson.M{ {"gender": arg1}, {"age": arg2}, @@ -1344,9 +1429,7 @@ func (r *UserRepositoryMongo) DeleteByGenderAndAge(arg0 context.Context, arg1 Ge if err != nil { return 0, err } - return int(result.DeletedCount), nil -} -`, + return int(result.DeletedCount), nil`, }, { Name: "delete with Or operator", @@ -1355,11 +1438,11 @@ func (r *UserRepositoryMongo) DeleteByGenderAndAge(arg0 context.Context, arg1 Ge Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, {Name: "gender", Type: code.SimpleType("Gender")}, - {Name: "age", Type: code.SimpleType("int")}, + {Name: "age", Type: code.TypeInt}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, Operation: spec.DeleteOperation{ Mode: spec.QueryModeMany, @@ -1372,9 +1455,7 @@ func (r *UserRepositoryMongo) DeleteByGenderAndAge(arg0 context.Context, arg1 Ge }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) DeleteByGenderOrAge(arg0 context.Context, arg1 Gender, arg2 int) (int, error) { - result, err := r.collection.DeleteMany(arg0, bson.M{ + ExpectedBody: ` result, err := r.collection.DeleteMany(arg0, bson.M{ "$or": []bson.M{ {"gender": arg1}, {"age": arg2}, @@ -1383,9 +1464,7 @@ func (r *UserRepositoryMongo) DeleteByGenderOrAge(arg0 context.Context, arg1 Gen if err != nil { return 0, err } - return int(result.DeletedCount), nil -} -`, + return int(result.DeletedCount), nil`, }, { Name: "delete with Not comparator", @@ -1396,8 +1475,8 @@ func (r *UserRepositoryMongo) DeleteByGenderOrAge(arg0 context.Context, arg1 Gen {Name: "gender", Type: code.SimpleType("Gender")}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, Operation: spec.DeleteOperation{ Mode: spec.QueryModeMany, @@ -1408,17 +1487,13 @@ func (r *UserRepositoryMongo) DeleteByGenderOrAge(arg0 context.Context, arg1 Gen }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) DeleteByGenderNot(arg0 context.Context, arg1 Gender) (int, error) { - result, err := r.collection.DeleteMany(arg0, bson.M{ + ExpectedBody: ` result, err := r.collection.DeleteMany(arg0, bson.M{ "gender": bson.M{"$ne": arg1}, }) if err != nil { return 0, err } - return int(result.DeletedCount), nil -} -`, + return int(result.DeletedCount), nil`, }, { Name: "delete with LessThan comparator", @@ -1426,11 +1501,11 @@ func (r *UserRepositoryMongo) DeleteByGenderNot(arg0 context.Context, arg1 Gende Name: "DeleteByAgeLessThan", Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Name: "age", Type: code.SimpleType("int")}, + {Name: "age", Type: code.TypeInt}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, Operation: spec.DeleteOperation{ Mode: spec.QueryModeMany, @@ -1441,17 +1516,13 @@ func (r *UserRepositoryMongo) DeleteByGenderNot(arg0 context.Context, arg1 Gende }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) DeleteByAgeLessThan(arg0 context.Context, arg1 int) (int, error) { - result, err := r.collection.DeleteMany(arg0, bson.M{ + ExpectedBody: ` result, err := r.collection.DeleteMany(arg0, bson.M{ "age": bson.M{"$lt": arg1}, }) if err != nil { return 0, err } - return int(result.DeletedCount), nil -} -`, + return int(result.DeletedCount), nil`, }, { Name: "delete with LessThanEqual comparator", @@ -1459,11 +1530,11 @@ func (r *UserRepositoryMongo) DeleteByAgeLessThan(arg0 context.Context, arg1 int Name: "DeleteByAgeLessThanEqual", Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Name: "age", Type: code.SimpleType("int")}, + {Name: "age", Type: code.TypeInt}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, Operation: spec.DeleteOperation{ Mode: spec.QueryModeMany, @@ -1474,17 +1545,13 @@ func (r *UserRepositoryMongo) DeleteByAgeLessThan(arg0 context.Context, arg1 int }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) DeleteByAgeLessThanEqual(arg0 context.Context, arg1 int) (int, error) { - result, err := r.collection.DeleteMany(arg0, bson.M{ + ExpectedBody: ` result, err := r.collection.DeleteMany(arg0, bson.M{ "age": bson.M{"$lte": arg1}, }) if err != nil { return 0, err } - return int(result.DeletedCount), nil -} -`, + return int(result.DeletedCount), nil`, }, { Name: "delete with GreaterThan comparator", @@ -1492,11 +1559,11 @@ func (r *UserRepositoryMongo) DeleteByAgeLessThanEqual(arg0 context.Context, arg Name: "DeleteByAgeGreaterThan", Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Name: "age", Type: code.SimpleType("int")}, + {Name: "age", Type: code.TypeInt}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, Operation: spec.DeleteOperation{ Mode: spec.QueryModeMany, @@ -1507,17 +1574,13 @@ func (r *UserRepositoryMongo) DeleteByAgeLessThanEqual(arg0 context.Context, arg }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) DeleteByAgeGreaterThan(arg0 context.Context, arg1 int) (int, error) { - result, err := r.collection.DeleteMany(arg0, bson.M{ + ExpectedBody: ` result, err := r.collection.DeleteMany(arg0, bson.M{ "age": bson.M{"$gt": arg1}, }) if err != nil { return 0, err } - return int(result.DeletedCount), nil -} -`, + return int(result.DeletedCount), nil`, }, { Name: "delete with GreaterThanEqual comparator", @@ -1525,11 +1588,11 @@ func (r *UserRepositoryMongo) DeleteByAgeGreaterThan(arg0 context.Context, arg1 Name: "DeleteByAgeGreaterThanEqual", Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Name: "age", Type: code.SimpleType("int")}, + {Name: "age", Type: code.TypeInt}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, Operation: spec.DeleteOperation{ Mode: spec.QueryModeMany, @@ -1540,17 +1603,13 @@ func (r *UserRepositoryMongo) DeleteByAgeGreaterThan(arg0 context.Context, arg1 }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) DeleteByAgeGreaterThanEqual(arg0 context.Context, arg1 int) (int, error) { - result, err := r.collection.DeleteMany(arg0, bson.M{ + ExpectedBody: ` result, err := r.collection.DeleteMany(arg0, bson.M{ "age": bson.M{"$gte": arg1}, }) if err != nil { return 0, err } - return int(result.DeletedCount), nil -} -`, + return int(result.DeletedCount), nil`, }, { Name: "delete with Between comparator", @@ -1558,12 +1617,12 @@ func (r *UserRepositoryMongo) DeleteByAgeGreaterThanEqual(arg0 context.Context, Name: "DeleteByAgeBetween", Params: []code.Param{ {Name: "ctx", Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Name: "fromAge", Type: code.SimpleType("int")}, - {Name: "toAge", Type: code.SimpleType("int")}, + {Name: "fromAge", Type: code.TypeInt}, + {Name: "toAge", Type: code.TypeInt}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, Operation: spec.DeleteOperation{ Mode: spec.QueryModeMany, @@ -1574,17 +1633,13 @@ func (r *UserRepositoryMongo) DeleteByAgeGreaterThanEqual(arg0 context.Context, }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) DeleteByAgeBetween(arg0 context.Context, arg1 int, arg2 int) (int, error) { - result, err := r.collection.DeleteMany(arg0, bson.M{ + ExpectedBody: ` result, err := r.collection.DeleteMany(arg0, bson.M{ "age": bson.M{"$gte": arg1, "$lte": arg2}, }) if err != nil { return 0, err } - return int(result.DeletedCount), nil -} -`, + return int(result.DeletedCount), nil`, }, { Name: "delete with In comparator", @@ -1595,8 +1650,8 @@ func (r *UserRepositoryMongo) DeleteByAgeBetween(arg0 context.Context, arg1 int, {Name: "gender", Type: code.ArrayType{ContainedType: code.SimpleType("Gender")}}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, Operation: spec.DeleteOperation{ Mode: spec.QueryModeMany, @@ -1607,31 +1662,72 @@ func (r *UserRepositoryMongo) DeleteByAgeBetween(arg0 context.Context, arg1 int, }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) DeleteByGenderIn(arg0 context.Context, arg1 []Gender) (int, error) { - result, err := r.collection.DeleteMany(arg0, bson.M{ + ExpectedBody: ` result, err := r.collection.DeleteMany(arg0, bson.M{ "gender": bson.M{"$in": arg1}, }) if err != nil { return 0, err } - return int(result.DeletedCount), nil -} -`, + return int(result.DeletedCount), nil`, }, } for _, testCase := range testTable { t.Run(testCase.Name, func(t *testing.T) { generator := mongo.NewGenerator(userModel, "UserRepository") - buffer := new(bytes.Buffer) + var expectedParams []code.Param + for i, param := range testCase.MethodSpec.Params { + expectedParams = append(expectedParams, code.Param{ + Name: fmt.Sprintf("arg%d", i), + Type: param.Type, + }) + } + expected := codegen.MethodBuilder{ + Receiver: codegen.MethodReceiver{ + Name: "r", + Type: "UserRepositoryMongo", + Pointer: true, + }, + Name: testCase.MethodSpec.Name, + Params: expectedParams, + Returns: testCase.MethodSpec.Returns, + Body: testCase.ExpectedBody, + } - err := generator.GenerateMethod(testCase.MethodSpec, buffer) + actual, err := generator.GenerateMethod(testCase.MethodSpec) if err != nil { - t.Error(err) + t.Fatal(err) } - if err := testutils.ExpectMultiLineString(testCase.ExpectedCode, buffer.String()); err != nil { + if expected.Receiver != actual.Receiver { + t.Errorf( + "incorrect method receiver: expected %+v, got %+v", + expected.Receiver, + actual.Receiver, + ) + } + if expected.Name != actual.Name { + t.Errorf( + "incorrect method name: expected %s, got %s", + expected.Name, + actual.Name, + ) + } + if !reflect.DeepEqual(expected.Params, actual.Params) { + t.Errorf( + "incorrect struct params: expected %+v, got %+v", + expected.Params, + actual.Params, + ) + } + if !reflect.DeepEqual(expected.Returns, actual.Returns) { + t.Errorf( + "incorrect struct returns: expected %+v, got %+v", + expected.Returns, + actual.Returns, + ) + } + if err := testutils.ExpectMultiLineString(expected.Body, actual.Body); err != nil { t.Error(err) } }) @@ -1649,8 +1745,8 @@ func TestGenerateMethod_Count(t *testing.T) { {Type: code.SimpleType("Gender")}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, Operation: spec.CountOperation{ Query: spec.QuerySpec{ @@ -1660,17 +1756,13 @@ func TestGenerateMethod_Count(t *testing.T) { }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) CountByGender(arg0 context.Context, arg1 Gender) (int, error) { - count, err := r.collection.CountDocuments(arg0, bson.M{ + ExpectedBody: ` count, err := r.collection.CountDocuments(arg0, bson.M{ "gender": arg1, }) if err != nil { return 0, err } - return int(count), nil -} -`, + return int(count), nil`, }, { Name: "count with And operator", @@ -1679,11 +1771,11 @@ func (r *UserRepositoryMongo) CountByGender(arg0 context.Context, arg1 Gender) ( Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, {Type: code.SimpleType("Gender")}, - {Type: code.SimpleType("int")}, + {Type: code.TypeInt}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, Operation: spec.CountOperation{ Query: spec.QuerySpec{ @@ -1695,9 +1787,7 @@ func (r *UserRepositoryMongo) CountByGender(arg0 context.Context, arg1 Gender) ( }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) CountByGenderAndCity(arg0 context.Context, arg1 Gender, arg2 int) (int, error) { - count, err := r.collection.CountDocuments(arg0, bson.M{ + ExpectedBody: ` count, err := r.collection.CountDocuments(arg0, bson.M{ "$and": []bson.M{ {"gender": arg1}, {"age": arg2}, @@ -1706,9 +1796,7 @@ func (r *UserRepositoryMongo) CountByGenderAndCity(arg0 context.Context, arg1 Ge if err != nil { return 0, err } - return int(count), nil -} -`, + return int(count), nil`, }, { Name: "count with Or operator", @@ -1717,11 +1805,11 @@ func (r *UserRepositoryMongo) CountByGenderAndCity(arg0 context.Context, arg1 Ge Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, {Type: code.SimpleType("Gender")}, - {Type: code.SimpleType("int")}, + {Type: code.TypeInt}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, Operation: spec.CountOperation{ Query: spec.QuerySpec{ @@ -1733,9 +1821,7 @@ func (r *UserRepositoryMongo) CountByGenderAndCity(arg0 context.Context, arg1 Ge }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) CountByGenderOrCity(arg0 context.Context, arg1 Gender, arg2 int) (int, error) { - count, err := r.collection.CountDocuments(arg0, bson.M{ + ExpectedBody: ` count, err := r.collection.CountDocuments(arg0, bson.M{ "$or": []bson.M{ {"gender": arg1}, {"age": arg2}, @@ -1744,9 +1830,7 @@ func (r *UserRepositoryMongo) CountByGenderOrCity(arg0 context.Context, arg1 Gen if err != nil { return 0, err } - return int(count), nil -} -`, + return int(count), nil`, }, { Name: "count with Not comparator", @@ -1757,8 +1841,8 @@ func (r *UserRepositoryMongo) CountByGenderOrCity(arg0 context.Context, arg1 Gen {Type: code.SimpleType("Gender")}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, Operation: spec.CountOperation{ Query: spec.QuerySpec{ @@ -1768,17 +1852,13 @@ func (r *UserRepositoryMongo) CountByGenderOrCity(arg0 context.Context, arg1 Gen }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) CountByGenderNot(arg0 context.Context, arg1 Gender) (int, error) { - count, err := r.collection.CountDocuments(arg0, bson.M{ + ExpectedBody: ` count, err := r.collection.CountDocuments(arg0, bson.M{ "gender": bson.M{"$ne": arg1}, }) if err != nil { return 0, err } - return int(count), nil -} -`, + return int(count), nil`, }, { Name: "count with LessThan comparator", @@ -1786,11 +1866,11 @@ func (r *UserRepositoryMongo) CountByGenderNot(arg0 context.Context, arg1 Gender Name: "CountByAgeLessThan", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("int")}, + {Type: code.TypeInt}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, Operation: spec.CountOperation{ Query: spec.QuerySpec{ @@ -1800,17 +1880,13 @@ func (r *UserRepositoryMongo) CountByGenderNot(arg0 context.Context, arg1 Gender }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) CountByAgeLessThan(arg0 context.Context, arg1 int) (int, error) { - count, err := r.collection.CountDocuments(arg0, bson.M{ + ExpectedBody: ` count, err := r.collection.CountDocuments(arg0, bson.M{ "age": bson.M{"$lt": arg1}, }) if err != nil { return 0, err } - return int(count), nil -} -`, + return int(count), nil`, }, { Name: "count with LessThanEqual comparator", @@ -1818,11 +1894,11 @@ func (r *UserRepositoryMongo) CountByAgeLessThan(arg0 context.Context, arg1 int) Name: "CountByAgeLessThanEqual", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("int")}, + {Type: code.TypeInt}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, Operation: spec.CountOperation{ Query: spec.QuerySpec{ @@ -1832,17 +1908,13 @@ func (r *UserRepositoryMongo) CountByAgeLessThan(arg0 context.Context, arg1 int) }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) CountByAgeLessThanEqual(arg0 context.Context, arg1 int) (int, error) { - count, err := r.collection.CountDocuments(arg0, bson.M{ + ExpectedBody: ` count, err := r.collection.CountDocuments(arg0, bson.M{ "age": bson.M{"$lte": arg1}, }) if err != nil { return 0, err } - return int(count), nil -} -`, + return int(count), nil`, }, { Name: "count with GreaterThan comparator", @@ -1850,11 +1922,11 @@ func (r *UserRepositoryMongo) CountByAgeLessThanEqual(arg0 context.Context, arg1 Name: "CountByAgeGreaterThan", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("int")}, + {Type: code.TypeInt}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, Operation: spec.CountOperation{ Query: spec.QuerySpec{ @@ -1864,17 +1936,13 @@ func (r *UserRepositoryMongo) CountByAgeLessThanEqual(arg0 context.Context, arg1 }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) CountByAgeGreaterThan(arg0 context.Context, arg1 int) (int, error) { - count, err := r.collection.CountDocuments(arg0, bson.M{ + ExpectedBody: ` count, err := r.collection.CountDocuments(arg0, bson.M{ "age": bson.M{"$gt": arg1}, }) if err != nil { return 0, err } - return int(count), nil -} -`, + return int(count), nil`, }, { Name: "count with GreaterThanEqual comparator", @@ -1882,11 +1950,11 @@ func (r *UserRepositoryMongo) CountByAgeGreaterThan(arg0 context.Context, arg1 i Name: "CountByAgeGreaterThanEqual", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("int")}, + {Type: code.TypeInt}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, Operation: spec.CountOperation{ Query: spec.QuerySpec{ @@ -1896,17 +1964,13 @@ func (r *UserRepositoryMongo) CountByAgeGreaterThan(arg0 context.Context, arg1 i }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) CountByAgeGreaterThanEqual(arg0 context.Context, arg1 int) (int, error) { - count, err := r.collection.CountDocuments(arg0, bson.M{ + ExpectedBody: ` count, err := r.collection.CountDocuments(arg0, bson.M{ "age": bson.M{"$gte": arg1}, }) if err != nil { return 0, err } - return int(count), nil -} -`, + return int(count), nil`, }, { Name: "count with Between comparator", @@ -1914,12 +1978,12 @@ func (r *UserRepositoryMongo) CountByAgeGreaterThanEqual(arg0 context.Context, a Name: "CountByAgeBetween", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("int")}, - {Type: code.SimpleType("int")}, + {Type: code.TypeInt}, + {Type: code.TypeInt}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, Operation: spec.CountOperation{ Query: spec.QuerySpec{ @@ -1929,17 +1993,13 @@ func (r *UserRepositoryMongo) CountByAgeGreaterThanEqual(arg0 context.Context, a }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) CountByAgeBetween(arg0 context.Context, arg1 int, arg2 int) (int, error) { - count, err := r.collection.CountDocuments(arg0, bson.M{ + ExpectedBody: ` count, err := r.collection.CountDocuments(arg0, bson.M{ "age": bson.M{"$gte": arg1, "$lte": arg2}, }) if err != nil { return 0, err } - return int(count), nil -} -`, + return int(count), nil`, }, { Name: "count with In comparator", @@ -1947,11 +2007,11 @@ func (r *UserRepositoryMongo) CountByAgeBetween(arg0 context.Context, arg1 int, Name: "CountByAgeIn", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.ArrayType{ContainedType: code.SimpleType("int")}}, + {Type: code.ArrayType{ContainedType: code.TypeInt}}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, Operation: spec.CountOperation{ Query: spec.QuerySpec{ @@ -1961,31 +2021,72 @@ func (r *UserRepositoryMongo) CountByAgeBetween(arg0 context.Context, arg1 int, }, }, }, - ExpectedCode: ` -func (r *UserRepositoryMongo) CountByAgeIn(arg0 context.Context, arg1 []int) (int, error) { - count, err := r.collection.CountDocuments(arg0, bson.M{ + ExpectedBody: ` count, err := r.collection.CountDocuments(arg0, bson.M{ "age": bson.M{"$in": arg1}, }) if err != nil { return 0, err } - return int(count), nil -} -`, + return int(count), nil`, }, } for _, testCase := range testTable { t.Run(testCase.Name, func(t *testing.T) { generator := mongo.NewGenerator(userModel, "UserRepository") - buffer := new(bytes.Buffer) + var expectedParams []code.Param + for i, param := range testCase.MethodSpec.Params { + expectedParams = append(expectedParams, code.Param{ + Name: fmt.Sprintf("arg%d", i), + Type: param.Type, + }) + } + expected := codegen.MethodBuilder{ + Receiver: codegen.MethodReceiver{ + Name: "r", + Type: "UserRepositoryMongo", + Pointer: true, + }, + Name: testCase.MethodSpec.Name, + Params: expectedParams, + Returns: testCase.MethodSpec.Returns, + Body: testCase.ExpectedBody, + } - err := generator.GenerateMethod(testCase.MethodSpec, buffer) + actual, err := generator.GenerateMethod(testCase.MethodSpec) if err != nil { - t.Error(err) + t.Fatal(err) } - if err := testutils.ExpectMultiLineString(testCase.ExpectedCode, buffer.String()); err != nil { + if expected.Receiver != actual.Receiver { + t.Errorf( + "incorrect method receiver: expected %+v, got %+v", + expected.Receiver, + actual.Receiver, + ) + } + if expected.Name != actual.Name { + t.Errorf( + "incorrect method name: expected %s, got %s", + expected.Name, + actual.Name, + ) + } + if !reflect.DeepEqual(expected.Params, actual.Params) { + t.Errorf( + "incorrect struct params: expected %+v, got %+v", + expected.Params, + actual.Params, + ) + } + if !reflect.DeepEqual(expected.Returns, actual.Returns) { + t.Errorf( + "incorrect struct returns: expected %+v, got %+v", + expected.Returns, + actual.Returns, + ) + } + if err := testutils.ExpectMultiLineString(expected.Body, actual.Body); err != nil { t.Error(err) } }) @@ -2017,7 +2118,7 @@ func TestGenerateMethod_Invalid(t *testing.T) { }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: StubOperation{}, }, @@ -2029,11 +2130,11 @@ func TestGenerateMethod_Invalid(t *testing.T) { Name: "FindByAccessToken", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeOne, @@ -2055,7 +2156,7 @@ func TestGenerateMethod_Invalid(t *testing.T) { }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, Operation: spec.FindOperation{ Mode: spec.QueryModeOne, @@ -2072,12 +2173,12 @@ func TestGenerateMethod_Invalid(t *testing.T) { Name: "UpdateAccessTokenByID", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, {Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("error"), + code.TypeBool, + code.TypeError, }, Operation: spec.UpdateOperation{ Update: spec.UpdateFields{ @@ -2099,12 +2200,12 @@ func TestGenerateMethod_Invalid(t *testing.T) { Name: "UpdateAgeByID", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("int")}, + {Type: code.TypeInt}, {Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("error"), + code.TypeBool, + code.TypeError, }, Operation: spec.UpdateOperation{ Update: StubUpdate{}, @@ -2124,12 +2225,12 @@ func TestGenerateMethod_Invalid(t *testing.T) { Name: "UpdateConsentHistoryAppendByID", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("int")}, + {Type: code.TypeInt}, {Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("error"), + code.TypeBool, + code.TypeError, }, Operation: spec.UpdateOperation{ Update: spec.UpdateFields{ @@ -2150,9 +2251,8 @@ func TestGenerateMethod_Invalid(t *testing.T) { for _, testCase := range testTable { t.Run(testCase.Name, func(t *testing.T) { generator := mongo.NewGenerator(userModel, "UserRepository") - buffer := new(bytes.Buffer) - err := generator.GenerateMethod(testCase.Method, buffer) + _, err := generator.GenerateMethod(testCase.Method) if err != testCase.ExpectedError { t.Errorf("\nExpected = %+v\nReceived = %+v", testCase.ExpectedError, err) diff --git a/internal/mongo/templates.go b/internal/mongo/templates.go index da3112e..28df6ba 100644 --- a/internal/mongo/templates.go +++ b/internal/mongo/templates.go @@ -1,77 +1,17 @@ package mongo import ( - "fmt" - "strings" - - "github.com/sunboyy/repogen/internal/code" "github.com/sunboyy/repogen/internal/spec" ) -const constructorTemplate = ` -import ( - "context" - - "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/bson/primitive" - "go.mongodb.org/mongo-driver/mongo" - "go.mongodb.org/mongo-driver/mongo/options" -) - -func New{{.InterfaceName}}(collection *mongo.Collection) {{.InterfaceName}} { - return &{{.ImplStructName}}{ +const constructorBody = ` return &{{.ImplStructName}}{ collection: collection, - } -} + }` -type {{.ImplStructName}} struct { - collection *mongo.Collection -} -` - -type mongoConstructorTemplateData struct { - InterfaceName string +type constructorBodyData struct { ImplStructName string } -const methodTemplate = ` -func (r *{{.StructName}}) {{.MethodName}}({{.Parameters}}){{.Returns}} { -{{.Implementation}} -} -` - -type mongoMethodTemplateData struct { - StructName string - MethodName string - ParamTypes []code.Type - ReturnTypes []code.Type - Implementation string -} - -func (data mongoMethodTemplateData) Parameters() string { - var params []string - for i, paramType := range data.ParamTypes { - params = append(params, fmt.Sprintf("arg%d %s", i, paramType.Code())) - } - return strings.Join(params, ", ") -} - -func (data mongoMethodTemplateData) Returns() string { - if len(data.ReturnTypes) == 0 { - return "" - } - - if len(data.ReturnTypes) == 1 { - return fmt.Sprintf(" %s", data.ReturnTypes[0].Code()) - } - - var returns []string - for _, returnType := range data.ReturnTypes { - returns = append(returns, returnType.Code()) - } - return fmt.Sprintf(" (%s)", strings.Join(returns, ", ")) -} - const insertOneTemplate = ` result, err := r.collection.InsertOne(arg0, arg1) if err != nil { return nil, err diff --git a/internal/spec/errors_test.go b/internal/spec/errors_test.go index 236cee5..9b75340 100644 --- a/internal/spec/errors_test.go +++ b/internal/spec/errors_test.go @@ -44,7 +44,7 @@ func TestError(t *testing.T) { Name: "IncompatibleComparatorError", Error: spec.NewIncompatibleComparatorError(spec.ComparatorTrue, code.StructField{ Name: "Age", - Type: code.SimpleType("int"), + Type: code.TypeInt, }), ExpectedString: "cannot use comparator EQUAL_TRUE with struct field 'Age' of type 'int'", }, @@ -55,7 +55,7 @@ func TestError(t *testing.T) { }, { Name: "ArgumentTypeNotMatchedError", - Error: spec.NewArgumentTypeNotMatchedError("Age", code.SimpleType("int"), code.SimpleType("float64")), + Error: spec.NewArgumentTypeNotMatchedError("Age", code.TypeInt, code.TypeFloat64), ExpectedString: "field 'Age' requires an argument of type 'int' (got 'float64')", }, { @@ -63,7 +63,7 @@ func TestError(t *testing.T) { Error: spec.NewIncompatibleUpdateOperatorError(spec.UpdateOperatorInc, spec.FieldReference{ code.StructField{ Name: "City", - Type: code.SimpleType("string"), + Type: code.TypeString, }, }), ExpectedString: "cannot use update operator INC with struct field 'City' of type 'string'", diff --git a/internal/spec/parser.go b/internal/spec/parser.go index 88f0dca..d64546c 100644 --- a/internal/spec/parser.go +++ b/internal/spec/parser.go @@ -85,7 +85,7 @@ func (p interfaceMethodParser) extractInsertReturns(returns []code.Type) (QueryM return "", NewOperationReturnCountUnmatchedError(2) } - if returns[1] != code.SimpleType("error") { + if returns[1] != code.TypeError { return "", NewUnsupportedReturnError(returns[1], 1) } @@ -203,7 +203,7 @@ func (p interfaceMethodParser) extractModelOrSliceReturns(returns []code.Type) ( return "", NewOperationReturnCountUnmatchedError(2) } - if returns[1] != code.SimpleType("error") { + if returns[1] != code.TypeError { return "", NewUnsupportedReturnError(returns[1], 1) } @@ -318,11 +318,11 @@ func (p interfaceMethodParser) validateCountReturns(returns []code.Type) error { return NewOperationReturnCountUnmatchedError(2) } - if returns[0] != code.SimpleType("int") { + if returns[0] != code.TypeInt { return NewUnsupportedReturnError(returns[0], 0) } - if returns[1] != code.SimpleType("error") { + if returns[1] != code.TypeError { return NewUnsupportedReturnError(returns[1], 1) } @@ -334,16 +334,16 @@ func (p interfaceMethodParser) extractIntOrBoolReturns(returns []code.Type) (Que return "", NewOperationReturnCountUnmatchedError(2) } - if returns[1] != code.SimpleType("error") { + if returns[1] != code.TypeError { return "", NewUnsupportedReturnError(returns[1], 1) } simpleType, ok := returns[0].(code.SimpleType) if ok { - if simpleType == code.SimpleType("bool") { + if simpleType == code.TypeBool { return QueryModeOne, nil } - if simpleType == code.SimpleType("int") { + if simpleType == code.TypeInt { return QueryModeMany, nil } } @@ -367,7 +367,7 @@ func (p interfaceMethodParser) validateQueryFromParams(params []code.Param, quer var currentParamIndex int for _, predicate := range querySpec.Predicates { if (predicate.Comparator == ComparatorTrue || predicate.Comparator == ComparatorFalse) && - predicate.FieldReference.ReferencedField().Type != code.SimpleType("bool") { + predicate.FieldReference.ReferencedField().Type != code.TypeBool { return NewIncompatibleComparatorError(predicate.Comparator, predicate.FieldReference.ReferencedField()) } diff --git a/internal/spec/parser_test.go b/internal/spec/parser_test.go index d49ab2a..866dd18 100644 --- a/internal/spec/parser_test.go +++ b/internal/spec/parser_test.go @@ -15,7 +15,7 @@ var ( } phoneNumberField = code.StructField{ Name: "PhoneNumber", - Type: code.SimpleType("string"), + Type: code.TypeString, } genderField = code.StructField{ Name: "Gender", @@ -23,11 +23,11 @@ var ( } cityField = code.StructField{ Name: "City", - Type: code.SimpleType("string"), + Type: code.TypeString, } ageField = code.StructField{ Name: "Age", - Type: code.SimpleType("int"), + Type: code.TypeInt, } nameField = code.StructField{ Name: "Name", @@ -47,7 +47,7 @@ var ( } enabledField = code.StructField{ Name: "Enabled", - Type: code.SimpleType("bool"), + Type: code.TypeBool, } consentHistoryField = code.StructField{ Name: "ConsentHistory", @@ -56,11 +56,11 @@ var ( firstNameField = code.StructField{ Name: "First", - Type: code.SimpleType("string"), + Type: code.TypeString, } lastNameField = code.StructField{ Name: "Last", - Type: code.SimpleType("string"), + Type: code.TypeString, } ) @@ -114,7 +114,7 @@ func TestParseInterfaceMethod_Insert(t *testing.T) { }, Returns: []code.Type{ code.InterfaceType{}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.InsertOperation{ @@ -131,7 +131,7 @@ func TestParseInterfaceMethod_Insert(t *testing.T) { }, Returns: []code.Type{ code.ArrayType{ContainedType: code.InterfaceType{}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.InsertOperation{ @@ -172,7 +172,7 @@ func TestParseInterfaceMethod_Find(t *testing.T) { }, Returns: []code.Type{ code.PointerType{ContainedType: code.SimpleType("UserModel")}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.FindOperation{ @@ -188,11 +188,11 @@ func TestParseInterfaceMethod_Find(t *testing.T) { Name: "FindOneByPhoneNumber", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ code.PointerType{ContainedType: code.SimpleType("UserModel")}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.FindOperation{ @@ -208,11 +208,11 @@ func TestParseInterfaceMethod_Find(t *testing.T) { Name: "FindByCity", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.FindOperation{ @@ -228,11 +228,11 @@ func TestParseInterfaceMethod_Find(t *testing.T) { Name: "FindByNameFirst", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.FindOperation{ @@ -252,7 +252,7 @@ func TestParseInterfaceMethod_Find(t *testing.T) { }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.FindOperation{ @@ -271,7 +271,7 @@ func TestParseInterfaceMethod_Find(t *testing.T) { }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.FindOperation{ @@ -284,12 +284,12 @@ func TestParseInterfaceMethod_Find(t *testing.T) { Name: "FindByCityAndGender", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, {Type: code.SimpleType("Gender")}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.FindOperation{ @@ -309,12 +309,12 @@ func TestParseInterfaceMethod_Find(t *testing.T) { Name: "FindByCityOrGender", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, {Type: code.SimpleType("Gender")}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.FindOperation{ @@ -334,11 +334,11 @@ func TestParseInterfaceMethod_Find(t *testing.T) { Name: "FindByCityNot", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.FindOperation{ @@ -354,11 +354,11 @@ func TestParseInterfaceMethod_Find(t *testing.T) { Name: "FindByAgeLessThan", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("int")}, + {Type: code.TypeInt}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.FindOperation{ @@ -374,11 +374,11 @@ func TestParseInterfaceMethod_Find(t *testing.T) { Name: "FindByAgeLessThanEqual", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("int")}, + {Type: code.TypeInt}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.FindOperation{ @@ -394,11 +394,11 @@ func TestParseInterfaceMethod_Find(t *testing.T) { Name: "FindByAgeGreaterThan", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("int")}, + {Type: code.TypeInt}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.FindOperation{ @@ -414,11 +414,11 @@ func TestParseInterfaceMethod_Find(t *testing.T) { Name: "FindByAgeGreaterThanEqual", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("int")}, + {Type: code.TypeInt}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.FindOperation{ @@ -434,12 +434,12 @@ func TestParseInterfaceMethod_Find(t *testing.T) { Name: "FindByAgeBetween", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("int")}, - {Type: code.SimpleType("int")}, + {Type: code.TypeInt}, + {Type: code.TypeInt}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.FindOperation{ @@ -455,11 +455,11 @@ func TestParseInterfaceMethod_Find(t *testing.T) { Name: "FindByCityIn", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.ArrayType{ContainedType: code.SimpleType("string")}}, + {Type: code.ArrayType{ContainedType: code.TypeString}}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.FindOperation{ @@ -475,11 +475,11 @@ func TestParseInterfaceMethod_Find(t *testing.T) { Name: "FindByCityNotIn", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.ArrayType{ContainedType: code.SimpleType("string")}}, + {Type: code.ArrayType{ContainedType: code.TypeString}}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.FindOperation{ @@ -498,7 +498,7 @@ func TestParseInterfaceMethod_Find(t *testing.T) { }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.FindOperation{ @@ -517,7 +517,7 @@ func TestParseInterfaceMethod_Find(t *testing.T) { }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.FindOperation{ @@ -533,11 +533,11 @@ func TestParseInterfaceMethod_Find(t *testing.T) { Name: "FindByCityOrderByAge", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.FindOperation{ @@ -556,11 +556,11 @@ func TestParseInterfaceMethod_Find(t *testing.T) { Name: "FindByCityOrderByAgeAsc", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.FindOperation{ @@ -579,11 +579,11 @@ func TestParseInterfaceMethod_Find(t *testing.T) { Name: "FindByCityOrderByAgeDesc", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.FindOperation{ @@ -602,11 +602,11 @@ func TestParseInterfaceMethod_Find(t *testing.T) { Name: "FindByCityOrderByNameFirst", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.FindOperation{ @@ -625,11 +625,11 @@ func TestParseInterfaceMethod_Find(t *testing.T) { Name: "FindByCityOrderByCityAndAgeDesc", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedOperation: spec.FindOperation{ @@ -677,8 +677,8 @@ func TestParseInterfaceMethod_Update(t *testing.T) { {Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("error"), + code.TypeBool, + code.TypeError, }, }, ExpectedOperation: spec.UpdateOperation{ @@ -699,8 +699,8 @@ func TestParseInterfaceMethod_Update(t *testing.T) { {Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("error"), + code.TypeBool, + code.TypeError, }, }, ExpectedOperation: spec.UpdateOperation{ @@ -723,8 +723,8 @@ func TestParseInterfaceMethod_Update(t *testing.T) { {Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedOperation: spec.UpdateOperation{ @@ -743,12 +743,12 @@ func TestParseInterfaceMethod_Update(t *testing.T) { Name: "UpdateNameFirstByID", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, {Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("error"), + code.TypeBool, + code.TypeError, }, }, ExpectedOperation: spec.UpdateOperation{ @@ -768,12 +768,12 @@ func TestParseInterfaceMethod_Update(t *testing.T) { Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, {Type: code.SimpleType("Gender")}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, {Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedOperation: spec.UpdateOperation{ @@ -797,8 +797,8 @@ func TestParseInterfaceMethod_Update(t *testing.T) { {Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedOperation: spec.UpdateOperation{ @@ -817,12 +817,12 @@ func TestParseInterfaceMethod_Update(t *testing.T) { Name: "UpdateAgeIncByID", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("int")}, + {Type: code.TypeInt}, {Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("error"), + code.TypeBool, + code.TypeError, }, }, ExpectedOperation: spec.UpdateOperation{ @@ -841,13 +841,13 @@ func TestParseInterfaceMethod_Update(t *testing.T) { Name: "UpdateEnabledAndConsentHistoryPushByID", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("bool")}, + {Type: code.TypeBool}, {Type: code.SimpleType("ConsentHistoryItem")}, {Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedOperation: spec.UpdateOperation{ @@ -894,8 +894,8 @@ func TestParseInterfaceMethod_Delete(t *testing.T) { {Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("error"), + code.TypeBool, + code.TypeError, }, }, ExpectedOperation: spec.DeleteOperation{ @@ -911,11 +911,11 @@ func TestParseInterfaceMethod_Delete(t *testing.T) { Name: "DeleteOneByPhoneNumber", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("error"), + code.TypeBool, + code.TypeError, }, }, ExpectedOperation: spec.DeleteOperation{ @@ -931,11 +931,11 @@ func TestParseInterfaceMethod_Delete(t *testing.T) { Name: "DeleteByCity", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedOperation: spec.DeleteOperation{ @@ -953,8 +953,8 @@ func TestParseInterfaceMethod_Delete(t *testing.T) { {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedOperation: spec.DeleteOperation{ @@ -967,12 +967,12 @@ func TestParseInterfaceMethod_Delete(t *testing.T) { Name: "DeleteByCityAndGender", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, {Type: code.SimpleType("Gender")}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedOperation: spec.DeleteOperation{ @@ -992,12 +992,12 @@ func TestParseInterfaceMethod_Delete(t *testing.T) { Name: "DeleteByCityOrGender", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, {Type: code.SimpleType("Gender")}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedOperation: spec.DeleteOperation{ @@ -1017,11 +1017,11 @@ func TestParseInterfaceMethod_Delete(t *testing.T) { Name: "DeleteByCityNot", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedOperation: spec.DeleteOperation{ @@ -1037,11 +1037,11 @@ func TestParseInterfaceMethod_Delete(t *testing.T) { Name: "DeleteByAgeLessThan", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("int")}, + {Type: code.TypeInt}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedOperation: spec.DeleteOperation{ @@ -1057,11 +1057,11 @@ func TestParseInterfaceMethod_Delete(t *testing.T) { Name: "DeleteByAgeLessThanEqual", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("int")}, + {Type: code.TypeInt}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedOperation: spec.DeleteOperation{ @@ -1077,11 +1077,11 @@ func TestParseInterfaceMethod_Delete(t *testing.T) { Name: "DeleteByAgeGreaterThan", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("int")}, + {Type: code.TypeInt}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedOperation: spec.DeleteOperation{ @@ -1097,11 +1097,11 @@ func TestParseInterfaceMethod_Delete(t *testing.T) { Name: "DeleteByAgeGreaterThanEqual", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("int")}, + {Type: code.TypeInt}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedOperation: spec.DeleteOperation{ @@ -1117,12 +1117,12 @@ func TestParseInterfaceMethod_Delete(t *testing.T) { Name: "DeleteByAgeBetween", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("int")}, - {Type: code.SimpleType("int")}, + {Type: code.TypeInt}, + {Type: code.TypeInt}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedOperation: spec.DeleteOperation{ @@ -1138,11 +1138,11 @@ func TestParseInterfaceMethod_Delete(t *testing.T) { Name: "DeleteByCityIn", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.ArrayType{ContainedType: code.SimpleType("string")}}, + {Type: code.ArrayType{ContainedType: code.TypeString}}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedOperation: spec.DeleteOperation{ @@ -1184,8 +1184,8 @@ func TestParseInterfaceMethod_Count(t *testing.T) { {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedOperation: spec.CountOperation{ @@ -1201,8 +1201,8 @@ func TestParseInterfaceMethod_Count(t *testing.T) { {Type: code.SimpleType("Gender")}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedOperation: spec.CountOperation{ @@ -1261,7 +1261,7 @@ func TestParseInterfaceMethod_Insert_Invalid(t *testing.T) { Returns: []code.Type{ code.PointerType{ContainedType: code.SimpleType("UserModel")}, code.InterfaceType{}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.NewOperationReturnCountUnmatchedError(2), @@ -1272,7 +1272,7 @@ func TestParseInterfaceMethod_Insert_Invalid(t *testing.T) { Name: "Insert", Returns: []code.Type{ code.PointerType{ContainedType: code.SimpleType("UserModel")}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.NewUnsupportedReturnError(code.PointerType{ContainedType: code.SimpleType("UserModel")}, 0), @@ -1287,7 +1287,7 @@ func TestParseInterfaceMethod_Insert_Invalid(t *testing.T) { {Name: "DoSomething"}, }, }, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.NewUnsupportedReturnError(code.InterfaceType{}, 0), @@ -1312,7 +1312,7 @@ func TestParseInterfaceMethod_Insert_Invalid(t *testing.T) { }, Returns: []code.Type{ code.InterfaceType{}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.ContextParamRequiredError, @@ -1327,7 +1327,7 @@ func TestParseInterfaceMethod_Insert_Invalid(t *testing.T) { }, Returns: []code.Type{ code.InterfaceType{}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.InvalidParamError, @@ -1342,7 +1342,7 @@ func TestParseInterfaceMethod_Insert_Invalid(t *testing.T) { }, Returns: []code.Type{ code.ArrayType{ContainedType: code.InterfaceType{}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.InvalidParamError, @@ -1368,8 +1368,8 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) { Name: "FindOneByID", Returns: []code.Type{ code.SimpleType("UserModel"), - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedError: spec.NewOperationReturnCountUnmatchedError(2), @@ -1380,7 +1380,7 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) { Name: "FindOneByID", Returns: []code.Type{ code.SimpleType("UserModel"), - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.NewUnsupportedReturnError(code.SimpleType("UserModel"), 0), @@ -1391,10 +1391,10 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) { Name: "FindOneByID", Returns: []code.Type{ code.SimpleType("UserModel"), - code.SimpleType("int"), + code.TypeInt, }, }, - ExpectedError: spec.NewUnsupportedReturnError(code.SimpleType("int"), 1), + ExpectedError: spec.NewUnsupportedReturnError(code.TypeInt, 1), }, { Name: "find method without query", @@ -1402,7 +1402,7 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) { Name: "Find", Returns: []code.Type{ code.PointerType{ContainedType: code.SimpleType("UserModel")}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.QueryRequiredError, @@ -1413,7 +1413,7 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) { Name: "FindByAndGender", Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.NewInvalidQueryError([]string{"And", "Gender"}), @@ -1424,7 +1424,7 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) { Name: "FindByGenderAnd", Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.NewInvalidQueryError([]string{"Gender", "And"}), @@ -1435,7 +1435,7 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) { Name: "FindByGenderAndAndCity", Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.NewInvalidQueryError([]string{"Gender", "And", "And", "City"}), @@ -1446,7 +1446,7 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) { Name: "FindByGenderAndCityOrAge", Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.NewInvalidQueryError([]string{"Gender", "And", "City", "Or", "Age"}), @@ -1460,7 +1460,7 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) { }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.ContextParamRequiredError, @@ -1471,12 +1471,12 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) { Name: "FindByCity", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, + {Type: code.TypeString}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.InvalidParamError, @@ -1487,11 +1487,11 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) { Name: "FindByCountry", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.NewStructFieldNotFoundError([]string{"Country"}), @@ -1502,11 +1502,11 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) { Name: "FindByNameMiddle", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.NewStructFieldNotFoundError([]string{"Name", "Middle"}), @@ -1517,11 +1517,11 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) { Name: "FindByContactPhone", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.NewStructFieldNotFoundError([]string{"Contact", "Phone"}), @@ -1532,11 +1532,11 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) { Name: "FindByDefaultPaymentMethod", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.NewStructFieldNotFoundError([]string{"Default", "Payment", "Method"}), @@ -1550,7 +1550,7 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) { }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.NewIncompatibleComparatorError(spec.ComparatorTrue, code.StructField{ @@ -1567,7 +1567,7 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) { }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.NewIncompatibleComparatorError(spec.ComparatorFalse, code.StructField{ @@ -1581,14 +1581,14 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) { Name: "FindByGender", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, - ExpectedError: spec.NewArgumentTypeNotMatchedError(genderField.Name, genderField.Type, code.SimpleType("string")), + ExpectedError: spec.NewArgumentTypeNotMatchedError(genderField.Name, genderField.Type, code.TypeString), }, { Name: "mismatched method parameter type for special case", @@ -1596,15 +1596,15 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) { Name: "FindByCityIn", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.NewArgumentTypeNotMatchedError(cityField.Name, - code.ArrayType{ContainedType: code.SimpleType("string")}, code.SimpleType("string")), + code.ArrayType{ContainedType: code.TypeString}, code.TypeString), }, { Name: "misplaced operator token (leftmost)", @@ -1612,7 +1612,7 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) { Name: "FindAllOrderByAndAge", Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.NewInvalidSortError([]string{"Order", "By", "And", "Age"}), @@ -1623,7 +1623,7 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) { Name: "FindAllOrderByAgeAnd", Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.NewInvalidSortError([]string{"Order", "By", "Age", "And"}), @@ -1634,7 +1634,7 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) { Name: "FindAllOrderByAgeAndAndGender", Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.NewInvalidSortError([]string{"Order", "By", "Age", "And", "And", "Gender"}), @@ -1645,7 +1645,7 @@ func TestParseInterfaceMethod_Find_Invalid(t *testing.T) { Name: "FindAllOrderByCountry", Returns: []code.Type{ code.ArrayType{ContainedType: code.PointerType{ContainedType: code.SimpleType("UserModel")}}, - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.NewStructFieldNotFoundError([]string{"Country"}), @@ -1670,9 +1670,9 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) { Method: code.Method{ Name: "UpdateAgeByID", Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeBool, + code.TypeInt, + code.TypeError, }, }, ExpectedError: spec.NewOperationReturnCountUnmatchedError(2), @@ -1682,22 +1682,22 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) { Method: code.Method{ Name: "UpdateAgeByID", Returns: []code.Type{ - code.SimpleType("float64"), - code.SimpleType("error"), + code.TypeFloat64, + code.TypeError, }, }, - ExpectedError: spec.NewUnsupportedReturnError(code.SimpleType("float64"), 0), + ExpectedError: spec.NewUnsupportedReturnError(code.TypeFloat64, 0), }, { Name: "error return not provided", Method: code.Method{ Name: "UpdateAgeByID", Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("bool"), + code.TypeBool, + code.TypeBool, }, }, - ExpectedError: spec.NewUnsupportedReturnError(code.SimpleType("bool"), 1), + ExpectedError: spec.NewUnsupportedReturnError(code.TypeBool, 1), }, { Name: "update with no field provided", @@ -1707,8 +1707,8 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) { {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, }, Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("error"), + code.TypeBool, + code.TypeError, }, }, ExpectedError: spec.InvalidUpdateFieldsError, @@ -1721,8 +1721,8 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) { {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, }, Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("error"), + code.TypeBool, + code.TypeError, }, }, ExpectedError: spec.InvalidUpdateFieldsError, @@ -1737,8 +1737,8 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) { {Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("error"), + code.TypeBool, + code.TypeError, }, }, ExpectedError: spec.NewIncompatibleUpdateOperatorError(spec.UpdateOperatorPush, spec.FieldReference{ @@ -1758,14 +1758,14 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) { {Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("error"), + code.TypeBool, + code.TypeError, }, }, ExpectedError: spec.NewIncompatibleUpdateOperatorError(spec.UpdateOperatorInc, spec.FieldReference{ code.StructField{ Name: "City", - Type: code.SimpleType("string"), + Type: code.TypeString, }, }), }, @@ -1775,11 +1775,11 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) { Name: "UpdateCity", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("error"), + code.TypeBool, + code.TypeError, }, }, ExpectedError: spec.QueryRequiredError, @@ -1790,11 +1790,11 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) { Name: "UpdateAgeByIDAndUsernameOrGender", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("int")}, + {Type: code.TypeInt}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedError: spec.NewInvalidQueryError([]string{"ID", "And", "Username", "Or", "Gender"}), @@ -1809,8 +1809,8 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) { {Type: code.ExternalType{PackageAlias: "primitive", Name: "ObjectID"}}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedError: spec.NewArgumentTypeNotMatchedError(consentHistoryField.Name, code.SimpleType("ConsentHistoryItem"), @@ -1825,8 +1825,8 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) { // {Type: code.SimpleType("Enabled")}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedError: spec.InvalidUpdateFieldsError, @@ -1837,11 +1837,11 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) { Name: "UpdateByID", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ - code.SimpleType("bool"), - code.SimpleType("error"), + code.TypeBool, + code.TypeError, }, }, ExpectedError: spec.InvalidUpdateFieldsError, @@ -1851,12 +1851,12 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) { Method: code.Method{ Name: "UpdateAgeByGender", Params: []code.Param{ - {Type: code.SimpleType("int")}, + {Type: code.TypeInt}, {Type: code.SimpleType("Gender")}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedError: spec.ContextParamRequiredError, @@ -1867,12 +1867,12 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) { Name: "UpdateCountryByGender", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, {Type: code.SimpleType("Gender")}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedError: spec.NewStructFieldNotFoundError([]string{"Country"}), @@ -1883,15 +1883,15 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) { Name: "UpdateAgeByGender", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("float64")}, + {Type: code.TypeFloat64}, {Type: code.SimpleType("Gender")}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, - ExpectedError: spec.NewArgumentTypeNotMatchedError(ageField.Name, ageField.Type, code.SimpleType("float64")), + ExpectedError: spec.NewArgumentTypeNotMatchedError(ageField.Name, ageField.Type, code.TypeFloat64), }, { Name: "struct field does not match parameter in query", @@ -1899,15 +1899,15 @@ func TestParseInterfaceMethod_Update_Invalid(t *testing.T) { Name: "UpdateAgeByGender", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("int")}, - {Type: code.SimpleType("string")}, + {Type: code.TypeInt}, + {Type: code.TypeString}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, - ExpectedError: spec.NewArgumentTypeNotMatchedError(genderField.Name, genderField.Type, code.SimpleType("string")), + ExpectedError: spec.NewArgumentTypeNotMatchedError(genderField.Name, genderField.Type, code.TypeString), }, } @@ -1930,8 +1930,8 @@ func TestParseInterfaceMethod_Delete_Invalid(t *testing.T) { Name: "DeleteOneByID", Returns: []code.Type{ code.SimpleType("UserModel"), - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedError: spec.NewOperationReturnCountUnmatchedError(2), @@ -1941,30 +1941,30 @@ func TestParseInterfaceMethod_Delete_Invalid(t *testing.T) { Method: code.Method{ Name: "DeleteOneByID", Returns: []code.Type{ - code.SimpleType("float64"), - code.SimpleType("error"), + code.TypeFloat64, + code.TypeError, }, }, - ExpectedError: spec.NewUnsupportedReturnError(code.SimpleType("float64"), 0), + ExpectedError: spec.NewUnsupportedReturnError(code.TypeFloat64, 0), }, { Name: "error return not provided", Method: code.Method{ Name: "DeleteOneByID", Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("bool"), + code.TypeInt, + code.TypeBool, }, }, - ExpectedError: spec.NewUnsupportedReturnError(code.SimpleType("bool"), 1), + ExpectedError: spec.NewUnsupportedReturnError(code.TypeBool, 1), }, { Name: "delete method without query", Method: code.Method{ Name: "Delete", Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedError: spec.QueryRequiredError, @@ -1974,8 +1974,8 @@ func TestParseInterfaceMethod_Delete_Invalid(t *testing.T) { Method: code.Method{ Name: "DeleteByAndGender", Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedError: spec.NewInvalidQueryError([]string{"And", "Gender"}), @@ -1985,8 +1985,8 @@ func TestParseInterfaceMethod_Delete_Invalid(t *testing.T) { Method: code.Method{ Name: "DeleteByGenderAnd", Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedError: spec.NewInvalidQueryError([]string{"Gender", "And"}), @@ -1996,8 +1996,8 @@ func TestParseInterfaceMethod_Delete_Invalid(t *testing.T) { Method: code.Method{ Name: "DeleteByGenderAndAndCity", Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedError: spec.NewInvalidQueryError([]string{"Gender", "And", "And", "City"}), @@ -2007,8 +2007,8 @@ func TestParseInterfaceMethod_Delete_Invalid(t *testing.T) { Method: code.Method{ Name: "DeleteByGenderAndCityOrAge", Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedError: spec.NewInvalidQueryError([]string{"Gender", "And", "City", "Or", "Age"}), @@ -2021,8 +2021,8 @@ func TestParseInterfaceMethod_Delete_Invalid(t *testing.T) { {Type: code.SimpleType("Gender")}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedError: spec.ContextParamRequiredError, @@ -2033,12 +2033,12 @@ func TestParseInterfaceMethod_Delete_Invalid(t *testing.T) { Name: "DeleteByCity", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, + {Type: code.TypeString}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedError: spec.InvalidParamError, @@ -2049,11 +2049,11 @@ func TestParseInterfaceMethod_Delete_Invalid(t *testing.T) { Name: "DeleteByCountry", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedError: spec.NewStructFieldNotFoundError([]string{"Country"}), @@ -2064,14 +2064,14 @@ func TestParseInterfaceMethod_Delete_Invalid(t *testing.T) { Name: "DeleteByGender", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, - ExpectedError: spec.NewArgumentTypeNotMatchedError("Gender", code.SimpleType("Gender"), code.SimpleType("string")), + ExpectedError: spec.NewArgumentTypeNotMatchedError("Gender", code.SimpleType("Gender"), code.TypeString), }, { Name: "mismatched method parameter type for special case", @@ -2079,15 +2079,15 @@ func TestParseInterfaceMethod_Delete_Invalid(t *testing.T) { Name: "DeleteByCityIn", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedError: spec.NewArgumentTypeNotMatchedError("City", - code.ArrayType{ContainedType: code.SimpleType("string")}, code.SimpleType("string")), + code.ArrayType{ContainedType: code.TypeString}, code.TypeString), }, } @@ -2109,9 +2109,9 @@ func TestParseInterfaceMethod_Count_Invalid(t *testing.T) { Method: code.Method{ Name: "CountAll", Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), - code.SimpleType("bool"), + code.TypeInt, + code.TypeError, + code.TypeBool, }, }, ExpectedError: spec.NewOperationReturnCountUnmatchedError(2), @@ -2122,7 +2122,7 @@ func TestParseInterfaceMethod_Count_Invalid(t *testing.T) { Name: "CountAll", Returns: []code.Type{ code.SimpleType("int64"), - code.SimpleType("error"), + code.TypeError, }, }, ExpectedError: spec.NewUnsupportedReturnError(code.SimpleType("int64"), 0), @@ -2132,19 +2132,19 @@ func TestParseInterfaceMethod_Count_Invalid(t *testing.T) { Method: code.Method{ Name: "CountAll", Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("bool"), + code.TypeInt, + code.TypeBool, }, }, - ExpectedError: spec.NewUnsupportedReturnError(code.SimpleType("bool"), 1), + ExpectedError: spec.NewUnsupportedReturnError(code.TypeBool, 1), }, { Name: "count method without query", Method: code.Method{ Name: "Count", Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedError: spec.QueryRequiredError, @@ -2157,8 +2157,8 @@ func TestParseInterfaceMethod_Count_Invalid(t *testing.T) { {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedError: spec.NewInvalidQueryError([]string{"By"}), @@ -2168,8 +2168,8 @@ func TestParseInterfaceMethod_Count_Invalid(t *testing.T) { Method: code.Method{ Name: "CountAll", Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedError: spec.ContextParamRequiredError, @@ -2181,11 +2181,11 @@ func TestParseInterfaceMethod_Count_Invalid(t *testing.T) { Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, {Type: code.SimpleType("Gender")}, - {Type: code.SimpleType("int")}, + {Type: code.TypeInt}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedError: spec.InvalidParamError, @@ -2196,14 +2196,14 @@ func TestParseInterfaceMethod_Count_Invalid(t *testing.T) { Name: "CountByGender", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, - ExpectedError: spec.NewArgumentTypeNotMatchedError("Gender", code.SimpleType("Gender"), code.SimpleType("string")), + ExpectedError: spec.NewArgumentTypeNotMatchedError("Gender", code.SimpleType("Gender"), code.TypeString), }, { Name: "struct field not found", @@ -2211,11 +2211,11 @@ func TestParseInterfaceMethod_Count_Invalid(t *testing.T) { Name: "CountByCountry", Params: []code.Param{ {Type: code.ExternalType{PackageAlias: "context", Name: "Context"}}, - {Type: code.SimpleType("string")}, + {Type: code.TypeString}, }, Returns: []code.Type{ - code.SimpleType("int"), - code.SimpleType("error"), + code.TypeInt, + code.TypeError, }, }, ExpectedError: spec.NewStructFieldNotFoundError([]string{"Country"}), diff --git a/main.go b/main.go index feb976f..fe4202e 100644 --- a/main.go +++ b/main.go @@ -21,7 +21,8 @@ const usageText = `repogen generates MongoDB repository implementation from repo Supported options:` -const version = "v0.2.1" +// version indicates the version of repogen. +const version = "v0.3-next" func main() { flag.Usage = printUsage