Add -version flag, add CONTRIBUTING.md, update dependencies

This commit is contained in:
sunboyy 2021-03-30 19:16:46 +07:00
parent aa16d6f1b6
commit b3d9bf3f8f
9 changed files with 210 additions and 165 deletions

View file

@ -63,57 +63,6 @@ const (
OrderingDescending = "DESC"
)
// UpdateOperation is a method specification for update operations
type UpdateOperation struct {
Update Update
Mode QueryMode
Query QuerySpec
}
// Update is an interface of update operation type
type Update interface {
Name() string
NumberOfArguments() int
}
// UpdateFields is a type of update operation that update specific fields
type UpdateFields []UpdateField
// Name returns UpdateFields name 'Fields'
func (u UpdateFields) Name() string {
return "Fields"
}
// NumberOfArguments returns number of update fields
func (u UpdateFields) NumberOfArguments() int {
return len(u)
}
// UpdateModel is a type of update operation that update the whole model
type UpdateModel struct {
}
// Name returns UpdateModel name 'Model'
func (u UpdateModel) Name() string {
return "Model"
}
// NumberOfArguments returns 1
func (u UpdateModel) NumberOfArguments() int {
return 1
}
// Name returns "Update" operation name
func (o UpdateOperation) Name() string {
return "Update"
}
// UpdateField stores mapping between field name in the model and the parameter index
type UpdateField struct {
FieldReference FieldReference
ParamIndex int
}
// DeleteOperation is a method specification for delete operations
type DeleteOperation struct {
Mode QueryMode

View file

@ -43,29 +43,3 @@ func TestOperationName(t *testing.T) {
})
}
}
type UpdateTypeTestCase struct {
Update spec.Update
ExpectedName string
}
func TestUpdateTypeName(t *testing.T) {
testTable := []UpdateTypeTestCase{
{
Update: spec.UpdateModel{},
ExpectedName: "Model",
},
{
Update: spec.UpdateFields{},
ExpectedName: "Fields",
},
}
for _, testCase := range testTable {
t.Run(testCase.ExpectedName, func(t *testing.T) {
if testCase.Update.Name() != testCase.ExpectedName {
t.Errorf("Expected = %v\nReceived = %v", testCase.ExpectedName, testCase.Update.Name())
}
})
}
}

View file

