Repository: googleapis/api-linter
Pull request #430 (2019-12-06 18:59:42)

[AIP-151] Make the LRO rules use a more precise location.


Patch:
diff --git a/locations/method_locations.go b/locations/method_locations.go
index e325e76..b5f7bba 100644
--- a/locations/method_locations.go
+++ b/locations/method_locations.go
@@ -18,6 +18,7 @@ import (
 	dpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
 	"github.com/jhump/protoreflect/desc"
 	apb "google.golang.org/genproto/googleapis/api/annotations"
+	lrpb "google.golang.org/genproto/googleapis/longrunning"
 )
 
 // MethodRequestType returns the precise location of the method's input type.
@@ -36,6 +37,12 @@ func MethodHTTPRule(m *desc.MethodDescriptor) *dpb.SourceCodeInfo_Location {
 	return pathLocation(m, 4, int(apb.E_Http.Field)) // MethodDescriptor.options == 4
 }
 
+// MethodOperationInfo returns the precise location of the method's
+// `google.longrunning.operation_info` annotation, if any.
+func MethodOperationInfo(m *desc.MethodDescriptor) *dpb.SourceCodeInfo_Location {
+	return pathLocation(m, 4, int(lrpb.E_OperationInfo.Field)) // MethodDescriptor.options == 4
+}
+
 // MethodSignature returns the precise location of the method's
 // `google.api.method_signature` annotation, if any.
 func MethodSignature(m *desc.MethodDescriptor, index int) *dpb.SourceCodeInfo_Location {
diff --git a/rules/aip0151/lro_metadata_type.go b/rules/aip0151/lro_metadata_type.go
index 5996c40..26559b1 100644
--- a/rules/aip0151/lro_metadata_type.go
+++ b/rules/aip0151/lro_metadata_type.go
@@ -16,6 +16,7 @@ package aip0151
 
 import (
 	"github.com/googleapis/api-linter/lint"
+	"github.com/googleapis/api-linter/locations"
 	"github.com/googleapis/api-linter/rules/internal/utils"
 	"github.com/jhump/protoreflect/desc"
 )
@@ -31,6 +32,7 @@ var lroMetadata = &lint.MethodRule{
 			return []lint.Problem{{
 				Message:    "Methods returning an LRO must set the metadata type.",
 				Descriptor: m,
+				Location:   locations.MethodOperationInfo(m),
 			}}
 		}
 
@@ -39,6 +41,7 @@ var lroMetadata = &lint.MethodRule{
 			return []lint.Problem{{
 				Message:    "Methods returning an LRO should create a blank message rather than using Empty.",
 				Descriptor: m,
+				Location:   locations.MethodOperationInfo(m),
 			}}
 		}
 
diff --git a/rules/aip0151/lro_response_type.go b/rules/aip0151/lro_response_type.go
index 87655fe..bdcc18c 100644
--- a/rules/aip0151/lro_response_type.go
+++ b/rules/aip0151/lro_response_type.go
@@ -17,6 +17,8 @@ package aip0151
 import (
 	"strings"
 
+	"github.com/googleapis/api-linter/locations"
+
 	"github.com/googleapis/api-linter/lint"
 	"github.com/googleapis/api-linter/rules/internal/utils"
 	"github.com/jhump/protoreflect/desc"
@@ -33,6 +35,7 @@ var lroResponse = &lint.MethodRule{
 			return []lint.Problem{{
 				Message:    "Methods returning an LRO must set the response type.",
 				Descriptor: m,
+				Location:   locations.MethodOperationInfo(m),
 			}}
 		}
 
@@ -44,6 +47,7 @@ var lroResponse = &lint.MethodRule{
 			return []lint.Problem{{
 				Message:    "Methods returning an LRO should create a blank message rather than using Empty.",
 				Descriptor: m,
+				Location:   locations.MethodOperationInfo(m),
 			}}
 		}
 
diff --git a/rules/aip0151/lro_types_defined_in_file.go b/rules/aip0151/lro_types_defined_in_file.go
index 9ee7536..9739e33 100644
--- a/rules/aip0151/lro_types_defined_in_file.go
+++ b/rules/aip0151/lro_types_defined_in_file.go
@@ -19,6 +19,7 @@ import (
 	"strings"
 
 	"github.com/googleapis/api-linter/lint"
+	"github.com/googleapis/api-linter/locations"
 	"github.com/googleapis/api-linter/rules/internal/utils"
 	"github.com/jhump/protoreflect/desc"
 )
@@ -46,6 +47,7 @@ var lroDefinedInFile = &lint.MethodRule{
 						k,
 					),
 					Descriptor: m,
+					Location:   locations.MethodOperationInfo(m),
 				})
 			}
 		}


Test patch:
diff --git a/locations/method_locations_test.go b/locations/method_locations_test.go
index f1b61f5..48b40e5 100644
--- a/locations/method_locations_test.go
+++ b/locations/method_locations_test.go
@@ -70,6 +70,26 @@ func TestMethodHTTPRule(t *testing.T) {
 	}
 }
 
+func TestMethodOperationInfo(t *testing.T) {
+	f := parse(t, `
+		import "google/longrunning/operations.proto";
+		service Library {
+		  rpc WriteBook(WriteBookRequest) returns (google.longrunning.Operation) {
+		    option (google.longrunning.operation_info) = {
+					response_type: "WriteBookResponse"
+		      metadata_type: "WriteBookMetadata"
+		    };
+		  }
+		}
+		message WriteBookRequest {}
+	`)
+	loc := MethodOperationInfo(f.GetServices()[0].GetMethods()[0])
+	// Four character span: start line, start column, end line, end column.
+	if diff := cmp.Diff(loc.GetSpan(), []int32{5, 4, 8, 6}); diff != "" {
+		t.Errorf(diff)
+	}
+}
+
 func TestMethodSignature(t *testing.T) {
 	f := parse(t, `
 		import "google/api/client.proto";