aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/GaijinEntertainment
diff options
context:
space:
mode:
authorTaras Madan <tarasmadan@google.com>2022-09-05 14:27:54 +0200
committerGitHub <noreply@github.com>2022-09-05 12:27:54 +0000
commitb2f2446b46bf02821d90ebedadae2bf7ae0e880e (patch)
tree923cf42842918d6bebca1d6bbdc08abed54d274d /vendor/github.com/GaijinEntertainment
parente6654faff4bcca4be92e9a8596fd4b77f747c39e (diff)
go.mod, vendor: update (#3358)
* go.mod, vendor: remove unnecessary dependencies Commands: 1. go mod tidy 2. go mod vendor * go.mod, vendor: update cloud.google.com/go Commands: 1. go get -u cloud.google.com/go 2. go mod tidy 3. go mod vendor * go.mod, vendor: update cloud.google.com/* Commands: 1. go get -u cloud.google.com/storage cloud.google.com/logging 2. go mod tidy 3. go mod vendor * go.mod, .golangci.yml, vendor: update *lint* Commands: 1. go get -u golang.org/x/tools github.com/golangci/golangci-lint@v1.47.0 2. go mod tidy 3. go mod vendor 4. edit .golangci.yml to suppress new errors (resolved in the same PR later) * all: fix lint errors hash.go: copy() recommended by gosimple parse.go: ent is never nil verifier.go: signal.Notify() with unbuffered channel is bad. Have no idea why. * .golangci.yml: adjust godot rules check-all is deprecated, but still work if you're hesitating too - I'll remove this commit
Diffstat (limited to 'vendor/github.com/GaijinEntertainment')
-rw-r--r--vendor/github.com/GaijinEntertainment/go-exhaustruct/v2/LICENSE21
-rw-r--r--vendor/github.com/GaijinEntertainment/go-exhaustruct/v2/pkg/analyzer/analyzer.go292
-rw-r--r--vendor/github.com/GaijinEntertainment/go-exhaustruct/v2/pkg/analyzer/patterns-list.go68
-rw-r--r--vendor/github.com/GaijinEntertainment/go-exhaustruct/v2/pkg/analyzer/struct-fields.go27
4 files changed, 408 insertions, 0 deletions
diff --git a/vendor/github.com/GaijinEntertainment/go-exhaustruct/v2/LICENSE b/vendor/github.com/GaijinEntertainment/go-exhaustruct/v2/LICENSE
new file mode 100644
index 000000000..6698196c5
--- /dev/null
+++ b/vendor/github.com/GaijinEntertainment/go-exhaustruct/v2/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2022 Gaijin Entertainment
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/GaijinEntertainment/go-exhaustruct/v2/pkg/analyzer/analyzer.go b/vendor/github.com/GaijinEntertainment/go-exhaustruct/v2/pkg/analyzer/analyzer.go
new file mode 100644
index 000000000..49948e12e
--- /dev/null
+++ b/vendor/github.com/GaijinEntertainment/go-exhaustruct/v2/pkg/analyzer/analyzer.go
@@ -0,0 +1,292 @@
+package analyzer
+
+import (
+ "errors"
+ "flag"
+ "go/ast"
+ "go/types"
+ "strings"
+ "sync"
+
+ "golang.org/x/tools/go/analysis"
+ "golang.org/x/tools/go/analysis/passes/inspect"
+ "golang.org/x/tools/go/ast/inspector"
+)
+
+var (
+ ErrEmptyPattern = errors.New("pattern can't be empty")
+)
+
+type analyzer struct {
+ include PatternsList
+ exclude PatternsList
+
+ typesProcessCache map[string]bool
+ typesProcessCacheMu sync.RWMutex
+
+ structFieldsCache map[string]*StructFields
+ structFieldsCacheMu sync.RWMutex
+}
+
+// NewAnalyzer returns a go/analysis-compatible analyzer.
+// -i arguments adds include patterns
+// -e arguments adds exclude patterns
+func NewAnalyzer(include []string, exclude []string) (*analysis.Analyzer, error) {
+ a := analyzer{ //nolint:exhaustruct
+ typesProcessCache: map[string]bool{},
+
+ structFieldsCache: map[string]*StructFields{},
+ }
+
+ var err error
+
+ a.include, err = newPatternsList(include)
+ if err != nil {
+ return nil, err
+ }
+
+ a.exclude, err = newPatternsList(exclude)
+ if err != nil {
+ return nil, err
+ }
+
+ return &analysis.Analyzer{ //nolint:exhaustruct
+ Name: "exhaustruct",
+ Doc: "Checks if all structure fields are initialized",
+ Run: a.run,
+ Requires: []*analysis.Analyzer{inspect.Analyzer},
+ Flags: a.newFlagSet(),
+ }, nil
+}
+
+func (a *analyzer) newFlagSet() flag.FlagSet {
+ fs := flag.NewFlagSet("exhaustruct flags", flag.PanicOnError)
+
+ fs.Var(
+ &reListVar{values: &a.include},
+ "i",
+ "Regular expression to match struct packages and names, can receive multiple flags",
+ )
+ fs.Var(
+ &reListVar{values: &a.exclude},
+ "e",
+ "Regular expression to exclude struct packages and names, can receive multiple flags",
+ )
+
+ return *fs
+}
+
+func (a *analyzer) run(pass *analysis.Pass) (interface{}, error) {
+ insp := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) //nolint:forcetypeassert
+
+ nodeTypes := []ast.Node{
+ (*ast.CompositeLit)(nil),
+ (*ast.ReturnStmt)(nil),
+ }
+
+ insp.Preorder(nodeTypes, a.newVisitor(pass))
+
+ return nil, nil //nolint:nilnil
+}
+
+//nolint:cyclop
+func (a *analyzer) newVisitor(pass *analysis.Pass) func(node ast.Node) {
+ var ret *ast.ReturnStmt
+
+ return func(node ast.Node) {
+ if retLit, ok := node.(*ast.ReturnStmt); ok {
+ // save return statement for future (to detect error-containing returns)
+ ret = retLit
+
+ return
+ }
+
+ lit, _ := node.(*ast.CompositeLit)
+ if lit.Type == nil {
+ // we're not interested in non-typed literals
+ return
+ }
+
+ typ := pass.TypesInfo.TypeOf(lit.Type)
+ if typ == nil {
+ return
+ }
+
+ strct, ok := typ.Underlying().(*types.Struct)
+ if !ok {
+ // we also not interested in non-structure literals
+ return
+ }
+
+ strctName := exprName(lit.Type)
+ if strctName == "" {
+ return
+ }
+
+ if !a.shouldProcessType(typ.String()) {
+ return
+ }
+
+ if len(lit.Elts) == 0 && ret != nil {
+ if ret.End() < lit.Pos() {
+ // we're outside last return statement
+ ret = nil
+ } else if returnContainsLiteral(ret, lit) && returnContainsError(ret, pass) {
+ // we're okay with empty literals in return statements with non-nil errors, like
+ // `return my.Struct{}, fmt.Errorf("non-nil error!")`
+ return
+ }
+ }
+
+ missingFields := a.structMissingFields(lit, strct, typ.String(), pass.Pkg.Path())
+
+ if len(missingFields) == 1 {
+ pass.Reportf(node.Pos(), "%s is missing in %s", missingFields[0], strctName)
+ } else if len(missingFields) > 1 {
+ pass.Reportf(node.Pos(), "%s are missing in %s", strings.Join(missingFields, ", "), strctName)
+ }
+ }
+}
+
+func (a *analyzer) shouldProcessType(typ string) bool {
+ if len(a.include) == 0 && len(a.exclude) == 0 {
+ // skip whole part with cache, since we have no restrictions and have to check everything
+ return true
+ }
+
+ a.typesProcessCacheMu.RLock()
+ v, ok := a.typesProcessCache[typ]
+ a.typesProcessCacheMu.RUnlock()
+
+ if !ok {
+ a.typesProcessCacheMu.Lock()
+ defer a.typesProcessCacheMu.Unlock()
+
+ v = true
+
+ if len(a.include) > 0 && !a.include.MatchesAny(typ) {
+ v = false
+ }
+
+ if v && a.exclude.MatchesAny(typ) {
+ v = false
+ }
+
+ a.typesProcessCache[typ] = v
+ }
+
+ return v
+}
+
+func (a *analyzer) structMissingFields(
+ lit *ast.CompositeLit,
+ strct *types.Struct,
+ typ string,
+ pkgPath string,
+) []string {
+ keys, unnamed := literalKeys(lit)
+ fields := a.structFields(typ, strct)
+
+ var fieldNames []string
+
+ if strings.HasPrefix(typ, pkgPath+".") {
+ // we're in same package and should match private fields
+ fieldNames = fields.All
+ } else {
+ fieldNames = fields.Public
+ }
+
+ if unnamed {
+ return fieldNames[len(keys):]
+ }
+
+ return difference(fieldNames, keys)
+}
+
+func (a *analyzer) structFields(typ string, strct *types.Struct) *StructFields {
+ a.structFieldsCacheMu.RLock()
+ fields, ok := a.structFieldsCache[typ]
+ a.structFieldsCacheMu.RUnlock()
+
+ if !ok {
+ a.structFieldsCacheMu.Lock()
+ defer a.structFieldsCacheMu.Unlock()
+
+ fields = NewStructFields(strct)
+ a.structFieldsCache[typ] = fields
+ }
+
+ return fields
+}
+
+func returnContainsLiteral(ret *ast.ReturnStmt, lit *ast.CompositeLit) bool {
+ for _, result := range ret.Results {
+ if l, ok := result.(*ast.CompositeLit); ok {
+ if lit == l {
+ return true
+ }
+ }
+ }
+
+ return false
+}
+
+func returnContainsError(ret *ast.ReturnStmt, pass *analysis.Pass) bool {
+ for _, result := range ret.Results {
+ if pass.TypesInfo.TypeOf(result).String() == "error" {
+ return true
+ }
+ }
+
+ return false
+}
+
+func literalKeys(lit *ast.CompositeLit) (keys []string, unnamed bool) {
+ for _, elt := range lit.Elts {
+ if k, ok := elt.(*ast.KeyValueExpr); ok {
+ if ident, ok := k.Key.(*ast.Ident); ok {
+ keys = append(keys, ident.Name)
+ }
+
+ continue
+ }
+
+ // in case we deal with unnamed initialization - no need to iterate over all
+ // elements - simply create slice with proper size
+ unnamed = true
+ keys = make([]string, len(lit.Elts))
+
+ return
+ }
+
+ return
+}
+
+// difference returns elements that are in `a` and not in `b`.
+func difference(a, b []string) (diff []string) {
+ mb := make(map[string]struct{}, len(b))
+ for _, x := range b {
+ mb[x] = struct{}{}
+ }
+
+ for _, x := range a {
+ if _, found := mb[x]; !found {
+ diff = append(diff, x)
+ }
+ }
+
+ return diff
+}
+
+func exprName(expr ast.Expr) string {
+ if i, ok := expr.(*ast.Ident); ok {
+ return i.Name
+ }
+
+ s, ok := expr.(*ast.SelectorExpr)
+ if !ok {
+ return ""
+ }
+
+ return s.Sel.Name
+}
diff --git a/vendor/github.com/GaijinEntertainment/go-exhaustruct/v2/pkg/analyzer/patterns-list.go b/vendor/github.com/GaijinEntertainment/go-exhaustruct/v2/pkg/analyzer/patterns-list.go
new file mode 100644
index 000000000..2884cab62
--- /dev/null
+++ b/vendor/github.com/GaijinEntertainment/go-exhaustruct/v2/pkg/analyzer/patterns-list.go
@@ -0,0 +1,68 @@
+package analyzer
+
+import (
+ "fmt"
+ "regexp"
+)
+
+type PatternsList []*regexp.Regexp
+
+// MatchesAny matches provided string against all regexps in a slice.
+func (l PatternsList) MatchesAny(str string) bool {
+ for _, r := range l {
+ if r.MatchString(str) {
+ return true
+ }
+ }
+
+ return false
+}
+
+// newPatternsList parses slice of strings to a slice of compiled regular
+// expressions.
+func newPatternsList(in []string) (PatternsList, error) {
+ list := PatternsList{}
+
+ for _, str := range in {
+ re, err := strToRegexp(str)
+ if err != nil {
+ return nil, err
+ }
+
+ list = append(list, re)
+ }
+
+ return list, nil
+}
+
+type reListVar struct {
+ values *PatternsList
+}
+
+func (v *reListVar) Set(value string) error {
+ re, err := strToRegexp(value)
+ if err != nil {
+ return err
+ }
+
+ *v.values = append(*v.values, re)
+
+ return nil
+}
+
+func (v *reListVar) String() string {
+ return ""
+}
+
+func strToRegexp(str string) (*regexp.Regexp, error) {
+ if str == "" {
+ return nil, ErrEmptyPattern
+ }
+
+ re, err := regexp.Compile(str)
+ if err != nil {
+ return nil, fmt.Errorf("unable to compile %s as regular expression: %w", str, err)
+ }
+
+ return re, nil
+}
diff --git a/vendor/github.com/GaijinEntertainment/go-exhaustruct/v2/pkg/analyzer/struct-fields.go b/vendor/github.com/GaijinEntertainment/go-exhaustruct/v2/pkg/analyzer/struct-fields.go
new file mode 100644
index 000000000..e7d004250
--- /dev/null
+++ b/vendor/github.com/GaijinEntertainment/go-exhaustruct/v2/pkg/analyzer/struct-fields.go
@@ -0,0 +1,27 @@
+package analyzer
+
+import (
+ "go/types"
+)
+
+type StructFields struct {
+ Public []string
+
+ All []string
+}
+
+func NewStructFields(strct *types.Struct) *StructFields {
+ sf := StructFields{} //nolint:exhaustruct
+
+ for i := 0; i < strct.NumFields(); i++ {
+ f := strct.Field(i)
+
+ sf.All = append(sf.All, f.Name())
+
+ if f.Exported() {
+ sf.Public = append(sf.Public, f.Name())
+ }
+ }
+
+ return &sf
+}