aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/ghostiam
diff options
context:
space:
mode:
authordependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>2024-03-04 17:40:11 +0000
committerTaras Madan <tarasmadan@google.com>2024-03-04 18:34:55 +0000
commit5fc5366972c874b919f93165bb4ed4e2bcb7c350 (patch)
tree287c3361a0dee0c72af80d9a1a66714a06e98a62 /vendor/github.com/ghostiam
parent1be5ce38a9059c356eb193a8c34d60d61c9fc31f (diff)
mod: bump github.com/golangci/golangci-lint from 1.55.2 to 1.56.2
Bumps [github.com/golangci/golangci-lint](https://github.com/golangci/golangci-lint) from 1.55.2 to 1.56.2. - [Release notes](https://github.com/golangci/golangci-lint/releases) - [Changelog](https://github.com/golangci/golangci-lint/blob/master/CHANGELOG.md) - [Commits](https://github.com/golangci/golangci-lint/compare/v1.55.2...v1.56.2) --- updated-dependencies: - dependency-name: github.com/golangci/golangci-lint dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com>
Diffstat (limited to 'vendor/github.com/ghostiam')
-rw-r--r--vendor/github.com/ghostiam/protogetter/Makefile2
-rw-r--r--vendor/github.com/ghostiam/protogetter/processor.go131
-rw-r--r--vendor/github.com/ghostiam/protogetter/protogetter.go130
3 files changed, 239 insertions, 24 deletions
diff --git a/vendor/github.com/ghostiam/protogetter/Makefile b/vendor/github.com/ghostiam/protogetter/Makefile
index af4b62bdf..4c2a62af1 100644
--- a/vendor/github.com/ghostiam/protogetter/Makefile
+++ b/vendor/github.com/ghostiam/protogetter/Makefile
@@ -1,6 +1,6 @@
.PHONY: test
test:
- cd testdata && make vendor
+ $(MAKE) -C testdata vendor
go test -v ./...
.PHONY: install
diff --git a/vendor/github.com/ghostiam/protogetter/processor.go b/vendor/github.com/ghostiam/protogetter/processor.go
index 445f136b8..d65199dd2 100644
--- a/vendor/github.com/ghostiam/protogetter/processor.go
+++ b/vendor/github.com/ghostiam/protogetter/processor.go
@@ -12,16 +12,18 @@ import (
type processor struct {
info *types.Info
filter *PosFilter
+ cfg *Config
to strings.Builder
from strings.Builder
err error
}
-func Process(info *types.Info, filter *PosFilter, n ast.Node) (*Result, error) {
+func Process(info *types.Info, filter *PosFilter, n ast.Node, cfg *Config) (*Result, error) {
p := &processor{
info: info,
filter: filter,
+ cfg: cfg,
}
return p.process(n)
@@ -31,8 +33,12 @@ func (c *processor) process(n ast.Node) (*Result, error) {
switch x := n.(type) {
case *ast.AssignStmt:
// Skip any assignment to the field.
- for _, lhs := range x.Lhs {
- c.filter.AddPos(lhs.Pos())
+ for _, s := range x.Lhs {
+ c.filter.AddPos(s.Pos())
+
+ if se, ok := s.(*ast.StarExpr); ok {
+ c.filter.AddPos(se.X.Pos())
+ }
}
case *ast.IncDecStmt:
@@ -47,6 +53,14 @@ func (c *processor) process(n ast.Node) (*Result, error) {
}
case *ast.CallExpr:
+ if !c.cfg.ReplaceFirstArgInAppend && len(x.Args) > 0 {
+ if v, ok := x.Fun.(*ast.Ident); ok && v.Name == "append" {
+ // Skip first argument of append function.
+ c.filter.AddPos(x.Args[0].Pos())
+ break
+ }
+ }
+
f, ok := x.Fun.(*ast.SelectorExpr)
if !ok {
return &Result{}, nil
@@ -66,6 +80,67 @@ func (c *processor) process(n ast.Node) (*Result, error) {
c.processInner(x)
+ case *ast.StarExpr:
+ f, ok := x.X.(*ast.SelectorExpr)
+ if !ok {
+ return &Result{}, nil
+ }
+
+ if !isProtoMessage(c.info, f.X) {
+ return &Result{}, nil
+ }
+
+ // proto2 generates fields as pointers. Hence, the indirection
+ // must be removed when generating the fix for the case.
+ // The `*` is retained in `c.from`, but excluded from the fix
+ // present in the `c.to`.
+ c.writeFrom("*")
+ c.processInner(x.X)
+
+ case *ast.BinaryExpr:
+ // Check if the expression is a comparison.
+ if x.Op != token.EQL && x.Op != token.NEQ {
+ return &Result{}, nil
+ }
+
+ // Check if one of the operands is nil.
+
+ xIdent, xOk := x.X.(*ast.Ident)
+ yIdent, yOk := x.Y.(*ast.Ident)
+
+ xIsNil := xOk && xIdent.Name == "nil"
+ yIsNil := yOk && yIdent.Name == "nil"
+
+ if !xIsNil && !yIsNil {
+ return &Result{}, nil
+ }
+
+ // Extract the non-nil operand for further checks
+
+ var expr ast.Expr
+ if xIsNil {
+ expr = x.Y
+ } else {
+ expr = x.X
+ }
+
+ se, ok := expr.(*ast.SelectorExpr)
+ if !ok {
+ return &Result{}, nil
+ }
+
+ if !isProtoMessage(c.info, se.X) {
+ return &Result{}, nil
+ }
+
+ // Check if the Getter function of the protobuf message returns a pointer.
+ hasPointer, ok := getterResultHasPointer(c.info, se.X, se.Sel.Name)
+ if !ok || hasPointer {
+ return &Result{}, nil
+ }
+
+ c.filter.AddPos(x.X.Pos())
+
default:
return nil, fmt.Errorf("not implemented for type: %s (%s)", reflect.TypeOf(x), formatNode(n))
}
@@ -204,14 +279,14 @@ func isProtoMessage(info *types.Info, expr ast.Expr) bool {
return false
}
-func methodIsExists(info *types.Info, x ast.Expr, name string) bool {
+func typesNamed(info *types.Info, x ast.Expr) (*types.Named, bool) {
if info == nil {
- return false
+ return nil, false
}
t := info.TypeOf(x)
if t == nil {
- return false
+ return nil, false
}
ptr, ok := t.Underlying().(*types.Pointer)
@@ -221,6 +296,15 @@ func methodIsExists(info *types.Info, x ast.Expr, name string) bool {
named, ok := t.(*types.Named)
if !ok {
+ return nil, false
+ }
+
+ return named, true
+}
+
+func methodIsExists(info *types.Info, x ast.Expr, name string) bool {
+ named, ok := typesNamed(info, x)
+ if !ok {
return false
}
@@ -232,3 +316,38 @@ func methodIsExists(info *types.Info, x ast.Expr, name string) bool {
return false
}
+
+func getterResultHasPointer(info *types.Info, x ast.Expr, name string) (hasPointer, ok bool) {
+ named, ok := typesNamed(info, x)
+ if !ok {
+ return false, false
+ }
+
+ for i := 0; i < named.NumMethods(); i++ {
+ method := named.Method(i)
+ if method.Name() != "Get"+name {
+ continue
+ }
+
+ var sig *types.Signature
+ sig, ok = method.Type().(*types.Signature)
+ if !ok {
+ return false, false
+ }
+
+ results := sig.Results()
+ if results.Len() == 0 {
+ return false, false
+ }
+
+ firstType := results.At(0)
+ _, ok = firstType.Type().(*types.Pointer)
+ if !ok {
+ return false, true
+ }
+
+ return true, true
+ }
+
+ return false, false
+}
diff --git a/vendor/github.com/ghostiam/protogetter/protogetter.go b/vendor/github.com/ghostiam/protogetter/protogetter.go
index 80a829672..31eee8572 100644
--- a/vendor/github.com/ghostiam/protogetter/protogetter.go
+++ b/vendor/github.com/ghostiam/protogetter/protogetter.go
@@ -2,13 +2,16 @@ package protogetter
import (
"bytes"
+ "flag"
"fmt"
"go/ast"
"go/format"
"go/token"
"log"
+ "path/filepath"
"strings"
+ "github.com/gobwas/glob"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/ast/inspector"
)
@@ -22,34 +25,101 @@ const (
const msgFormat = "avoid direct access to proto field %s, use %s instead"
-func NewAnalyzer() *analysis.Analyzer {
+func NewAnalyzer(cfg *Config) *analysis.Analyzer {
+ if cfg == nil {
+ cfg = &Config{}
+ }
+
return &analysis.Analyzer{
- Name: "protogetter",
- Doc: "Reports direct reads from proto message fields when getters should be used",
+ Name: "protogetter",
+ Doc: "Reports direct reads from proto message fields when getters should be used",
+ Flags: flags(cfg),
Run: func(pass *analysis.Pass) (any, error) {
- Run(pass, StandaloneMode)
- return nil, nil
+ _, err := Run(pass, cfg)
+ return nil, err
},
}
}
-func Run(pass *analysis.Pass, mode Mode) []Issue {
+func flags(opts *Config) flag.FlagSet {
+ fs := flag.NewFlagSet("protogetter", flag.ContinueOnError)
+
+ fs.Func("skip-generated-by", "skip files generated with the given prefixes", func(s string) error {
+ for _, prefix := range strings.Split(s, ",") {
+ opts.SkipGeneratedBy = append(opts.SkipGeneratedBy, prefix)
+ }
+ return nil
+ })
+ fs.Func("skip-files", "skip files with the given glob patterns", func(s string) error {
+ for _, pattern := range strings.Split(s, ",") {
+ opts.SkipFiles = append(opts.SkipFiles, pattern)
+ }
+ return nil
+ })
+ fs.BoolVar(&opts.SkipAnyGenerated, "skip-any-generated", false, "skip any generated files")
+
+ return *fs
+}
+
+type Config struct {
+ Mode Mode // Zero value is StandaloneMode.
+ SkipGeneratedBy []string
+ SkipFiles []string
+ SkipAnyGenerated bool
+ ReplaceFirstArgInAppend bool
+}
+
+func Run(pass *analysis.Pass, cfg *Config) ([]Issue, error) {
+ skipGeneratedBy := make([]string, 0, len(cfg.SkipGeneratedBy)+3)
+ // Always skip files generated by protoc-gen-go, protoc-gen-go-grpc and protoc-gen-grpc-gateway.
+ skipGeneratedBy = append(skipGeneratedBy, "protoc-gen-go", "protoc-gen-go-grpc", "protoc-gen-grpc-gateway")
+ for _, s := range cfg.SkipGeneratedBy {
+ s = strings.TrimSpace(s)
+ if s == "" {
+ continue
+ }
+ skipGeneratedBy = append(skipGeneratedBy, s)
+ }
+
+ skipFilesGlobPatterns := make([]glob.Glob, 0, len(cfg.SkipFiles))
+ for _, s := range cfg.SkipFiles {
+ s = strings.TrimSpace(s)
+ if s == "" {
+ continue
+ }
+
+ compile, err := glob.Compile(s)
+ if err != nil {
+ return nil, fmt.Errorf("invalid glob pattern: %w", err)
+ }
+
+ skipFilesGlobPatterns = append(skipFilesGlobPatterns, compile)
+ }
+
nodeTypes := []ast.Node{
(*ast.AssignStmt)(nil),
+ (*ast.BinaryExpr)(nil),
(*ast.CallExpr)(nil),
(*ast.SelectorExpr)(nil),
+ (*ast.StarExpr)(nil),
(*ast.IncDecStmt)(nil),
(*ast.UnaryExpr)(nil),
}
- // Skip protoc-generated files.
+ // Skip filtered files.
var files []*ast.File
for _, f := range pass.Files {
- if !isProtocGeneratedFile(f) {
- files = append(files, f)
+ if skipGeneratedFile(f, skipGeneratedBy, cfg.SkipAnyGenerated) {
+ continue
+ }
- // ast.Print(pass.Fset, f)
+ if skipFilesByGlob(pass.Fset.File(f.Pos()).Name(), skipFilesGlobPatterns) {
+ continue
}
+
+ files = append(files, f)
+
+ // ast.Print(pass.Fset, f)
}
ins := inspector.New(files)
@@ -58,12 +128,12 @@ func Run(pass *analysis.Pass, mode Mode) []Issue {
filter := NewPosFilter()
ins.Preorder(nodeTypes, func(node ast.Node) {
- report := analyse(pass, filter, node)
+ report := analyse(pass, filter, node, cfg)
if report == nil {
return
}
- switch mode {
+ switch cfg.Mode {
case StandaloneMode:
pass.Report(report.ToDiagReport())
case GolangciLintMode:
@@ -71,10 +141,10 @@ func Run(pass *analysis.Pass, mode Mode) []Issue {
}
})
- return issues
+ return issues, nil
}
-func analyse(pass *analysis.Pass, filter *PosFilter, n ast.Node) *Report {
+func analyse(pass *analysis.Pass, filter *PosFilter, n ast.Node, cfg *Config) *Report {
// fmt.Printf("\n>>> check: %s\n", formatNode(n))
// ast.Print(pass.Fset, n)
if filter.IsFiltered(n.Pos()) {
@@ -82,7 +152,7 @@ func analyse(pass *analysis.Pass, filter *PosFilter, n ast.Node) *Report {
return nil
}
- result, err := Process(pass.TypesInfo, filter, n)
+ result, err := Process(pass.TypesInfo, filter, n, cfg)
if err != nil {
pass.Report(analysis.Diagnostic{
Pos: n.Pos(),
@@ -168,8 +238,34 @@ func (r *Report) ToIssue(fset *token.FileSet) Issue {
}
}
-func isProtocGeneratedFile(f *ast.File) bool {
- return len(f.Comments) > 0 && strings.HasPrefix(f.Comments[0].Text(), "Code generated by protoc-gen-go")
+func skipGeneratedFile(f *ast.File, prefixes []string, skipAny bool) bool {
+ if len(f.Comments) == 0 {
+ return false
+ }
+ firstComment := f.Comments[0].Text()
+
+ // https://golang.org/s/generatedcode
+ if skipAny && strings.HasPrefix(firstComment, "Code generated") {
+ return true
+ }
+
+ for _, prefix := range prefixes {
+ if strings.HasPrefix(firstComment, "Code generated by "+prefix) {
+ return true
+ }
+ }
+
+ return false
+}
+
+func skipFilesByGlob(filename string, patterns []glob.Glob) bool {
+ for _, pattern := range patterns {
+ if pattern.Match(filename) || pattern.Match(filepath.Base(filename)) {
+ return true
+ }
+ }
+
+ return false
}
func formatNode(node ast.Node) string {