Add -version flag, add CONTRIBUTING.md, update dependencies
This commit is contained in:
parent
aa16d6f1b6
commit
b3d9bf3f8f
9 changed files with 210 additions and 165 deletions
7
CONTRIBUTING.md
Normal file
7
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# Contributing
|
||||||
|
|
||||||
|
## Styleguides
|
||||||
|
|
||||||
|
- Use default `goimports` for code formatting.
|
||||||
|
- Use default `golint`, `golangci-lint` and `go vet` for linting.
|
||||||
|
- Do not use boolean flag in function arguments.
|
6
go.mod
6
go.mod
|
@ -7,11 +7,11 @@ require (
|
||||||
github.com/fatih/camelcase v1.0.0
|
github.com/fatih/camelcase v1.0.0
|
||||||
github.com/golang/snappy v0.0.2 // indirect
|
github.com/golang/snappy v0.0.2 // indirect
|
||||||
github.com/klauspost/compress v1.11.7 // indirect
|
github.com/klauspost/compress v1.11.7 // indirect
|
||||||
go.mongodb.org/mongo-driver v1.4.6
|
go.mongodb.org/mongo-driver v1.5.0
|
||||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect
|
||||||
golang.org/x/mod v0.4.1 // indirect
|
golang.org/x/mod v0.4.2 // indirect
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a // indirect
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a // indirect
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c // indirect
|
golang.org/x/sys v0.0.0-20210326220804-49726bf1d181 // indirect
|
||||||
golang.org/x/text v0.3.5 // indirect
|
golang.org/x/text v0.3.5 // indirect
|
||||||
golang.org/x/tools v0.1.0
|
golang.org/x/tools v0.1.0
|
||||||
)
|
)
|
||||||
|
|
18
go.sum
18
go.sum
|
@ -87,21 +87,22 @@ github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c h1:u40Z8hqBAAQyv+vATcGgV
|
||||||
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
|
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
|
||||||
github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc h1:n+nNi93yXLkJvKwXNP9d55HC7lGK4H/SRcwB5IaUZLo=
|
github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc h1:n+nNi93yXLkJvKwXNP9d55HC7lGK4H/SRcwB5IaUZLo=
|
||||||
github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
|
github.com/xdg/stringprep v0.0.0-20180714160509-73f8eece6fdc/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
|
||||||
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA=
|
||||||
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
go.mongodb.org/mongo-driver v1.4.6 h1:rh7GdYmDrb8AQSkF8yteAus8qYOgOASWDOv1BWqBXkU=
|
go.mongodb.org/mongo-driver v1.5.0 h1:REddm85e1Nl0JPXGGhgZkgJdG/yOe6xvpXUcYK5WLt0=
|
||||||
go.mongodb.org/mongo-driver v1.4.6/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc=
|
go.mongodb.org/mongo-driver v1.5.0/go.mod h1:boiGPFqyBs5R0R5qf2ErokGRekMfwn+MqKaUyHs7wy0=
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||||
golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
|
||||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.1 h1:Kvvh58BN8Y9/lBi7hTekvtMpm07eUZ0ck5pRHpsMWrY=
|
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
|
||||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
@ -126,11 +127,10 @@ golang.org/x/sys v0.0.0-20190531175056-4c3a928424d2/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
|
golang.org/x/sys v0.0.0-20210326220804-49726bf1d181 h1:64ChN/hjER/taL4YJuA+gpLfIMT+/NFherRZixbxOhg=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210326220804-49726bf1d181/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
|
golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
|
||||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
|
|
@ -63,57 +63,6 @@ const (
|
||||||
OrderingDescending = "DESC"
|
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
|
// DeleteOperation is a method specification for delete operations
|
||||||
type DeleteOperation struct {
|
type DeleteOperation struct {
|
||||||
Mode QueryMode
|
Mode QueryMode
|
||||||
|
|
|
@ -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())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -235,79 +235,6 @@ func (p interfaceMethodParser) extractModelOrSliceReturns(returns []code.Type) (
|
||||||
return "", UnsupportedReturnError
|
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) {
|
func splitByAnd(tokens []string) ([][]string, bool) {
|
||||||
var updateFieldTokens [][]string
|
var updateFieldTokens [][]string
|
||||||
var aggregatedToken []string
|
var aggregatedToken []string
|
||||||
|
|
127
internal/spec/update.go
Normal file
127
internal/spec/update.go
Normal 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
|
||||||
|
}
|
33
internal/spec/update_test.go
Normal file
33
internal/spec/update_test.go
Normal 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())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
34
main.go
34
main.go
|
@ -3,8 +3,10 @@ package main
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
|
"fmt"
|
||||||
"go/parser"
|
"go/parser"
|
||||||
"go/token"
|
"go/token"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
@ -13,7 +15,12 @@ import (
|
||||||
"github.com/sunboyy/repogen/internal/spec"
|
"github.com/sunboyy/repogen/internal/spec"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const version = ""
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
flag.Usage = printUsage
|
||||||
|
|
||||||
|
versionPtr := flag.Bool("version", false, "print repogen version")
|
||||||
sourcePtr := flag.String("src", "", "source file")
|
sourcePtr := flag.String("src", "", "source file")
|
||||||
destPtr := flag.String("dest", "", "destination file")
|
destPtr := flag.String("dest", "", "destination file")
|
||||||
modelPtr := flag.String("model", "", "model struct name")
|
modelPtr := flag.String("model", "", "model struct name")
|
||||||
|
@ -21,14 +28,22 @@ func main() {
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
if *versionPtr {
|
||||||
|
printVersion()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if *sourcePtr == "" {
|
if *sourcePtr == "" {
|
||||||
panic("-source flag required")
|
printUsage()
|
||||||
|
log.Fatal("-source flag required")
|
||||||
}
|
}
|
||||||
if *modelPtr == "" {
|
if *modelPtr == "" {
|
||||||
panic("-model flag required")
|
printUsage()
|
||||||
|
log.Fatal("-model flag required")
|
||||||
}
|
}
|
||||||
if *repoPtr == "" {
|
if *repoPtr == "" {
|
||||||
panic("-repo flag required")
|
printUsage()
|
||||||
|
log.Fatal("-repo flag required")
|
||||||
}
|
}
|
||||||
|
|
||||||
code, err := generateFromRequest(*sourcePtr, *modelPtr, *repoPtr)
|
code, err := generateFromRequest(*sourcePtr, *modelPtr, *repoPtr)
|
||||||
|
@ -54,6 +69,19 @@ func main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func printUsage() {
|
||||||
|
fmt.Println("Usage of repogen")
|
||||||
|
flag.PrintDefaults()
|
||||||
|
}
|
||||||
|
|
||||||
|
func printVersion() {
|
||||||
|
if version != "" {
|
||||||
|
fmt.Println(version)
|
||||||
|
} else {
|
||||||
|
fmt.Println("(devel)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func generateFromRequest(fileName, structModelName, repositoryInterfaceName string) (string, error) {
|
func generateFromRequest(fileName, structModelName, repositoryInterfaceName string) (string, error) {
|
||||||
fset := token.NewFileSet()
|
fset := token.NewFileSet()
|
||||||
f, err := parser.ParseFile(fset, fileName, nil, parser.ParseComments)
|
f, err := parser.ParseFile(fset, fileName, nil, parser.ParseComments)
|
||||||
|
|
Loading…
Reference in a new issue