diff --git a/locations/field_locations.go b/locations/field_locations.go index 73880d57e..e58cdc21e 100644 --- a/locations/field_locations.go +++ b/locations/field_locations.go @@ -18,8 +18,17 @@ import ( dpb "github.com/golang/protobuf/protoc-gen-go/descriptor" "github.com/jhump/protoreflect/desc" apb "google.golang.org/genproto/googleapis/api/annotations" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) +// FieldOption returns the precise location for the given extension defintion on +// the given field. This is useful for writing rules against custom extensions. +// +// Example: locations.FieldOption(field, fieldbehaviorpb.E_FieldBehavior) +func FieldOption(f *desc.FieldDescriptor, e *protoimpl.ExtensionInfo) *dpb.SourceCodeInfo_Location { + return pathLocation(f, 8, int(e.TypeDescriptor().Number())) // FieldDescriptor.options == 8 +} + // FieldResourceReference returns the precise location for a field's // resource reference annotation. func FieldResourceReference(f *desc.FieldDescriptor) *dpb.SourceCodeInfo_Location { diff --git a/locations/field_locations_test.go b/locations/field_locations_test.go index afb05cedb..5bb7c7b79 100644 --- a/locations/field_locations_test.go +++ b/locations/field_locations_test.go @@ -19,6 +19,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/jhump/protoreflect/desc" + apb "google.golang.org/genproto/googleapis/api/annotations" ) func TestFieldLocations(t *testing.T) { @@ -81,6 +82,22 @@ func TestFieldResourceReference(t *testing.T) { } `) loc := FieldResourceReference(f.GetMessageTypes()[0].GetFields()[0]) + // resource_reference annotation location is roughly line 4, column 19. + if diff := cmp.Diff(loc.GetSpan(), []int32{4, 19, 6, 3}); diff != "" { + t.Errorf(diff) + } +} + +func TestFieldOption(t *testing.T) { + f := parse(t, ` + import "google/api/resource.proto"; + message GetBookRequest { + string name = 1 [(google.api.resource_reference) = { + type: "library.googleapis.com/Book" + }]; + } + `) + loc := FieldOption(f.GetMessageTypes()[0].GetFields()[0], apb.E_ResourceReference) if diff := cmp.Diff(loc.GetSpan(), []int32{4, 19, 6, 3}); diff != "" { t.Errorf(diff) }