From 3c2de633d4eaf5937ca4b95124642e6853e65f1f Mon Sep 17 00:00:00 2001 From: Uwe Krueger Date: Mon, 20 Apr 2020 13:10:08 +0200 Subject: [PATCH] go-to-protobuf: fix rewrite of embedded struct fields The protobuf generator cannot handle embedded struct fields correctly. When using an embedded field by pointer it produces the error message `unable to get name for tag from struct "...", field ...` The reason is that the name determination evaluating the AST does not handle pointers if the AST does not already contain a field name. This seems to be the case for structs embedded by pointers. Example: ``` type MyStruct struct { *OtherStruct `protobuf:"bytes,1,opt,name=otherStruct"` } ``` --- .../cmd/go-to-protobuf/protobuf/parser.go | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/staging/src/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/parser.go b/staging/src/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/parser.go index 3115bc688dd..b3c8d2e8728 100644 --- a/staging/src/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/parser.go +++ b/staging/src/k8s.io/code-generator/cmd/go-to-protobuf/protobuf/parser.go @@ -375,6 +375,21 @@ func RewriteTypesWithProtobufStructTags(name string, structTags map[string]map[s }) } +func getFieldName(expr ast.Expr, structname string) (name string, err error) { + for { + switch t := expr.(type) { + case *ast.Ident: + return t.Name, nil + case *ast.SelectorExpr: + return t.Sel.Name, nil + case *ast.StarExpr: + expr = t.X + default: + return "", fmt.Errorf("unable to get name for tag from struct %q, field %#v", structname, t) + } + } +} + func updateStructTags(decl ast.Decl, structTags map[string]map[string]string, toCopy []string) []error { var errs []error t, ok := decl.(*ast.GenDecl) @@ -403,14 +418,11 @@ func updateStructTags(decl ast.Decl, structTags map[string]map[string]string, to for i := range st.Fields.List { f := st.Fields.List[i] var name string + var err error if len(f.Names) == 0 { - switch t := f.Type.(type) { - case *ast.Ident: - name = t.Name - case *ast.SelectorExpr: - name = t.Sel.Name - default: - errs = append(errs, fmt.Errorf("unable to get name for tag from struct %q, field %#v", spec.Name.Name, t)) + name, err = getFieldName(f.Type, spec.Name.Name) + if err != nil { + errs = append(errs, err) continue } } else {