Repository: googleapis/api-linter
Pull request #417 (2019-12-05 23:21:02)

[feat] Add location methods for resource annotations.


Patch:
diff --git a/locations/field_locations.go b/locations/field_locations.go
index f6e4a16..d35ee95 100644
--- a/locations/field_locations.go
+++ b/locations/field_locations.go
@@ -17,8 +17,15 @@ package locations
 import (
 	dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
 	"github.com/jhump/protoreflect/desc"
+	apb "google.golang.org/genproto/googleapis/api/annotations"
 )
 
+// FieldResourceReference returns the precise location for a field's
+// resource reference annotation.
+func FieldResourceReference(f *desc.FieldDescriptor) *dpb.SourceCodeInfo_Location {
+	return pathLocation(f, 8, int(apb.E_ResourceReference.Field)) // FieldDescriptor.options == 8
+}
+
 // FieldType returns the precise location for a field's type.
 func FieldType(f *desc.FieldDescriptor) *dpb.SourceCodeInfo_Location {
 	if f.GetMessageType() != nil || f.GetEnumType() != nil {
diff --git a/locations/message_locations.go b/locations/message_locations.go
new file mode 100644
index 0000000..ce8851c
--- /dev/null
+++ b/locations/message_locations.go
@@ -0,0 +1,27 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 		https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package locations
+
+import (
+	dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
+	"github.com/jhump/protoreflect/desc"
+	apb "google.golang.org/genproto/googleapis/api/annotations"
+)
+
+// MessageResource returns the precise location of the `google.api.resource`
+// annotation.
+func MessageResource(m *desc.MessageDescriptor) *dpb.SourceCodeInfo_Location {
+	return pathLocation(m, 7, int(apb.E_Resource.Field)) // MessageDescriptor.options == 7
+}


Test patch:
diff --git a/locations/field_locations_test.go b/locations/field_locations_test.go
index 6be5c4c..549619d 100644
--- a/locations/field_locations_test.go
+++ b/locations/field_locations_test.go
@@ -46,3 +46,18 @@ func TestFieldLocations(t *testing.T) {
 		})
 	}
 }
+
+func TestFieldResourceReference(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 := FieldResourceReference(f.GetMessageTypes()[0].GetFields()[0])
+	if diff := cmp.Diff(loc.GetSpan(), []int32{4, 19, 6, 3}); diff != "" {
+		t.Errorf(diff)
+	}
+}
diff --git a/locations/message_locations_test.go b/locations/message_locations_test.go
new file mode 100644
index 0000000..a23e30c
--- /dev/null
+++ b/locations/message_locations_test.go
@@ -0,0 +1,37 @@
+// Copyright 2019 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// 		https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package locations
+
+import (
+	"testing"
+
+	"github.com/google/go-cmp/cmp"
+)
+
+func TestMessageResource(t *testing.T) {
+	f := parse(t, `
+		import "google/api/resource.proto";
+		message Book {
+		  option (google.api.resource) = {
+		    type: "library.googleapis.com/Book"
+		    pattern: "publishers/{publisher}/books/{book}"
+		  };
+		}
+	`)
+	loc := MessageResource(f.GetMessageTypes()[0])
+	if diff := cmp.Diff(loc.GetSpan(), []int32{4, 2, 7, 4}); diff != "" {
+		t.Errorf(diff)
+	}
+}