mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2025-01-13 06:49:08 +00:00
compiler/protogen: add Semantic.SET to setter annotations
Provide an API to add the GeneratedCodeInfo.Annotation.Semantic enum to annotations. Change-Id: I92ab30619a94a117679a0eb16d8cb5b3a1352586 Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/489795 Reviewed-by: Lasse Folger <lassefolger@google.com> Reviewed-by: Damien Neil <dneil@google.com>
This commit is contained in:
parent
05cbe34333
commit
cf06b0c33c
@ -9,9 +9,11 @@ import (
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"google.golang.org/protobuf/encoding/prototext"
|
||||
"google.golang.org/protobuf/internal/genid"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/testing/protocmp"
|
||||
|
||||
"google.golang.org/protobuf/types/descriptorpb"
|
||||
)
|
||||
@ -33,22 +35,48 @@ func TestAnnotations(t *testing.T) {
|
||||
wantInfo := &descriptorpb.GeneratedCodeInfo{}
|
||||
for _, want := range []struct {
|
||||
prefix, text, suffix string
|
||||
path []int32
|
||||
annotation *descriptorpb.GeneratedCodeInfo_Annotation
|
||||
}{{
|
||||
"type ", "AnnotationsTestEnum", " int32",
|
||||
[]int32{int32(genid.FileDescriptorProto_EnumType_field_number), 0},
|
||||
&descriptorpb.GeneratedCodeInfo_Annotation{
|
||||
Path: []int32{int32(genid.FileDescriptorProto_EnumType_field_number), 0},
|
||||
},
|
||||
}, {
|
||||
"\t", "AnnotationsTestEnum_ANNOTATIONS_TEST_ENUM_VALUE", " AnnotationsTestEnum = 0",
|
||||
[]int32{int32(genid.FileDescriptorProto_EnumType_field_number), 0, int32(genid.EnumDescriptorProto_Value_field_number), 0},
|
||||
&descriptorpb.GeneratedCodeInfo_Annotation{
|
||||
Path: []int32{int32(genid.FileDescriptorProto_EnumType_field_number), 0, int32(genid.EnumDescriptorProto_Value_field_number), 0},
|
||||
},
|
||||
}, {
|
||||
"type ", "AnnotationsTestMessage", " struct {",
|
||||
[]int32{int32(genid.FileDescriptorProto_MessageType_field_number), 0},
|
||||
&descriptorpb.GeneratedCodeInfo_Annotation{
|
||||
Path: []int32{int32(genid.FileDescriptorProto_MessageType_field_number), 0},
|
||||
},
|
||||
}, {
|
||||
"\t", "AnnotationsTestField", " ",
|
||||
[]int32{int32(genid.FileDescriptorProto_MessageType_field_number), 0, int32(genid.DescriptorProto_Field_field_number), 0},
|
||||
&descriptorpb.GeneratedCodeInfo_Annotation{
|
||||
Path: []int32{int32(genid.FileDescriptorProto_MessageType_field_number), 0, int32(genid.DescriptorProto_Field_field_number), 0},
|
||||
},
|
||||
}, {
|
||||
"\t", "XXX_weak_M", " ",
|
||||
&descriptorpb.GeneratedCodeInfo_Annotation{
|
||||
Path: []int32{int32(genid.FileDescriptorProto_MessageType_field_number), 0, int32(genid.DescriptorProto_Field_field_number), 1},
|
||||
},
|
||||
}, {
|
||||
"func (x *AnnotationsTestMessage) ", "GetAnnotationsTestField", "() string {",
|
||||
[]int32{int32(genid.FileDescriptorProto_MessageType_field_number), 0, int32(genid.DescriptorProto_Field_field_number), 0},
|
||||
&descriptorpb.GeneratedCodeInfo_Annotation{
|
||||
Path: []int32{int32(genid.FileDescriptorProto_MessageType_field_number), 0, int32(genid.DescriptorProto_Field_field_number), 0},
|
||||
},
|
||||
}, {
|
||||
"func (x *AnnotationsTestMessage) ", "GetM", "() proto.Message {",
|
||||
&descriptorpb.GeneratedCodeInfo_Annotation{
|
||||
Path: []int32{int32(genid.FileDescriptorProto_MessageType_field_number), 0, int32(genid.DescriptorProto_Field_field_number), 1},
|
||||
},
|
||||
}, {
|
||||
"func (x *AnnotationsTestMessage) ", "SetM", "(v proto.Message) {",
|
||||
&descriptorpb.GeneratedCodeInfo_Annotation{
|
||||
Path: []int32{int32(genid.FileDescriptorProto_MessageType_field_number), 0, int32(genid.DescriptorProto_Field_field_number), 1},
|
||||
Semantic: descriptorpb.GeneratedCodeInfo_Annotation_SET.Enum(),
|
||||
},
|
||||
}} {
|
||||
s := want.prefix + want.text + want.suffix
|
||||
pos := bytes.Index(sourceFile, []byte(s))
|
||||
@ -58,14 +86,15 @@ func TestAnnotations(t *testing.T) {
|
||||
}
|
||||
begin := pos + len(want.prefix)
|
||||
end := begin + len(want.text)
|
||||
wantInfo.Annotation = append(wantInfo.Annotation, &descriptorpb.GeneratedCodeInfo_Annotation{
|
||||
Path: want.path,
|
||||
a := &descriptorpb.GeneratedCodeInfo_Annotation{
|
||||
Begin: proto.Int32(int32(begin)),
|
||||
End: proto.Int32(int32(end)),
|
||||
SourceFile: proto.String("cmd/protoc-gen-go/testdata/annotations/annotations.proto"),
|
||||
})
|
||||
}
|
||||
proto.Merge(a, want.annotation)
|
||||
wantInfo.Annotation = append(wantInfo.Annotation, a)
|
||||
}
|
||||
if !proto.Equal(gotInfo, wantInfo) {
|
||||
t.Errorf("unexpected annotations for annotations.proto; got:\n%v\nwant:\n%v", gotInfo, wantInfo)
|
||||
if diff := cmp.Diff(wantInfo, gotInfo, protocmp.Transform()); diff != "" {
|
||||
t.Fatalf("unexpected annotations for annotations.proto (-want +got):\n%s", diff)
|
||||
}
|
||||
}
|
||||
|
@ -614,7 +614,10 @@ func genMessageSetterMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageI
|
||||
|
||||
genNoInterfacePragma(g, m.isTracked)
|
||||
|
||||
g.Annotate(m.GoIdent.GoName+".Set"+field.GoName, field.Location)
|
||||
g.AnnotateSymbol(m.GoIdent.GoName+".Set"+field.GoName, protogen.Annotation{
|
||||
Location: field.Location,
|
||||
Semantic: descriptorpb.GeneratedCodeInfo_Annotation_SET.Enum(),
|
||||
})
|
||||
leadingComments := appendDeprecationSuffix("",
|
||||
field.Desc.ParentFile(),
|
||||
field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated())
|
||||
|
@ -8,6 +8,7 @@
|
||||
package annotations
|
||||
|
||||
import (
|
||||
proto "google.golang.org/protobuf/proto"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
@ -70,9 +71,11 @@ func (AnnotationsTestEnum) EnumDescriptor() ([]byte, []int) {
|
||||
type AnnotationsTestMessage struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
weakFields protoimpl.WeakFields
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
AnnotationsTestField *string `protobuf:"bytes,1,opt,name=AnnotationsTestField" json:"AnnotationsTestField,omitempty"`
|
||||
AnnotationsTestField *string `protobuf:"bytes,1,opt,name=AnnotationsTestField" json:"AnnotationsTestField,omitempty"`
|
||||
XXX_weak_M struct{} `protobuf:"bytes,2,opt,name=m,weak=fmt.M" json:"m,omitempty"`
|
||||
}
|
||||
|
||||
func (x *AnnotationsTestMessage) Reset() {
|
||||
@ -114,6 +117,22 @@ func (x *AnnotationsTestMessage) GetAnnotationsTestField() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *AnnotationsTestMessage) GetM() proto.Message {
|
||||
var w protoimpl.WeakFields
|
||||
if x != nil {
|
||||
w = x.weakFields
|
||||
}
|
||||
return protoimpl.X.GetWeak(w, 2, "fmt.M")
|
||||
}
|
||||
|
||||
func (x *AnnotationsTestMessage) SetM(v proto.Message) {
|
||||
var w *protoimpl.WeakFields
|
||||
if x != nil {
|
||||
w = &x.weakFields
|
||||
}
|
||||
protoimpl.X.SetWeak(w, 2, "fmt.M", v)
|
||||
}
|
||||
|
||||
var File_cmd_protoc_gen_go_testdata_annotations_annotations_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_cmd_protoc_gen_go_testdata_annotations_annotations_proto_rawDesc = []byte{
|
||||
@ -122,20 +141,24 @@ var file_cmd_protoc_gen_go_testdata_annotations_annotations_proto_rawDesc = []by
|
||||
0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x1a, 0x67, 0x6f, 0x70, 0x72,
|
||||
0x6f, 0x74, 0x6f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2e, 0x61, 0x6e, 0x6e, 0x6f, 0x74,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x4c, 0x0a, 0x16, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x2e, 0x63, 0x6d, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x64, 0x61,
|
||||
0x74, 0x61, 0x2f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x2f, 0x66, 0x6d, 0x74, 0x2f, 0x6d,
|
||||
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x66, 0x0a, 0x16, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x73, 0x54, 0x65, 0x73, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65,
|
||||
0x12, 0x32, 0x0a, 0x14, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x54,
|
||||
0x65, 0x73, 0x74, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14,
|
||||
0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x54, 0x65, 0x73, 0x74, 0x46,
|
||||
0x69, 0x65, 0x6c, 0x64, 0x2a, 0x36, 0x0a, 0x13, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x73, 0x54, 0x65, 0x73, 0x74, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x1f, 0x0a, 0x1b, 0x41,
|
||||
0x4e, 0x4e, 0x4f, 0x54, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x5f,
|
||||
0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x10, 0x00, 0x42, 0x43, 0x5a, 0x41,
|
||||
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72,
|
||||
0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d, 0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x73,
|
||||
0x74, 0x64, 0x61, 0x74, 0x61, 0x2f, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x73,
|
||||
0x69, 0x65, 0x6c, 0x64, 0x12, 0x18, 0x0a, 0x01, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
|
||||
0x06, 0x2e, 0x66, 0x6d, 0x74, 0x2e, 0x4d, 0x42, 0x02, 0x50, 0x01, 0x52, 0x01, 0x6d, 0x2a, 0x36,
|
||||
0x0a, 0x13, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x54, 0x65, 0x73,
|
||||
0x74, 0x45, 0x6e, 0x75, 0x6d, 0x12, 0x1f, 0x0a, 0x1b, 0x41, 0x4e, 0x4e, 0x4f, 0x54, 0x41, 0x54,
|
||||
0x49, 0x4f, 0x4e, 0x53, 0x5f, 0x54, 0x45, 0x53, 0x54, 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x5f, 0x56,
|
||||
0x41, 0x4c, 0x55, 0x45, 0x10, 0x00, 0x42, 0x43, 0x5a, 0x41, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
|
||||
0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x62, 0x75, 0x66, 0x2f, 0x63, 0x6d, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x2d,
|
||||
0x67, 0x65, 0x6e, 0x2d, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x64, 0x61, 0x74, 0x61, 0x2f,
|
||||
0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x58, 0x00,
|
||||
}
|
||||
|
||||
var (
|
||||
@ -177,6 +200,8 @@ func file_cmd_protoc_gen_go_testdata_annotations_annotations_proto_init() {
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.weakFields
|
||||
case 3:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
|
@ -1 +1 @@
|
||||
annotation:{path:5 path:0 source_file:"cmd/protoc-gen-go/testdata/annotations/annotations.proto" begin:470 end:489} annotation:{path:5 path:0 path:2 path:0 source_file:"cmd/protoc-gen-go/testdata/annotations/annotations.proto" begin:506 end:553} annotation:{path:4 path:0 source_file:"cmd/protoc-gen-go/testdata/annotations/annotations.proto" begin:1912 end:1934} annotation:{path:4 path:0 path:2 path:0 source_file:"cmd/protoc-gen-go/testdata/annotations/annotations.proto" begin:2058 end:2078} annotation:{path:4 path:0 path:2 path:0 source_file:"cmd/protoc-gen-go/testdata/annotations/annotations.proto" begin:3225 end:3248}
|
||||
annotation:{path:5 path:0 source_file:"cmd/protoc-gen-go/testdata/annotations/annotations.proto" begin:512 end:531} annotation:{path:5 path:0 path:2 path:0 source_file:"cmd/protoc-gen-go/testdata/annotations/annotations.proto" begin:548 end:595} annotation:{path:4 path:0 source_file:"cmd/protoc-gen-go/testdata/annotations/annotations.proto" begin:1954 end:1976} annotation:{path:4 path:0 path:2 path:0 source_file:"cmd/protoc-gen-go/testdata/annotations/annotations.proto" begin:2136 end:2156} annotation:{path:4 path:0 path:2 path:1 source_file:"cmd/protoc-gen-go/testdata/annotations/annotations.proto" begin:2256 end:2266} annotation:{path:4 path:0 path:2 path:0 source_file:"cmd/protoc-gen-go/testdata/annotations/annotations.proto" begin:3397 end:3420} annotation:{path:4 path:0 path:2 path:1 source_file:"cmd/protoc-gen-go/testdata/annotations/annotations.proto" begin:3563 end:3567} annotation:{path:4 path:0 path:2 path:1 source_file:"cmd/protoc-gen-go/testdata/annotations/annotations.proto" begin:3730 end:3734 semantic:SET}
|
@ -6,10 +6,14 @@ syntax = "proto2";
|
||||
|
||||
package goproto.protoc.annotations;
|
||||
|
||||
import weak "cmd/protoc-gen-go/testdata/imports/fmt/m.proto";
|
||||
|
||||
option go_package = "google.golang.org/protobuf/cmd/protoc-gen-go/testdata/annotations";
|
||||
|
||||
message AnnotationsTestMessage {
|
||||
optional string AnnotationsTestField = 1;
|
||||
|
||||
optional fmt.M m = 2 [weak = true];
|
||||
}
|
||||
|
||||
enum AnnotationsTestEnum {
|
||||
|
@ -920,7 +920,7 @@ type GeneratedFile struct {
|
||||
packageNames map[GoImportPath]GoPackageName
|
||||
usedPackageNames map[GoPackageName]bool
|
||||
manualImports map[GoImportPath]bool
|
||||
annotations map[string][]Location
|
||||
annotations map[string][]Annotation
|
||||
}
|
||||
|
||||
// NewGeneratedFile creates a new generated file with the given filename
|
||||
@ -933,7 +933,7 @@ func (gen *Plugin) NewGeneratedFile(filename string, goImportPath GoImportPath)
|
||||
packageNames: make(map[GoImportPath]GoPackageName),
|
||||
usedPackageNames: make(map[GoPackageName]bool),
|
||||
manualImports: make(map[GoImportPath]bool),
|
||||
annotations: make(map[string][]Location),
|
||||
annotations: make(map[string][]Annotation),
|
||||
}
|
||||
|
||||
// All predeclared identifiers in Go are already used.
|
||||
@ -1012,8 +1012,32 @@ func (g *GeneratedFile) Unskip() {
|
||||
// The symbol may refer to a type, constant, variable, function, method, or
|
||||
// struct field. The "T.sel" syntax is used to identify the method or field
|
||||
// 'sel' on type 'T'.
|
||||
//
|
||||
// Deprecated: Use the AnnotateSymbol method instead.
|
||||
func (g *GeneratedFile) Annotate(symbol string, loc Location) {
|
||||
g.annotations[symbol] = append(g.annotations[symbol], loc)
|
||||
g.AnnotateSymbol(symbol, Annotation{Location: loc})
|
||||
}
|
||||
|
||||
// An Annotation provides semantic detail for a generated proto element.
|
||||
//
|
||||
// See the google.protobuf.GeneratedCodeInfo.Annotation documentation in
|
||||
// descriptor.proto for details.
|
||||
type Annotation struct {
|
||||
// Location is the source .proto file for the element.
|
||||
Location Location
|
||||
|
||||
// Semantic is the symbol's effect on the element in the original .proto file.
|
||||
Semantic *descriptorpb.GeneratedCodeInfo_Annotation_Semantic
|
||||
}
|
||||
|
||||
// AnnotateSymbol associates a symbol in a generated Go file with a location
|
||||
// in a source .proto file and a semantic type.
|
||||
//
|
||||
// The symbol may refer to a type, constant, variable, function, method, or
|
||||
// struct field. The "T.sel" syntax is used to identify the method or field
|
||||
// 'sel' on type 'T'.
|
||||
func (g *GeneratedFile) AnnotateSymbol(symbol string, info Annotation) {
|
||||
g.annotations[symbol] = append(g.annotations[symbol], info)
|
||||
}
|
||||
|
||||
// Content returns the contents of the generated file.
|
||||
@ -1106,25 +1130,24 @@ func (g *GeneratedFile) Content() ([]byte, error) {
|
||||
return out.Bytes(), nil
|
||||
}
|
||||
|
||||
// metaFile returns the contents of the file's metadata file, which is a
|
||||
// text formatted string of the google.protobuf.GeneratedCodeInfo.
|
||||
func (g *GeneratedFile) metaFile(content []byte) (string, error) {
|
||||
func (g *GeneratedFile) generatedCodeInfo(content []byte) (*descriptorpb.GeneratedCodeInfo, error) {
|
||||
fset := token.NewFileSet()
|
||||
astFile, err := parser.ParseFile(fset, "", content, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
info := &descriptorpb.GeneratedCodeInfo{}
|
||||
|
||||
seenAnnotations := make(map[string]bool)
|
||||
annotate := func(s string, ident *ast.Ident) {
|
||||
seenAnnotations[s] = true
|
||||
for _, loc := range g.annotations[s] {
|
||||
for _, a := range g.annotations[s] {
|
||||
info.Annotation = append(info.Annotation, &descriptorpb.GeneratedCodeInfo_Annotation{
|
||||
SourceFile: proto.String(loc.SourceFile),
|
||||
Path: loc.Path,
|
||||
SourceFile: proto.String(a.Location.SourceFile),
|
||||
Path: a.Location.Path,
|
||||
Begin: proto.Int32(int32(fset.Position(ident.Pos()).Offset)),
|
||||
End: proto.Int32(int32(fset.Position(ident.End()).Offset)),
|
||||
Semantic: a.Semantic,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -1171,10 +1194,21 @@ func (g *GeneratedFile) metaFile(content []byte) (string, error) {
|
||||
}
|
||||
for a := range g.annotations {
|
||||
if !seenAnnotations[a] {
|
||||
return "", fmt.Errorf("%v: no symbol matching annotation %q", g.filename, a)
|
||||
return nil, fmt.Errorf("%v: no symbol matching annotation %q", g.filename, a)
|
||||
}
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// metaFile returns the contents of the file's metadata file, which is a
|
||||
// text formatted string of the google.protobuf.GeneratedCodeInfo.
|
||||
func (g *GeneratedFile) metaFile(content []byte) (string, error) {
|
||||
info, err := g.generatedCodeInfo(content)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
b, err := prototext.Marshal(info)
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
@ -11,8 +11,10 @@ import (
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
|
||||
"google.golang.org/protobuf/internal/genid"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/reflect/protoreflect"
|
||||
"google.golang.org/protobuf/testing/protocmp"
|
||||
|
||||
"google.golang.org/protobuf/types/descriptorpb"
|
||||
"google.golang.org/protobuf/types/pluginpb"
|
||||
@ -344,3 +346,73 @@ var _ = bar.X
|
||||
t.Fatalf("content mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAnnotations(t *testing.T) {
|
||||
gen, err := Options{}.New(&pluginpb.CodeGeneratorRequest{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
loc := Location{SourceFile: "foo.go"}
|
||||
g := gen.NewGeneratedFile("foo.go", "golang.org/x/foo")
|
||||
|
||||
g.P("package foo")
|
||||
g.P()
|
||||
|
||||
structName := "S"
|
||||
fieldName := "Field"
|
||||
|
||||
messageLoc := loc.appendPath(genid.FileDescriptorProto_MessageType_field_number, 1)
|
||||
fieldLoc := messageLoc.appendPath(genid.DescriptorProto_Field_field_number, 1)
|
||||
|
||||
g.Annotate(structName, messageLoc) // use deprecated version to test existing usages
|
||||
g.P("type ", structName, " struct {")
|
||||
g.AnnotateSymbol(structName+"."+fieldName, Annotation{Location: fieldLoc})
|
||||
g.P(fieldName, " string")
|
||||
g.P("}")
|
||||
g.P()
|
||||
|
||||
g.AnnotateSymbol(fmt.Sprintf("%s.Set%s", structName, fieldName), Annotation{
|
||||
Location: fieldLoc,
|
||||
Semantic: descriptorpb.GeneratedCodeInfo_Annotation_SET.Enum(),
|
||||
})
|
||||
g.P("func (m *", structName, ") Set", fieldName, "(x string) {")
|
||||
g.P("m.", fieldName, " = x")
|
||||
g.P("}")
|
||||
g.P()
|
||||
|
||||
want := &descriptorpb.GeneratedCodeInfo{
|
||||
Annotation: []*descriptorpb.GeneratedCodeInfo_Annotation{
|
||||
{ // S
|
||||
SourceFile: proto.String("foo.go"),
|
||||
Path: []int32{4, 1}, // message S
|
||||
Begin: proto.Int32(18),
|
||||
End: proto.Int32(19),
|
||||
},
|
||||
{ // S.F
|
||||
SourceFile: proto.String("foo.go"),
|
||||
Path: []int32{4, 1, 2, 1},
|
||||
Begin: proto.Int32(30),
|
||||
End: proto.Int32(35),
|
||||
},
|
||||
{ // SetF
|
||||
SourceFile: proto.String("foo.go"),
|
||||
Path: []int32{4, 1, 2, 1},
|
||||
Begin: proto.Int32(58),
|
||||
End: proto.Int32(66),
|
||||
Semantic: descriptorpb.GeneratedCodeInfo_Annotation_SET.Enum(),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
content, err := g.Content()
|
||||
if err != nil {
|
||||
t.Fatalf("g.Content() = %v", err)
|
||||
}
|
||||
got, err := g.generatedCodeInfo(content)
|
||||
if err != nil {
|
||||
t.Fatalf("g.generatedCodeInfo(...) = %v", err)
|
||||
}
|
||||
if diff := cmp.Diff(want, got, protocmp.Transform()); diff != "" {
|
||||
t.Fatalf("GeneratedCodeInfo mismatch (-want +got):\n%s", diff)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user