diff --git a/rules/aip0136/response_message_name.go b/rules/aip0136/response_message_name.go index ab10dcc30..d9c3f54e3 100644 --- a/rules/aip0136/response_message_name.go +++ b/rules/aip0136/response_message_name.go @@ -53,8 +53,17 @@ var responseMessageName = &lint.MethodRule{ // just exit. return nil } + res := utils.GetResource(response) + responseResourceType := res.GetType() requestResourceType := utils.GetResourceReference(m.GetInputType().FindFieldByName("name")).GetType() - responseResourceType := utils.GetResource(response).GetType() + + // Check to see if the custom method uses the resource type name as the target + // field name and use that instead if `name` is not present as well. + // AIP-144 methods recommend this naming style. + resourceFieldType := utils.GetResourceReference(m.GetInputType().FindFieldByName(utils.GetResourceSingular(res))).GetType() + if requestResourceType == "" && resourceFieldType != "" { + requestResourceType = resourceFieldType + } // Short-circuit: Output type is the resource being operated on if utils.IsResource(response) && responseResourceType == requestResourceType { diff --git a/rules/aip0136/response_message_name_test.go b/rules/aip0136/response_message_name_test.go index d7f04bd5f..0c9478dc7 100644 --- a/rules/aip0136/response_message_name_test.go +++ b/rules/aip0136/response_message_name_test.go @@ -102,13 +102,15 @@ func TestResponseMessageName(t *testing.T) { testName string MethodName string RespMessageName string + ReqFieldName string LRO bool problems testutils.Problems }{ - {"Valid", "ArchiveBook", "Book", false, testutils.Problems{}}, - {"Valid LRO", "ArchiveBook", "Book", true, testutils.Problems{}}, - {"Invalid", "ArchiveBook", "Author", false, testutils.Problems{{Message: "not \"Author\"."}}}, - {"Invalid LRO", "ArchiveBook", "Author", true, testutils.Problems{{Message: "not \"Author\"."}}}, + {"Valid", "ArchiveBook", "Book", "name", false, testutils.Problems{}}, + {"ValidResourceField", "ArchiveBook", "Book", "book", false, testutils.Problems{}}, + {"Valid LRO", "ArchiveBook", "Book", "name", true, testutils.Problems{}}, + {"Invalid", "ArchiveBook", "Author", "name", false, testutils.Problems{{Message: "not \"Author\"."}}}, + {"Invalid LRO", "ArchiveBook", "Author", "name", true, testutils.Problems{{Message: "not \"Author\"."}}}, } for _, test := range tests { @@ -123,7 +125,7 @@ func TestResponseMessageName(t *testing.T) { service Library { rpc {{.MethodName}}({{.MethodName}}Request) returns ({{ if .LRO }}google.longrunning.Operation{{ else }}{{.RespMessageName}}{{ end }}) { option (google.api.http) = { - post: "/v1/{name=publishers/*/books/*}:foo" + post: "/v1/{ {{.ReqFieldName}}=publishers/*/books/*}:foo" body: "*" }; {{ if .LRO }} @@ -139,6 +141,8 @@ func TestResponseMessageName(t *testing.T) { option (google.api.resource) = { type: "library.googleapis.com/Book" pattern: "publishers/{publisher}/books/{book}" + singular: "book" + plural: "books" }; } @@ -152,7 +156,7 @@ func TestResponseMessageName(t *testing.T) { message {{.MethodName}}Request { // The book to operate on. // Format: publishers/{publisher}/books/{book} - string name = 1 [(google.api.resource_reference).type = "library.googleapis.com/Book"]; + string {{.ReqFieldName}} = 1 [(google.api.resource_reference).type = "library.googleapis.com/Book"]; } `, test) method := file.GetServices()[0].GetMethods()[0]