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/golang/snappy v0.0.2 // 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/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/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/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/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/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=
|
||||
go.mongodb.org/mongo-driver v1.4.6 h1:rh7GdYmDrb8AQSkF8yteAus8qYOgOASWDOv1BWqBXkU=
|
||||
go.mongodb.org/mongo-driver v1.4.6/go.mod h1:WcMNYLx/IlOxLe6JRJiv2uXuCz6zBLndR4SoGjYphSc=
|
||||
go.mongodb.org/mongo-driver v1.5.0 h1:REddm85e1Nl0JPXGGhgZkgJdG/yOe6xvpXUcYK5WLt0=
|
||||
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-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-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-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-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
|
||||
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.4.1 h1:Kvvh58BN8Y9/lBi7hTekvtMpm07eUZ0ck5pRHpsMWrY=
|
||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
|
||||
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-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
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-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-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210326220804-49726bf1d181 h1:64ChN/hjER/taL4YJuA+gpLfIMT+/NFherRZixbxOhg=
|
||||
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/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.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
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
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 (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
|
@ -13,7 +15,12 @@ import (
|
|||
"github.com/sunboyy/repogen/internal/spec"
|
||||
)
|
||||
|
||||
const version = ""
|
||||
|
||||
func main() {
|
||||
flag.Usage = printUsage
|
||||
|
||||
versionPtr := flag.Bool("version", false, "print repogen version")
|
||||
sourcePtr := flag.String("src", "", "source file")
|
||||
destPtr := flag.String("dest", "", "destination file")
|
||||
modelPtr := flag.String("model", "", "model struct name")
|
||||
|
@ -21,14 +28,22 @@ func main() {
|
|||
|
||||
flag.Parse()
|
||||
|
||||
if *versionPtr {
|
||||
printVersion()
|
||||
return
|
||||
}
|
||||
|
||||
if *sourcePtr == "" {
|
||||
panic("-source flag required")
|
||||
printUsage()
|
||||
log.Fatal("-source flag required")
|
||||
}
|
||||
if *modelPtr == "" {
|
||||
panic("-model flag required")
|
||||
printUsage()
|
||||
log.Fatal("-model flag required")
|
||||
}
|
||||
if *repoPtr == "" {
|
||||
panic("-repo flag required")
|
||||
printUsage()
|
||||
log.Fatal("-repo flag required")
|
||||
}
|
||||
|
||||
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) {
|
||||
fset := token.NewFileSet()
|
||||
f, err := parser.ParseFile(fset, fileName, nil, parser.ParseComments)
|
||||
|
|
Loading…
Reference in a new issue