Skip to content

Commit 2eaad84

Browse files
authored
chore(internal/protoveneer): support additional fields (#10296)
Allow fields in the veneer type that do not correspond to fields in the proto type.
1 parent c15d69a commit 2eaad84

4 files changed

Lines changed: 48 additions & 7 deletions

File tree

internal/protoveneer/cmd/protoveneer/config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ type fieldConfig struct {
7171
Type string // veneer type
7272
// Omit from output.
7373
Omit bool
74+
// This field is not part of the proto; add it.
75+
Add bool
7476
// Generate the type, but not conversions.
7577
// The populate functions (see [typeConfg.PopulateToFrom]) should set the field.
7678
NoConvert bool `yaml:"noConvert"`

internal/protoveneer/cmd/protoveneer/protoveneer.go

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ func generate(conf *config, pkg *ast.Package, fset *token.FileSet) (src []byte,
220220
// Use the converters map to give every field a converter.
221221
for _, ti := range toWrite {
222222
for _, f := range ti.fields {
223-
if f.converter != nil {
223+
if f.converter != nil || f.noConvert {
224224
continue
225225
}
226226
f.converter, err = makeConverter(f.af.Type, f.protoType, converters)
@@ -422,7 +422,7 @@ func processType(ti *typeInfo, tconf *typeConfig, typeInfos map[string]*typeInfo
422422
ti.spec.Name.Name = ti.veneerName
423423
switch t := ti.spec.Type.(type) {
424424
case *ast.StructType:
425-
// Check that all configured fields are present.
425+
// Check that all configured fields are present, and added fields are not.
426426
exportedFields := map[string]bool{}
427427
for _, f := range t.Fields.List {
428428
if len(f.Names) > 1 {
@@ -433,13 +433,16 @@ func processType(ti *typeInfo, tconf *typeConfig, typeInfos map[string]*typeInfo
433433
}
434434
}
435435
if tconf != nil {
436-
for name := range tconf.Fields {
437-
if !exportedFields[name] {
436+
for name, fconfig := range tconf.Fields {
437+
if !exportedFields[name] && !fconfig.Add {
438438
return fmt.Errorf("%s: configured field %s is not present", ti.protoName, name)
439439
}
440+
if exportedFields[name] && fconfig.Add {
441+
return fmt.Errorf("%s: added field %s is already present", ti.protoName, name)
442+
}
440443
}
441444
}
442-
// Process the fields.
445+
// Process the existing fields.
443446
fs := t.Fields.List
444447
t.Fields.List = t.Fields.List[:0]
445448
for _, f := range fs {
@@ -452,6 +455,16 @@ func processType(ti *typeInfo, tconf *typeConfig, typeInfos map[string]*typeInfo
452455
ti.fields = append(ti.fields, fi)
453456
}
454457
}
458+
// Add additional fields.
459+
if tconf != nil {
460+
for name, fconfig := range tconf.Fields {
461+
if fconfig.Add {
462+
if err := addField(name, fconfig, t, ti); err != nil {
463+
return err
464+
}
465+
}
466+
}
467+
}
455468
// Other processing.
456469
if tconf != nil && tconf.PopulateToFrom != "" {
457470
toFunc, fromFunc := parseCommaPair(tconf.PopulateToFrom)
@@ -552,6 +565,25 @@ func veneerType(protoType ast.Expr, typeInfos map[string]*typeInfo) ast.Expr {
552565
return wtype(protoType)
553566
}
554567

568+
func addField(name string, fconfig fieldConfig, t *ast.StructType, ti *typeInfo) error {
569+
expr, err := parser.ParseExpr(fconfig.Type)
570+
if err != nil {
571+
return err
572+
}
573+
af := &ast.Field{
574+
Names: []*ast.Ident{{Name: name}},
575+
Type: expr,
576+
}
577+
t.Fields.List = append(t.Fields.List, af)
578+
ti.fields = append(ti.fields, &fieldInfo{
579+
af: af,
580+
protoName: "",
581+
veneerName: name,
582+
noConvert: true,
583+
})
584+
return nil
585+
}
586+
555587
// processEnumValues processes enum values.
556588
// The proto compiler puts all the values for an enum in one GenDecl,
557589
// and there are no other values in that GenDecl.

internal/protoveneer/cmd/protoveneer/testdata/basic/config.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,9 @@ types:
5252
Y:
5353
noConvert: true
5454
populateToFrom: popYTo, popYFrom
55+
56+
File:
57+
fields:
58+
hidden:
59+
add: true
60+
type: '*Client'

internal/protoveneer/cmd/protoveneer/testdata/basic/golden

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,9 @@ func (CitationMetadata) fromProto(p *pb.CitationMetadata) *CitationMetadata {
106106
}
107107

108108
type File struct {
109-
Error *apierror.APIError
110-
Dur time.Duration
109+
Error *apierror.APIError
110+
Dur time.Duration
111+
hidden *Client
111112
}
112113

113114
func (v *File) toProto() *pb.File {

0 commit comments

Comments
 (0)