diff options
| author | Taras Madan <tarasmadan@google.com> | 2025-01-22 16:07:17 +0100 |
|---|---|---|
| committer | Taras Madan <tarasmadan@google.com> | 2025-01-23 10:42:36 +0000 |
| commit | 7b4377ad9d8a7205416df8d6217ef2b010f89481 (patch) | |
| tree | e6fec4fd12ff807a16d847923f501075bf71d16c /vendor/github.com/ghostiam/protogetter/processor.go | |
| parent | 475a4c203afb8b7d3af51c4fd32bb170ff32a45e (diff) | |
vendor: delete
Diffstat (limited to 'vendor/github.com/ghostiam/protogetter/processor.go')
| -rw-r--r-- | vendor/github.com/ghostiam/protogetter/processor.go | 351 |
1 files changed, 0 insertions, 351 deletions
diff --git a/vendor/github.com/ghostiam/protogetter/processor.go b/vendor/github.com/ghostiam/protogetter/processor.go deleted file mode 100644 index 44f346e85..000000000 --- a/vendor/github.com/ghostiam/protogetter/processor.go +++ /dev/null @@ -1,351 +0,0 @@ -package protogetter - -import ( - "fmt" - "go/ast" - "go/token" - "go/types" - "reflect" - "strings" -) - -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, cfg *Config) (*Result, error) { - p := &processor{ - info: info, - filter: filter, - cfg: cfg, - } - - return p.process(n) -} - -func (c *processor) process(n ast.Node) (*Result, error) { - switch x := n.(type) { - case *ast.AssignStmt: - // Skip any assignment to the field. - 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: - // Skip any increment/decrement to the field. - c.filter.AddPos(x.X.Pos()) - - case *ast.UnaryExpr: - if x.Op == token.AND { - // Skip all expressions when the field is used as a pointer. - // Because this is not direct reading, but most likely writing by pointer (for example like sql.Scan). - c.filter.AddPos(x.X.Pos()) - } - - 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 - } - - if !isProtoMessage(c.info, f.X) { - return &Result{}, nil - } - - c.processInner(x) - - case *ast.SelectorExpr: - if !isProtoMessage(c.info, x.X) { - // If the selector is not on a proto message, skip it. - return &Result{}, nil - } - - 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)) - } - - if c.err != nil { - return nil, c.err - } - - return &Result{ - From: c.from.String(), - To: c.to.String(), - }, nil -} - -func (c *processor) processInner(expr ast.Expr) { - switch x := expr.(type) { - case *ast.Ident: - c.write(x.Name) - - case *ast.BasicLit: - c.write(x.Value) - - case *ast.UnaryExpr: - if x.Op == token.AND { - c.write(formatNode(x)) - return - } - - c.write(x.Op.String()) - c.processInner(x.X) - - case *ast.SelectorExpr: - c.processInner(x.X) - c.write(".") - - // If getter exists, use it. - if methodIsExists(c.info, x.X, "Get"+x.Sel.Name) { - c.writeFrom(x.Sel.Name) - c.writeTo("Get" + x.Sel.Name + "()") - return - } - - // If the selector is not a proto-message or the method has already been called, we leave it unchanged. - // This approach is significantly more efficient than verifying the presence of methods in all cases. - c.write(x.Sel.Name) - - case *ast.CallExpr: - c.processInner(x.Fun) - c.write("(") - for i, arg := range x.Args { - if i > 0 { - c.write(",") - } - c.processInner(arg) - } - c.write(")") - - case *ast.IndexExpr: - c.processInner(x.X) - c.write("[") - c.processInner(x.Index) - c.write("]") - - case *ast.BinaryExpr: - c.processInner(x.X) - c.write(x.Op.String()) - c.processInner(x.Y) - - case *ast.ParenExpr: - c.write("(") - c.processInner(x.X) - c.write(")") - - case *ast.StarExpr: - c.write("*") - c.processInner(x.X) - - case *ast.CompositeLit, *ast.TypeAssertExpr, *ast.ArrayType, *ast.FuncLit, *ast.SliceExpr: - // Process the node as is. - c.write(formatNode(x)) - - default: - c.err = fmt.Errorf("processInner: not implemented for type: %s", reflect.TypeOf(x)) - } -} - -func (c *processor) write(s string) { - c.writeTo(s) - c.writeFrom(s) -} - -func (c *processor) writeTo(s string) { - c.to.WriteString(s) -} - -func (c *processor) writeFrom(s string) { - c.from.WriteString(s) -} - -// Result contains source code (from) and suggested change (to) -type Result struct { - From string - To string -} - -func (r *Result) Skipped() bool { - // If from and to are the same, skip it. - return r.From == r.To -} - -func isProtoMessage(info *types.Info, expr ast.Expr) bool { - // First, we are checking for the presence of the ProtoReflect method which is currently being generated - // and corresponds to v2 version. - // https://pkg.go.dev/google.golang.org/protobuf@v1.31.0/proto#Message - const protoV2Method = "ProtoReflect" - ok := methodIsExists(info, expr, protoV2Method) - if ok { - return true - } - - // Afterwards, we are checking the ProtoMessage method. All the structures that implement the proto.Message interface - // have a ProtoMessage method and are proto-structures. This interface has been generated since version 1.0.0 and - // continues to exist for compatibility. - // https://pkg.go.dev/github.com/golang/protobuf/proto?utm_source=godoc#Message - const protoV1Method = "ProtoMessage" - ok = methodIsExists(info, expr, protoV1Method) - if ok { - // Since there is a protoc-gen-gogo generator that implements the proto.Message interface, but may not generate - // getters or generate from without checking for nil, so even if getters exist, we skip them. - const protocGenGoGoMethod = "MarshalToSizedBuffer" - return !methodIsExists(info, expr, protocGenGoGoMethod) - } - - return false -} - -func typesNamed(info *types.Info, x ast.Expr) (*types.Named, bool) { - if info == nil { - return nil, false - } - - t := info.TypeOf(x) - if t == nil { - return nil, false - } - - ptr, ok := t.Underlying().(*types.Pointer) - if ok { - t = ptr.Elem() - } - - 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 - } - - for i := 0; i < named.NumMethods(); i++ { - if named.Method(i).Name() == name { - return true - } - } - - 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 -} |
