From 2fdafde84d48f88503dcf267f1bbc040bf4a9f49 Mon Sep 17 00:00:00 2001 From: Denis Isaev Date: Sat, 16 Mar 2019 17:44:13 +0300 Subject: [PATCH] refactor the project --- .codeclimate.yml | 13 -- .gitignore | 1 + .golangci.yml | 37 ++++ .travis.yml | 11 +- Makefile | 20 +-- cmd/goqueryset/goqueryset.go | 26 ++- {parser => internal/parser}/parser.go | 158 ++++++++---------- {parser => internal/parser}/parser_test.go | 35 ++-- {parser => internal/parser}/test/test.go | 0 .../queryset}/field/field.go | 0 .../queryset}/field/field_test.go | 0 internal/queryset/generator/generator.go | 103 ++++++++++++ .../queryset/generator}/methodsbuilder.go | 8 +- .../queryset/generator}/queryset.go | 26 ++- .../queryset/generator}/queryset_test.go | 54 +++--- .../queryset/generator}/template.go | 2 +- .../generator}/test/autogenerated_models.go | 2 +- .../queryset/generator}/test/models.go | 4 +- .../test/pkgimport/autogenerated_models.go | 2 +- .../test/pkgimport/forex/v1/types.go | 0 .../generator}/test/pkgimport/models.go | 4 +- .../queryset/generator}/tmp/tmp.go | 0 .../queryset}/methods/base.go | 0 .../queryset}/methods/context.go | 4 +- .../queryset}/methods/field_utils.go | 0 .../queryset}/methods/field_utils_test.go | 0 .../queryset}/methods/fields.go | 0 .../queryset}/methods/gorm.go | 0 .../queryset}/methods/queryset.go | 32 ++-- .../queryset}/methods/struct.go | 0 .../queryset}/methods/updater.go | 0 queryset/bootstrap.go | 93 ----------- queryset/compile | Bin 286724 -> 0 bytes 33 files changed, 326 insertions(+), 309 deletions(-) delete mode 100644 .codeclimate.yml create mode 100644 .golangci.yml rename {parser => internal/parser}/parser.go (57%) rename {parser => internal/parser}/parser_test.go (86%) rename {parser => internal/parser}/test/test.go (100%) rename {queryset => internal/queryset}/field/field.go (100%) rename {queryset => internal/queryset}/field/field_test.go (100%) create mode 100644 internal/queryset/generator/generator.go rename {queryset => internal/queryset/generator}/methodsbuilder.go (95%) rename {queryset => internal/queryset/generator}/queryset.go (76%) rename {queryset => internal/queryset/generator}/queryset_test.go (85%) rename {queryset => internal/queryset/generator}/template.go (99%) rename {queryset => internal/queryset/generator}/test/autogenerated_models.go (99%) rename {queryset => internal/queryset/generator}/test/models.go (86%) rename {queryset => internal/queryset/generator}/test/pkgimport/autogenerated_models.go (99%) rename {queryset => internal/queryset/generator}/test/pkgimport/forex/v1/types.go (100%) rename {queryset => internal/queryset/generator}/test/pkgimport/models.go (55%) rename {queryset => internal/queryset/generator}/tmp/tmp.go (100%) rename {queryset => internal/queryset}/methods/base.go (100%) rename {queryset => internal/queryset}/methods/context.go (92%) rename {queryset => internal/queryset}/methods/field_utils.go (100%) rename {queryset => internal/queryset}/methods/field_utils_test.go (100%) rename {queryset => internal/queryset}/methods/fields.go (100%) rename {queryset => internal/queryset}/methods/gorm.go (100%) rename {queryset => internal/queryset}/methods/queryset.go (94%) rename {queryset => internal/queryset}/methods/struct.go (100%) rename {queryset => internal/queryset}/methods/updater.go (100%) delete mode 100644 queryset/bootstrap.go delete mode 100644 queryset/compile diff --git a/.codeclimate.yml b/.codeclimate.yml deleted file mode 100644 index baf8a21..0000000 --- a/.codeclimate.yml +++ /dev/null @@ -1,13 +0,0 @@ -version: "2" - -exclude_patterns: -- "**/autogenerated_*" -- "**/vendor/" - -checks: - file-lines: - config: - threshold: 400 - method-lines: - config: - threshold: 100 diff --git a/.gitignore b/.gitignore index db181c1..9886722 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /go-queryset /vendor +/internal/parser/test/tmptestdir*/ diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..1d70599 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,37 @@ +run: + skip-dirs: + - ^internal/parser/test/tmptestdir.* + +linters-settings: + govet: + check-shadowing: true + golint: + min-confidence: 0 + gocyclo: + min-complexity: 15 + goconst: + min-len: 2 + min-occurrences: 2 + lll: + line-length: 140 + +linters: + enable-all: true + disable: + - scopelint + - gochecknoglobals + - gosec + +issues: + exclude-rules: + - linters: + - unparam + text: always receives + - linters: + - staticcheck + text: "SA9003:" + +# golangci.com configuration +# https://github.com/golangci/golangci/wiki/Configuration +# service: +# golangci-lint-version: 1.14.0 # use fixed version to not introduce new linters unexpectedly diff --git a/.travis.yml b/.travis.yml index c0119a5..dd3f0f1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,10 @@ language: go go: - - 1.8.x - - 1.9.x + - 1.11.x + - 1.12.x before_install: - go get github.com/mattn/goveralls - - go get github.com/alecthomas/gometalinter - - go get github.com/golang/dep/cmd/dep - - dep ensure -v - - gometalinter --install --vendored-linters + - curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin v1.15.0 script: - make test - - $HOME/gopath/bin/goveralls -ignore "queryset/test/autogenerated_models.go,examples/comparison/*/*.go,queryset/test/pkgimport/*.go,queryset/test/pkgimport/*/*/*.go" -v -service=travis-ci + - $HOME/gopath/bin/goveralls -ignore "internal/queryset/generator/test/autogenerated_models.go,examples/comparison/*/*.go,internal/queryset/generator/test/pkgimport/*.go,internal/queryset/generator/test/pkgimport/*/*/*.go" -v -service=travis-ci diff --git a/Makefile b/Makefile index 1559649..1b701d9 100644 --- a/Makefile +++ b/Makefile @@ -1,24 +1,14 @@ test_static: - go install ./... - gometalinter --vendor --enable-all --min-confidence=0.3 --line-length=120 \ - -e "parameter \w+ always receives" \ - -e "/jinzhu/gorm/" \ - -e "model is unused" \ - -e '"expections" is a misspelling of "exceptions"' \ - -e "autogenerated_" \ - -e "should have comment" \ - -e "examples/comparison/" \ - --deadline=5m \ - ./... + golangci-lint run test_unit: test_gen mkdir -p test - go test -v ./parser/ ./queryset/ ./queryset/methods/ + go test -v ./... AUTOGEN_FILES = \ - ./queryset/test/autogenerated_models.go \ + ./internal/queryset/generator/test/autogenerated_models.go \ ./examples/comparison/gorm4/autogenerated_gorm4.go \ - ./queryset/test/pkgimport/autogenerated_models.go + ./internal/queryset/generator/test/pkgimport/autogenerated_models.go test_gen: gen @- $(foreach F,$(AUTOGEN_FILES), \ @@ -28,7 +18,7 @@ test_gen: gen test: test_unit bench test_static bench: - go test -bench=. -benchtime=1s -v -run=^$$ ./queryset/ + go test -bench=. -benchtime=1s -v -run=^$$ ./internal/queryset/generator/ gen: @- $(foreach F,$(AUTOGEN_FILES), \ diff --git a/cmd/goqueryset/goqueryset.go b/cmd/goqueryset/goqueryset.go index 350bf8e..8b5321c 100644 --- a/cmd/goqueryset/goqueryset.go +++ b/cmd/goqueryset/goqueryset.go @@ -1,20 +1,36 @@ package main import ( + "context" "flag" "log" - "strings" + "path/filepath" + "time" - "github.com/jirfag/go-queryset/queryset" + "github.com/jirfag/go-queryset/internal/parser" + "github.com/jirfag/go-queryset/internal/queryset/generator" ) func main() { + const defaultOutPath = "autogenerated_{in}" + inFile := flag.String("in", "models.go", "path to input file") - outFile := flag.String("out", "autogenerated_{in}", "path to output file") + outFile := flag.String("out", defaultOutPath, "path to output file") + timeout := flag.Duration("timeout", time.Minute, "timeout for generation") flag.Parse() - *outFile = strings.Replace(*outFile, "{in}", *inFile, 1) - if err := queryset.GenerateQuerySets(*inFile, *outFile); err != nil { + if *outFile == defaultOutPath { + *outFile = filepath.Join(filepath.Dir(*inFile), "autogenerated_"+filepath.Base(*inFile)) + } + + g := generator.Generator{ + StructsParser: &parser.Structs{}, + } + + ctx, finish := context.WithTimeout(context.Background(), *timeout) + defer finish() + + if err := g.Generate(ctx, *inFile, *outFile); err != nil { log.Fatalf("can't generate query sets: %s", err) } } diff --git a/parser/parser.go b/internal/parser/parser.go similarity index 57% rename from parser/parser.go rename to internal/parser/parser.go index 8609133..598ca46 100644 --- a/parser/parser.go +++ b/internal/parser/parser.go @@ -1,17 +1,19 @@ package parser import ( + "context" "fmt" "go/ast" "go/parser" "go/token" "go/types" - "os" "path/filepath" "reflect" "strings" - "golang.org/x/tools/go/loader" + "github.com/pkg/errors" + + "golang.org/x/tools/go/packages" ) // StructField represents one field in struct @@ -33,9 +35,6 @@ func (sf StructField) Tag() reflect.StructTag { return sf.tag } -// ParsedStructs is a map from struct type name to list of fields -type ParsedStructs map[string]ParsedStruct - // ParsedStruct represents struct info type ParsedStruct struct { TypeName string @@ -43,47 +42,79 @@ type ParsedStruct struct { Doc *ast.CommentGroup // line comments; or nil } -func fileNameToPkgName(filePath, absFilePath string) string { - dir := filepath.Dir(absFilePath) - gopathEnv := os.Getenv("GOPATH") - gopaths := strings.Split(gopathEnv, string(os.PathListSeparator)) - var inGoPath string - for _, gopath := range gopaths { - if strings.HasPrefix(dir, gopath) { - inGoPath = gopath - break - } - } - if inGoPath == "" { - // not in GOPATH - return "./" + filepath.Dir(filePath) - } - r := strings.TrimPrefix(dir, inGoPath) - r = strings.TrimPrefix(r, "/") // may be and may not be - r = strings.TrimPrefix(r, "\\") // may be and may not be - r = strings.TrimPrefix(r, "src/") - r = strings.TrimPrefix(r, "src\\") - return r +type Result struct { + Structs map[string]ParsedStruct + PackageName string + Types *types.Package } -func typeCheckFuncBodies(path string) bool { - return false // don't type-check func bodies to speedup parsing -} +type Structs struct{} -func loadProgramFromPackage(pkgFullName string) (*loader.Program, error) { - // The loader loads a complete Go program from source code. - conf := loader.Config{ - ParserMode: parser.ParseComments, - TypeCheckFuncBodies: typeCheckFuncBodies, +func (p Structs) ParseFile(ctx context.Context, filePath string) (*Result, error) { + absFilePath, err := filepath.Abs(filePath) + if err != nil { + return nil, errors.Wrapf(err, "can't get abs path for %s", filePath) } - conf.Import(pkgFullName) - lprog, err := conf.Load() + + neededStructs, err := p.getStructNamesInFile(absFilePath) if err != nil { - return nil, fmt.Errorf("can't load program from package %q: %s", - pkgFullName, err) + return nil, errors.Wrap(err, "can't get struct names") + } + + // need load the full package type info because + // some deps can be in other files + inPkgName := filepath.Dir(filePath) + if !filepath.IsAbs(inPkgName) && !strings.HasPrefix(inPkgName, ".") { + // to make this dir name a local package name + // can't use filepath.Join because it calls Clean and removes "."+sep + inPkgName = fmt.Sprintf(".%c%s", filepath.Separator, inPkgName) + } + + pkgs, err := packages.Load(&packages.Config{ + Mode: packages.LoadAllSyntax, + Context: ctx, + Tests: false, + }, inPkgName) + if err != nil { + return nil, errors.Wrapf(err, "failed to load package for file %s", filePath) + } + + if len(pkgs) != 1 { + return nil, fmt.Errorf("got too many (%d) packages: %#v", len(pkgs), pkgs) + } + + structs := p.buildParsedStructs(pkgs[0], neededStructs) + return &Result{ + Structs: structs, + PackageName: pkgs[0].Name, + Types: pkgs[0].Types, + }, nil +} + +func (p Structs) buildParsedStructs(pkg *packages.Package, neededStructs structNamesInfo) map[string]ParsedStruct { + ret := map[string]ParsedStruct{} + + scope := pkg.Types.Scope() + for _, name := range scope.Names() { + obj := scope.Lookup(name) + + if neededStructs[name] == nil { + continue + } + + t := obj.Type().(*types.Named) + s := t.Underlying().(*types.Struct) + + parsedStruct := parseStruct(s, neededStructs[name]) + if parsedStruct != nil { + parsedStruct.TypeName = name + ret[name] = *parsedStruct + } else { + // TODO + } } - return lprog, nil + return ret } type structNamesInfo map[string]*ast.GenDecl @@ -106,7 +137,7 @@ func (v *structNamesVisitor) Visit(n ast.Node) (w ast.Visitor) { return v } -func getStructNamesInFile(fname string) (structNamesInfo, error) { +func (p Structs) getStructNamesInFile(fname string) (structNamesInfo, error) { fset := token.NewFileSet() f, err := parser.ParseFile(fset, fname, nil, parser.ParseComments) if err != nil { @@ -120,53 +151,6 @@ func getStructNamesInFile(fname string) (structNamesInfo, error) { return v.names, nil } -// GetStructsInFile lists all structures in file passed and returns them with all fields -func GetStructsInFile(filePath string) (*loader.PackageInfo, ParsedStructs, error) { - absFilePath, err := filepath.Abs(filePath) - if err != nil { - return nil, nil, fmt.Errorf("can't get abs path for %s", filePath) - } - - neededStructs, err := getStructNamesInFile(absFilePath) - if err != nil { - return nil, nil, fmt.Errorf("can't get struct names: %s", err) - } - - packageFullName := fileNameToPkgName(filePath, absFilePath) - lprog, err := loadProgramFromPackage(packageFullName) - if err != nil { - return nil, nil, err - } - - pkgInfo := lprog.Package(packageFullName) - if pkgInfo == nil { - return nil, nil, fmt.Errorf("can't load types for file %s in package %q", - filePath, packageFullName) - } - - ret := ParsedStructs{} - - scope := pkgInfo.Pkg.Scope() - for _, name := range scope.Names() { - obj := scope.Lookup(name) - - if neededStructs[name] == nil { - continue - } - - t := obj.Type().(*types.Named) - s := t.Underlying().(*types.Struct) - - parsedStruct := parseStruct(s, neededStructs[name]) - if parsedStruct != nil { - parsedStruct.TypeName = name - ret[name] = *parsedStruct - } - } - - return pkgInfo, ret, nil -} - func newStructField(f *types.Var, tag string) *StructField { return &StructField{ name: f.Name(), diff --git a/parser/parser_test.go b/internal/parser/parser_test.go similarity index 86% rename from parser/parser_test.go rename to internal/parser/parser_test.go index 0a0c9c6..ff0fe9f 100644 --- a/parser/parser_test.go +++ b/internal/parser/parser_test.go @@ -1,6 +1,7 @@ package parser import ( + "context" "crypto/rand" "encoding/hex" "fmt" @@ -9,7 +10,6 @@ import ( "os" "path/filepath" "runtime" - "strings" "testing" "github.com/stretchr/testify/assert" @@ -30,23 +30,7 @@ func getRepoRoot() string { } func getTempDirRoot() string { - return filepath.Join(getRepoRoot(), "test") -} - -func TestFileNameToPkgName(t *testing.T) { - _, selfFilePath, _, ok := runtime.Caller(0) - assert.True(t, ok) - assert.NotEmpty(t, selfFilePath) - selfPkg := "github.com/jirfag/go-queryset/parser" - if !strings.Contains(selfFilePath, selfPkg) { - t.Skipf("it's a forked repo %q, skip pkg path test", selfFilePath) - } - - assert.Equal(t, selfPkg, fileNameToPkgName("", selfFilePath)) - - const fileNotInGoPath = "models/models.go" - const absFileNotInGoPath = "/tmp/" + fileNotInGoPath - assert.Equal(t, "./models", fileNameToPkgName(fileNotInGoPath, absFileNotInGoPath)) + return filepath.Join(getRepoRoot(), "parser", "test") } func getTempFileName(rootDir, prefix, suffix string) (*os.File, error) { @@ -123,6 +107,7 @@ func TestGetStructNamesInFile(t *testing.T) { }, } + p := Structs{} for i, tc := range cases { tc := tc // capture range variable t.Run(fmt.Sprintf("case %d", i), func(t *testing.T) { @@ -130,7 +115,7 @@ func TestGetStructNamesInFile(t *testing.T) { f := getTmpFileForCode(tc.code) defer removeTempFileAndDir(f) - res, err := getStructNamesInFile(f.Name()) + res, err := p.getStructNamesInFile(f.Name()) if tc.errorIsExpected { assert.NotNil(t, err) return @@ -267,24 +252,24 @@ func testStructFields(t *testing.T, tc structFieldsCase) { f := getTmpFileForCode(tc.code) defer removeTempFileAndDir(f) - pkg, structs, err := GetStructsInFile(f.Name()) + p := Structs{} + ret, err := p.ParseFile(context.Background(), f.Name()) if tc.errorIsExpected { assert.NotNil(t, err) return } assert.Nil(t, err) - assert.NotNil(t, pkg) - assert.NotNil(t, structs) + assert.NotNil(t, ret) - assert.Len(t, structs, tc.getExpectedtructsCount()) + assert.Len(t, ret.Structs, tc.getExpectedtructsCount()) if tc.getExpectedtructsCount() == 0 { return } var typeName string - for structTypeName := range structs { + for structTypeName := range ret.Structs { if structTypeName == "T" { typeName = structTypeName break @@ -292,7 +277,7 @@ func testStructFields(t *testing.T, tc structFieldsCase) { } assert.NotNil(t, typeName) - s := structs[typeName] + s := ret.Structs[typeName] fieldNames := []string{} for _, field := range s.Fields { assert.NotEmpty(t, field.Name) diff --git a/parser/test/test.go b/internal/parser/test/test.go similarity index 100% rename from parser/test/test.go rename to internal/parser/test/test.go diff --git a/queryset/field/field.go b/internal/queryset/field/field.go similarity index 100% rename from queryset/field/field.go rename to internal/queryset/field/field.go diff --git a/queryset/field/field_test.go b/internal/queryset/field/field_test.go similarity index 100% rename from queryset/field/field_test.go rename to internal/queryset/field/field_test.go diff --git a/internal/queryset/generator/generator.go b/internal/queryset/generator/generator.go new file mode 100644 index 0000000..7d4f6bc --- /dev/null +++ b/internal/queryset/generator/generator.go @@ -0,0 +1,103 @@ +package generator + +import ( + "bytes" + "context" + "fmt" + "io" + "log" + "os" + "path/filepath" + + "github.com/jirfag/go-queryset/internal/parser" + "github.com/pkg/errors" + "golang.org/x/tools/imports" +) + +type Generator struct { + StructsParser *parser.Structs +} + +// Generate generates output file with querysets +func (g Generator) Generate(ctx context.Context, inFilePath, outFilePath string) error { + parsedFile, err := g.StructsParser.ParseFile(ctx, inFilePath) + if err != nil { + return errors.Wrapf(err, "can't parse file %s to get structs", inFilePath) + } + + var r io.Reader + r, err = GenerateQuerySetsForStructs(parsedFile.Types, parsedFile.Structs) + if err != nil { + return errors.Wrap(err, "can't generate query sets") + } + + if r == nil { + return fmt.Errorf("no structs to generate query set in %s", inFilePath) + } + + if err = g.writeQuerySetsToOutput(r, parsedFile.PackageName, outFilePath); err != nil { + return errors.Wrapf(err, "can't save query sets to out file %s", outFilePath) + } + + var absOutPath string + absOutPath, err = filepath.Abs(outFilePath) + if err != nil { + absOutPath = outFilePath + } + + log.Printf("successfully wrote querysets to %s", absOutPath) + return nil +} + +func (g Generator) writeQuerySetsToOutput(r io.Reader, packageName, outFile string) error { + const hdrTmpl = `%s + package %s + +import ( + "errors" + "fmt" + "time" + + "github.com/jinzhu/gorm" +) +` + + // https://golang.org/s/generatedcode + const genHdr = `// Code generated by go-queryset. DO NOT EDIT.` + + var buf bytes.Buffer + pkgName := fmt.Sprintf(hdrTmpl, genHdr, packageName) + if _, err := buf.WriteString(pkgName); err != nil { + return errors.Wrap(err, "can't write hdr string into buf") + } + if _, err := io.Copy(&buf, r); err != nil { + return errors.Wrap(err, "can't write to buf") + } + + formattedRes, err := imports.Process(outFile, buf.Bytes(), nil) + if err != nil { + if os.Getenv("GOQUERYSET_DEBUG_IMPORTS_ERRORS") == "1" { + log.Printf("Can't format generated file: %s", err) + formattedRes = buf.Bytes() + } else { + return errors.Wrap(err, "can't format generated file") + } + } + + var outF *os.File + outF, err = os.OpenFile(outFile, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0640) // nolint: gas + if err != nil { + return fmt.Errorf("can't open out file: %s", err) + } + defer func() { + if e := outF.Close(); e != nil { + log.Printf("can't close file: %s", e) + } + }() + + if _, err = outF.Write(formattedRes); err != nil { + return errors.Wrap(err, "can't write to out file") + } + + return nil +} diff --git a/queryset/methodsbuilder.go b/internal/queryset/generator/methodsbuilder.go similarity index 95% rename from queryset/methodsbuilder.go rename to internal/queryset/generator/methodsbuilder.go index 64777a3..e0276a5 100644 --- a/queryset/methodsbuilder.go +++ b/internal/queryset/generator/methodsbuilder.go @@ -1,9 +1,9 @@ -package queryset +package generator import ( - "github.com/jirfag/go-queryset/parser" - "github.com/jirfag/go-queryset/queryset/field" - "github.com/jirfag/go-queryset/queryset/methods" + "github.com/jirfag/go-queryset/internal/parser" + "github.com/jirfag/go-queryset/internal/queryset/field" + "github.com/jirfag/go-queryset/internal/queryset/methods" ) type methodsBuilder struct { diff --git a/queryset/queryset.go b/internal/queryset/generator/queryset.go similarity index 76% rename from queryset/queryset.go rename to internal/queryset/generator/queryset.go index da71685..d9e34e0 100644 --- a/queryset/queryset.go +++ b/internal/queryset/generator/queryset.go @@ -1,18 +1,17 @@ -package queryset +package generator import ( "bytes" "fmt" "go/ast" + "go/types" "io" "sort" "strings" - "golang.org/x/tools/go/loader" - - "github.com/jirfag/go-queryset/parser" - "github.com/jirfag/go-queryset/queryset/field" - "github.com/jirfag/go-queryset/queryset/methods" + "github.com/jirfag/go-queryset/internal/parser" + "github.com/jirfag/go-queryset/internal/queryset/field" + "github.com/jirfag/go-queryset/internal/queryset/methods" ) type querySetStructConfig struct { @@ -56,8 +55,8 @@ func doesNeedToGenerateQuerySet(doc *ast.CommentGroup) bool { return false } -func genStructFieldInfos(s parser.ParsedStruct, pkgInfo *loader.PackageInfo) (ret []field.Info) { - g := field.NewInfoGenerator(pkgInfo.Pkg) +func genStructFieldInfos(s parser.ParsedStruct, types *types.Package) (ret []field.Info) { + g := field.NewInfoGenerator(types) for _, f := range s.Fields { fi := g.GenFieldInfo(f) if fi == nil { @@ -68,8 +67,8 @@ func genStructFieldInfos(s parser.ParsedStruct, pkgInfo *loader.PackageInfo) (re return ret } -func generateQuerySetConfigs(pkgInfo *loader.PackageInfo, - structs parser.ParsedStructs) querySetStructConfigSlice { +func generateQuerySetConfigs(types *types.Package, + structs map[string]parser.ParsedStruct) querySetStructConfigSlice { querySetStructConfigs := querySetStructConfigSlice{} @@ -78,7 +77,7 @@ func generateQuerySetConfigs(pkgInfo *loader.PackageInfo, continue } - fields := genStructFieldInfos(s, pkgInfo) + fields := genStructFieldInfos(s, types) b := newMethodsBuilder(s, fields) methods := b.Build() @@ -97,9 +96,8 @@ func generateQuerySetConfigs(pkgInfo *loader.PackageInfo, // GenerateQuerySetsForStructs is an internal method to retrieve querysets // generated code from parsed structs -func GenerateQuerySetsForStructs(pkgInfo *loader.PackageInfo, structs parser.ParsedStructs) (io.Reader, error) { - - querySetStructConfigs := generateQuerySetConfigs(pkgInfo, structs) +func GenerateQuerySetsForStructs(types *types.Package, structs map[string]parser.ParsedStruct) (io.Reader, error) { + querySetStructConfigs := generateQuerySetConfigs(types, structs) if len(querySetStructConfigs) == 0 { return nil, nil } diff --git a/queryset/queryset_test.go b/internal/queryset/generator/queryset_test.go similarity index 85% rename from queryset/queryset_test.go rename to internal/queryset/generator/queryset_test.go index fd7790c..9dc6e5c 100644 --- a/queryset/queryset_test.go +++ b/internal/queryset/generator/queryset_test.go @@ -1,6 +1,7 @@ -package queryset +package generator import ( + "context" "database/sql" "database/sql/driver" "fmt" @@ -15,14 +16,18 @@ import ( "testing" "time" + "github.com/jirfag/go-queryset/internal/parser" + "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mysql" - "github.com/jirfag/go-queryset/queryset/test" - "github.com/stretchr/testify/assert" + "github.com/jirfag/go-queryset/internal/queryset/generator/test" + assert "github.com/stretchr/testify/require" - "gopkg.in/DATA-DOG/go-sqlmock.v1" + sqlmock "gopkg.in/DATA-DOG/go-sqlmock.v1" ) +const testSurname = "Ivanov" + func fixedFullRe(s string) string { return fmt.Sprintf("^%s$", regexp.QuoteMeta(s)) } @@ -139,7 +144,7 @@ func TestQueries(t *testing.T) { func testUserSelectAll(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) { expUsers := getTestUsers(2) - m.ExpectQuery(fixedFullRe("SELECT * FROM `users` WHERE `users`.deleted_at IS NULL")). + m.ExpectQuery(fixedFullRe("SELECT * FROM `users` WHERE `users`.`deleted_at` IS NULL")). WillReturnRows(getRowsForUsers(expUsers)) var users []test.User @@ -149,7 +154,7 @@ func testUserSelectAll(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) { func testUserSelectWithLimitAndOffset(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) { expUsers := getTestUsers(2) - req := "SELECT * FROM `users` WHERE `users`.deleted_at IS NULL LIMIT 1 OFFSET 1" + req := "SELECT * FROM `users` WHERE `users`.`deleted_at` IS NULL LIMIT 1 OFFSET 1" m.ExpectQuery(fixedFullRe(req)). WillReturnRows(getRowsForUsers(expUsers)) @@ -159,7 +164,7 @@ func testUserSelectWithLimitAndOffset(t *testing.T, m sqlmock.Sqlmock, db *gorm. } func testUserSelectAllNoRecords(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) { - m.ExpectQuery(fixedFullRe("SELECT * FROM `users` WHERE `users`.deleted_at IS NULL")). + m.ExpectQuery(fixedFullRe("SELECT * FROM `users` WHERE `users`.`deleted_at` IS NULL")). WillReturnError(sql.ErrNoRows) var users []test.User @@ -169,7 +174,7 @@ func testUserSelectAllNoRecords(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) { func testUserSelectOne(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) { expUsers := getTestUsers(1) - req := "SELECT * FROM `users` WHERE `users`.deleted_at IS NULL ORDER BY `users`.`id` ASC LIMIT 1" + req := "SELECT * FROM `users` WHERE `users`.`deleted_at` IS NULL ORDER BY `users`.`id` ASC LIMIT 1" m.ExpectQuery(fixedFullRe(req)). WillReturnRows(getRowsForUsers(expUsers)) @@ -181,11 +186,11 @@ func testUserSelectOne(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) { func testUserSelectWithSurnameFilter(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) { expUsers := getTestUsers(1) - surname := "Ivanov" + surname := testSurname expUsers[0].Surname = &surname req := "SELECT * FROM `users` " + - "WHERE `users`.deleted_at IS NULL AND ((user_surname = ?)) ORDER BY `users`.`id` ASC LIMIT 1" + "WHERE `users`.`deleted_at` IS NULL AND ((user_surname = ?)) ORDER BY `users`.`id` ASC LIMIT 1" m.ExpectQuery(fixedFullRe(req)). WillReturnRows(getRowsForUsers(expUsers)) @@ -242,7 +247,7 @@ func testUserQueryFilters(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) { func runUserQueryFilterSubTest(t *testing.T, c userQueryTestCase, m sqlmock.Sqlmock, db *gorm.DB) { expUsers := getTestUsers(5) - req := "SELECT * FROM `users` WHERE `users`.deleted_at IS NULL AND " + c.q + req := "SELECT * FROM `users` WHERE `users`.`deleted_at` IS NULL AND " + c.q m.ExpectQuery(fixedFullRe(req)).WithArgs(c.args...). WillReturnRows(getRowsForUsers(expUsers)) @@ -270,7 +275,7 @@ func testUserCreateOneWithSurname(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) req := "INSERT INTO `users` (`created_at`,`updated_at`,`deleted_at`,`name`,`user_surname`,`email`) " + "VALUES (?,?,?,?,?,?)" - surname := "Ivanov" + surname := testSurname u.Surname = &surname args := []driver.Value{sqlmock.AnyArg(), sqlmock.AnyArg(), sqlmock.AnyArg(), @@ -284,7 +289,7 @@ func testUserCreateOneWithSurname(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) func testUserUpdateByEmail(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) { u := getUser() - req := "UPDATE `users` SET `name` = ? WHERE `users`.deleted_at IS NULL AND ((email = ?))" + req := "UPDATE `users` SET `name` = ? WHERE `users`.`deleted_at` IS NULL AND ((email = ?))" m.ExpectExec(fixedFullRe(req)). WithArgs(u.Name, u.Email). WillReturnResult(sqlmock.NewResult(0, 1)) @@ -299,7 +304,7 @@ func testUserUpdateByEmail(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) { func testUserUpdateFieldsByPK(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) { u := getUser() - req := "UPDATE `users` SET `name` = ? WHERE `users`.deleted_at IS NULL AND `users`.`id` = ?" + req := "UPDATE `users` SET `name` = ? WHERE `users`.`deleted_at` IS NULL AND `users`.`id` = ?" m.ExpectExec(fixedFullRe(req)). WithArgs(u.Name, u.ID). WillReturnResult(sqlmock.NewResult(0, 1)) @@ -309,7 +314,7 @@ func testUserUpdateFieldsByPK(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) { func testUserDeleteByEmail(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) { u := getUser() - req := "UPDATE `users` SET deleted_at=? WHERE `users`.deleted_at IS NULL AND ((email = ?))" + req := "UPDATE `users` SET `deleted_at`=? WHERE `users`.`deleted_at` IS NULL AND ((email = ?))" m.ExpectExec(fixedFullRe(req)). WithArgs(sqlmock.AnyArg(), u.Email). WillReturnResult(sqlmock.NewResult(0, 1)) @@ -322,7 +327,7 @@ func testUserDeleteByEmail(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) { func testUserDeleteByPK(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) { u := getUser() - req := "UPDATE `users` SET deleted_at=? WHERE `users`.deleted_at IS NULL AND `users`.`id` = ?" + req := "UPDATE `users` SET `deleted_at`=? WHERE `users`.`deleted_at` IS NULL AND `users`.`id` = ?" m.ExpectExec(fixedFullRe(req)). WithArgs(sqlmock.AnyArg(), u.ID). WillReturnResult(sqlmock.NewResult(0, 1)) @@ -333,7 +338,7 @@ func testUserDeleteByPK(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) { func testUsersDeleteNum(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) { usersNum := 2 users := getTestUsers(usersNum) - req := "UPDATE `users` SET deleted_at=? WHERE `users`.deleted_at IS NULL AND ((email IN (?,?)))" + req := "UPDATE `users` SET `deleted_at`=? WHERE `users`.`deleted_at` IS NULL AND ((email IN (?,?)))" m.ExpectExec(fixedFullRe(req)). WithArgs(sqlmock.AnyArg(), users[0].Email, users[1].Email). WillReturnResult(sqlmock.NewResult(0, int64(usersNum))) @@ -363,7 +368,7 @@ func testUsersDeleteNumUnscoped(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) { func testUsersUpdateNum(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) { usersNum := 2 users := getTestUsers(usersNum) - req := "UPDATE `users` SET `name` = ? WHERE `users`.deleted_at IS NULL AND ((email IN (?,?)))" + req := "UPDATE `users` SET `name` = ? WHERE `users`.`deleted_at` IS NULL AND ((email IN (?,?)))" m.ExpectExec(fixedFullRe(req)). WithArgs(sqlmock.AnyArg(), users[0].Email, users[1].Email). WillReturnResult(sqlmock.NewResult(0, int64(usersNum))) @@ -379,7 +384,7 @@ func testUsersUpdateNum(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) { func testUsersCount(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) { expCount := 5 - req := "SELECT count(*) FROM `users` WHERE `users`.deleted_at IS NULL AND ((name != ?))" + req := "SELECT count(*) FROM `users` WHERE `users`.`deleted_at` IS NULL AND ((name != ?))" m.ExpectQuery(fixedFullRe(req)).WithArgs(driver.Value("")). WillReturnRows(getRowWithFields([]driver.Value{expCount})) @@ -389,7 +394,10 @@ func testUsersCount(t *testing.T, m sqlmock.Sqlmock, db *gorm.DB) { } func TestMain(m *testing.M) { - err := GenerateQuerySets("test/models.go", "test/autogenerated_models.go") + g := Generator{ + StructsParser: &parser.Structs{}, + } + err := g.Generate(context.Background(), "test/models.go", "test/autogenerated_models.go") if err != nil { panic(err) } @@ -398,8 +406,12 @@ func TestMain(m *testing.M) { } func BenchmarkHello(b *testing.B) { + g := Generator{ + StructsParser: &parser.Structs{}, + } + for i := 0; i < b.N; i++ { - err := GenerateQuerySets("test/models.go", "test/autogenerated_models.go") + err := g.Generate(context.Background(), "test/models.go", "test/autogenerated_models.go") if err != nil { b.Fatalf("can't generate querysets: %s", err) } diff --git a/queryset/template.go b/internal/queryset/generator/template.go similarity index 99% rename from queryset/template.go rename to internal/queryset/generator/template.go index d0ed0af..c6d2633 100644 --- a/queryset/template.go +++ b/internal/queryset/generator/template.go @@ -1,4 +1,4 @@ -package queryset +package generator import ( "text/template" diff --git a/queryset/test/autogenerated_models.go b/internal/queryset/generator/test/autogenerated_models.go similarity index 99% rename from queryset/test/autogenerated_models.go rename to internal/queryset/generator/test/autogenerated_models.go index 48fe53a..315655b 100644 --- a/queryset/test/autogenerated_models.go +++ b/internal/queryset/generator/test/autogenerated_models.go @@ -7,7 +7,7 @@ import ( "time" "github.com/jinzhu/gorm" - "github.com/jirfag/go-queryset/queryset/tmp" + "github.com/jirfag/go-queryset/internal/queryset/generator/tmp" ) // ===== BEGIN of all query sets diff --git a/queryset/test/models.go b/internal/queryset/generator/test/models.go similarity index 86% rename from queryset/test/models.go rename to internal/queryset/generator/test/models.go index 851e690..7ec12fe 100644 --- a/queryset/test/models.go +++ b/internal/queryset/generator/test/models.go @@ -2,10 +2,10 @@ package test import ( "github.com/jinzhu/gorm" - "github.com/jirfag/go-queryset/queryset/tmp" + "github.com/jirfag/go-queryset/internal/queryset/generator/tmp" ) -//go:generate go run ../../cmd/goqueryset/goqueryset.go -in models.go +//go:generate go run ../../../../cmd/goqueryset/goqueryset.go -in models.go // User is a usual user // gen:qs diff --git a/queryset/test/pkgimport/autogenerated_models.go b/internal/queryset/generator/test/pkgimport/autogenerated_models.go similarity index 99% rename from queryset/test/pkgimport/autogenerated_models.go rename to internal/queryset/generator/test/pkgimport/autogenerated_models.go index 0545eff..7df060a 100644 --- a/queryset/test/pkgimport/autogenerated_models.go +++ b/internal/queryset/generator/test/pkgimport/autogenerated_models.go @@ -6,7 +6,7 @@ import ( "fmt" "github.com/jinzhu/gorm" - forex "github.com/jirfag/go-queryset/queryset/test/pkgimport/forex/v1" + forex "github.com/jirfag/go-queryset/internal/queryset/generator/test/pkgimport/forex/v1" ) // ===== BEGIN of all query sets diff --git a/queryset/test/pkgimport/forex/v1/types.go b/internal/queryset/generator/test/pkgimport/forex/v1/types.go similarity index 100% rename from queryset/test/pkgimport/forex/v1/types.go rename to internal/queryset/generator/test/pkgimport/forex/v1/types.go diff --git a/queryset/test/pkgimport/models.go b/internal/queryset/generator/test/pkgimport/models.go similarity index 55% rename from queryset/test/pkgimport/models.go rename to internal/queryset/generator/test/pkgimport/models.go index f296675..3cb8171 100644 --- a/queryset/test/pkgimport/models.go +++ b/internal/queryset/generator/test/pkgimport/models.go @@ -3,8 +3,8 @@ package models //go:generate goqueryset -in models.go import ( - forex "github.com/jirfag/go-queryset/queryset/test/pkgimport/forex/v1" - forexAlias "github.com/jirfag/go-queryset/queryset/test/pkgimport/forex/v1" + forex "github.com/jirfag/go-queryset/internal/queryset/generator/test/pkgimport/forex/v1" + forexAlias "github.com/jirfag/go-queryset/internal/queryset/generator/test/pkgimport/forex/v1" ) // Example is a test struct diff --git a/queryset/tmp/tmp.go b/internal/queryset/generator/tmp/tmp.go similarity index 100% rename from queryset/tmp/tmp.go rename to internal/queryset/generator/tmp/tmp.go diff --git a/queryset/methods/base.go b/internal/queryset/methods/base.go similarity index 100% rename from queryset/methods/base.go rename to internal/queryset/methods/base.go diff --git a/queryset/methods/context.go b/internal/queryset/methods/context.go similarity index 92% rename from queryset/methods/context.go rename to internal/queryset/methods/context.go index 62337df..93582f1 100644 --- a/queryset/methods/context.go +++ b/internal/queryset/methods/context.go @@ -1,8 +1,8 @@ package methods import ( - "github.com/jirfag/go-queryset/parser" - "github.com/jirfag/go-queryset/queryset/field" + "github.com/jirfag/go-queryset/internal/parser" + "github.com/jirfag/go-queryset/internal/queryset/field" ) type QsStructContext struct { diff --git a/queryset/methods/field_utils.go b/internal/queryset/methods/field_utils.go similarity index 100% rename from queryset/methods/field_utils.go rename to internal/queryset/methods/field_utils.go diff --git a/queryset/methods/field_utils_test.go b/internal/queryset/methods/field_utils_test.go similarity index 100% rename from queryset/methods/field_utils_test.go rename to internal/queryset/methods/field_utils_test.go diff --git a/queryset/methods/fields.go b/internal/queryset/methods/fields.go similarity index 100% rename from queryset/methods/fields.go rename to internal/queryset/methods/fields.go diff --git a/queryset/methods/gorm.go b/internal/queryset/methods/gorm.go similarity index 100% rename from queryset/methods/gorm.go rename to internal/queryset/methods/gorm.go diff --git a/queryset/methods/queryset.go b/internal/queryset/methods/queryset.go similarity index 94% rename from queryset/methods/queryset.go rename to internal/queryset/methods/queryset.go index 724a4c1..76d14c0 100644 --- a/queryset/methods/queryset.go +++ b/internal/queryset/methods/queryset.go @@ -272,27 +272,27 @@ func NewDeleteMethod(qsTypeName, structTypeName string) DeleteMethod { // DeleteNumMethod creates DeleteNum method type DeleteNumMethod struct { - namedMethod - baseQuerySetMethod + namedMethod + baseQuerySetMethod - noArgsMethod - constBodyMethod - constRetMethod + noArgsMethod + constBodyMethod + constRetMethod } // NewDeleteNumMethod delete row count func NewDeleteNumMethod(qsTypeName, structTypeName string) DeleteNumMethod { - return DeleteNumMethod{ - namedMethod: newNamedMethod("DeleteNum"), - baseQuerySetMethod: newBaseQuerySetMethod(qsTypeName), - constRetMethod: newConstRetMethod("(int64, error)"), - constBodyMethod: newConstBodyMethod( - strings.Join([]string{ - "db := qs.db.Delete(" + structTypeName + "{}" + ")", - "return db.RowsAffected, db.Error", - }, "\n"), - ), - } + return DeleteNumMethod{ + namedMethod: newNamedMethod("DeleteNum"), + baseQuerySetMethod: newBaseQuerySetMethod(qsTypeName), + constRetMethod: newConstRetMethod("(int64, error)"), + constBodyMethod: newConstBodyMethod( + strings.Join([]string{ + "db := qs.db.Delete(" + structTypeName + "{}" + ")", + "return db.RowsAffected, db.Error", + }, "\n"), + ), + } } // DeleteNumUnscopedMethod creates DeleteNumUnscoped method for performing hard deletes diff --git a/queryset/methods/struct.go b/internal/queryset/methods/struct.go similarity index 100% rename from queryset/methods/struct.go rename to internal/queryset/methods/struct.go diff --git a/queryset/methods/updater.go b/internal/queryset/methods/updater.go similarity index 100% rename from queryset/methods/updater.go rename to internal/queryset/methods/updater.go diff --git a/queryset/bootstrap.go b/queryset/bootstrap.go deleted file mode 100644 index b0dc254..0000000 --- a/queryset/bootstrap.go +++ /dev/null @@ -1,93 +0,0 @@ -package queryset - -import ( - "bytes" - "fmt" - "io" - "log" - "os" - "path/filepath" - - "github.com/jirfag/go-queryset/parser" - "golang.org/x/tools/go/loader" - "golang.org/x/tools/imports" -) - -// GenerateQuerySets generates output file with querysets -func GenerateQuerySets(inFilePath, outFilePath string) error { - pkgInfo, structs, err := parser.GetStructsInFile(inFilePath) - if err != nil { - return fmt.Errorf("can't parse file %s to get structs: %s", inFilePath, err) - } - - var r io.Reader - r, err = GenerateQuerySetsForStructs(pkgInfo, structs) - if err != nil { - return fmt.Errorf("can't generate query sets: %s", err) - } - - if r == nil { - return fmt.Errorf("no structs to generate query set in %s", inFilePath) - } - - if err = writeQuerySetsToOutput(r, pkgInfo, outFilePath); err != nil { - return fmt.Errorf("can't save query sets to out file %s: %s", outFilePath, err) - } - - var absOutPath string - absOutPath, err = filepath.Abs(outFilePath) - if err != nil { - absOutPath = outFilePath - } - - log.Printf("successfully wrote querysets to %s", absOutPath) - return nil -} - -func writeQuerySetsToOutput(r io.Reader, pkgInfo *loader.PackageInfo, outFile string) error { - const hdrTmpl = `%s - package %s - -import ( - "errors" - "fmt" - "time" - - "github.com/jinzhu/gorm" -) -` - - // https://golang.org/s/generatedcode - const genHdr = `// Code generated by go-queryset. DO NOT EDIT.` - - var buf bytes.Buffer - pkgName := fmt.Sprintf(hdrTmpl, genHdr, pkgInfo.Pkg.Name()) - if _, err := buf.WriteString(pkgName); err != nil { - return fmt.Errorf("can't write hdr string into buf: %s", err) - } - if _, err := io.Copy(&buf, r); err != nil { - return fmt.Errorf("can't write to buf: %s", err) - } - - formattedRes, err := imports.Process(outFile, buf.Bytes(), nil) - if err != nil { - return fmt.Errorf("can't format generated file: %s", err) - } - - var outF *os.File - outF, err = os.OpenFile(outFile, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0640) // nolint: gas - if err != nil { - return fmt.Errorf("can't open out file: %s", err) - } - defer func() { - if e := outF.Close(); e != nil { - log.Printf("can't close file: %s", e) - } - }() - - if _, err = outF.Write(formattedRes); err != nil { - return fmt.Errorf("can't write to out file: %s", err) - } - - return nil -} diff --git a/queryset/compile b/queryset/compile deleted file mode 100644 index 28efd778b2f89b495e5d819c5ae17f4b70e850ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 286724 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