@ -235,79 +235,6 @@ func (p interfaceMethodParser) extractModelOrSliceReturns(returns []code.Type) (
return "", UnsupportedReturnError
}
func (p interfaceMethodParser) parseUpdateOperation(tokens []string) (Operation, error) {
mode, err := p.extractIntOrBoolReturns(p.Method.Returns)
if err != nil {
return nil, err
}
if err := p.validateContextParam(); err != nil {
return nil, err
}
updateTokens, queryTokens := p.splitUpdateAndQueryTokens(tokens)
update, err := p.parseUpdate(updateTokens)
if err != nil {
return nil, err
}
querySpec, err := p.parseQuery(queryTokens, 1+update.NumberOfArguments())
if err != nil {
return nil, err
}
if err := p.validateQueryFromParams(p.Method.Params[update.NumberOfArguments()+1:], querySpec); err != nil {
return nil, err
}
return UpdateOperation{
Update: update,
Mode: mode,
Query: querySpec,
}, nil
}
func (p interfaceMethodParser) parseUpdate(tokens []string) (Update, error) {
if len(tokens) == 0 {
requiredType := code.PointerType{ContainedType: p.StructModel.ReferencedType()}
if len(p.Method.Params) <= 1 || p.Method.Params[1].Type != requiredType {
return nil, InvalidUpdateFieldsError
}
return UpdateModel{}, nil
}
updateFieldTokens, ok := splitByAnd(tokens)
if !ok {
return nil, InvalidUpdateFieldsError
}
var updateFields UpdateFields
paramIndex := 1
for _, updateFieldToken := range updateFieldTokens {
updateFieldReference, ok := p.fieldResolver.ResolveStructField(p.StructModel, updateFieldToken)
if !ok {
return nil, NewStructFieldNotFoundError(updateFieldToken)
}
updateFields = append(updateFields, UpdateField{
FieldReference: updateFieldReference,
ParamIndex: paramIndex,
})
paramIndex++
}
for _, field := range updateFields {
if len(p.Method.Params) <= field.ParamIndex ||
field.FieldReference.ReferencedField().Type != p.Method.Params[field.ParamIndex].Type {
return nil, InvalidUpdateFieldsError
}
}
return updateFields, nil
}
func splitByAnd(tokens []string) ([][]string, bool) {
var updateFieldTokens [][]string
var aggregatedToken []string

127
internal/spec/update.go Normal file
View file

@ -0,0 +1,127 @@
package spec
import "github.com/sunboyy/repogen/internal/code"
// UpdateOperation is a method specification for update operations
type UpdateOperation struct {
Update Update
Mode QueryMode
Query QuerySpec
}
// Name returns "Update" operation name
func (o UpdateOperation) Name() string {
return "Update"
}
// Update is an interface of update operation type
type Update interface {
Name() string
NumberOfArguments() int
}
// UpdateModel is a type of update operation that update the whole model
type UpdateModel struct {
}
// Name returns UpdateModel name 'Model'
func (u UpdateModel) Name() string {
return "Model"
}
// NumberOfArguments returns 1
func (u UpdateModel) NumberOfArguments() int {
return 1
}
// UpdateFields is a type of update operation that update specific fields
type UpdateFields []UpdateField
// Name returns UpdateFields name 'Fields'
func (u UpdateFields) Name() string {
return "Fields"
}
// NumberOfArguments returns number of update fields
func (u UpdateFields) NumberOfArguments() int {
return len(u)
}
// UpdateField stores mapping between field name in the model and the parameter index
type UpdateField struct {
FieldReference FieldReference
ParamIndex int
}
func (p interfaceMethodParser) parseUpdateOperation(tokens []string) (Operation, error) {
mode, err := p.extractIntOrBoolReturns(p.Method.Returns)
if err != nil {
return nil, err
}
if err := p.validateContextParam(); err != nil {
return nil, err
}
updateTokens, queryTokens := p.splitUpdateAndQueryTokens(tokens)
update, err := p.parseUpdate(updateTokens)
if err != nil {
return nil, err
}
querySpec, err := p.parseQuery(queryTokens, 1+update.NumberOfArguments())
if err != nil {
return nil, err
}
if err := p.validateQueryFromParams(p.Method.Params[update.NumberOfArguments()+1:], querySpec); err != nil {
return nil, err
}
return UpdateOperation{
Update: update,
Mode: mode,
Query: querySpec,
}, nil
}
func (p interfaceMethodParser) parseUpdate(tokens []string) (Update, error) {
if len(tokens) == 0 {
requiredType := code.PointerType{ContainedType: p.StructModel.ReferencedType()}
if len(p.Method.Params) <= 1 || p.Method.Params[1].Type != requiredType {
return nil, InvalidUpdateFieldsError
}
return UpdateModel{}, nil
}
updateFieldTokens, ok := splitByAnd(tokens)
if !ok {
return nil, InvalidUpdateFieldsError
}
var updateFields UpdateFields
paramIndex := 1
for _, updateFieldToken := range updateFieldTokens {
updateFieldReference, ok := p.fieldResolver.ResolveStructField(p.StructModel, updateFieldToken)
if !ok {
return nil, NewStructFieldNotFoundError(updateFieldToken)
}
updateFields = append(updateFields, UpdateField{
FieldReference: updateFieldReference,
ParamIndex: paramIndex,
})
paramIndex++
}
for _, field := range updateFields {
if len(p.Method.Params) <= field.ParamIndex ||
field.FieldReference.ReferencedField().Type != p.Method.Params[field.ParamIndex].Type {
return nil, InvalidUpdateFieldsError
}
}
return updateFields, nil
}

View file

@ -0,0 +1,33 @@
package spec_test
import (
"testing"
"github.com/sunboyy/repogen/internal/spec"
)
type UpdateTypeTestCase struct {
Update spec.Update
ExpectedName string
}
func TestUpdateTypeName(t *testing.T) {
testTable := []UpdateTypeTestCase{
{
Update: spec.UpdateModel{},
ExpectedName: "Model",
},
{
Update: spec.UpdateFields{},
ExpectedName: "Fields",
},
}
for _, testCase := range testTable {
t.Run(testCase.ExpectedName, func(t *testing.T) {
if testCase.Update.Name() != testCase.ExpectedName {
t.Errorf("Expected = %v\nReceived = %v", testCase.ExpectedName, testCase.Update.Name())
}
})
}
}