diff --git a/rules/aip0132/response_unknown_fields.go b/rules/aip0132/response_unknown_fields.go index 51fd1ba05..d617f739d 100644 --- a/rules/aip0132/response_unknown_fields.go +++ b/rules/aip0132/response_unknown_fields.go @@ -15,8 +15,11 @@ package aip0132 import ( + "strings" + "bitbucket.org/creachadair/stringset" "github.com/googleapis/api-linter/lint" + "github.com/googleapis/api-linter/rules/internal/utils" "github.com/jhump/protoreflect/desc" "github.com/stoewer/go-strcase" ) @@ -37,7 +40,15 @@ var responseUnknownFields = &lint.FieldRule{ }, LintField: func(f *desc.FieldDescriptor) []lint.Problem { // A repeated variant of the resource should be permitted. - resource := strcase.SnakeCase(listRespMessageRegexp.FindStringSubmatch(f.GetOwner().GetName())[1]) + msgName := f.GetOwner().GetName() + resource := strcase.SnakeCase(listRespMessageRegexp.FindStringSubmatch(msgName)[1]) + if strings.HasSuffix(resource, "_revisions") { + // This is an AIP-162 ListFooRevisions response, which is subtly + // different from an AIP-132 List response. We need to modify the RPC + // name to what the AIP-132 List response would be in order to permit + // the resource field properly. + resource = utils.ToPlural(strings.TrimSuffix(resource, "_revisions")) + } if f.GetName() == resource { return nil } diff --git a/rules/aip0132/response_unknown_fields_test.go b/rules/aip0132/response_unknown_fields_test.go index 6c00da973..6ec76f75d 100644 --- a/rules/aip0132/response_unknown_fields_test.go +++ b/rules/aip0132/response_unknown_fields_test.go @@ -23,17 +23,19 @@ import ( func TestResponseUnknownFields(t *testing.T) { for _, test := range []struct { - FieldName string - problems testutils.Problems + MessageName string + FieldName string + problems testutils.Problems }{ - {"total_size", testutils.Problems{}}, - {"unreachable", testutils.Problems{}}, - {"unreachable_locations", testutils.Problems{}}, - {"extra", testutils.Problems{{Message: "List responses"}}}, + {"ListBooksResponse", "total_size", nil}, + {"ListBooksResponse", "unreachable", nil}, + {"ListBooksResponse", "unreachable_locations", nil}, + {"ListBookRevisionsResponse", "total_size", nil}, + {"ListBooksResponse", "extra", testutils.Problems{{Message: "List responses"}}}, } { t.Run(strcase.UpperCamelCase(test.FieldName), func(t *testing.T) { f := testutils.ParseProto3Tmpl(t, ` - message ListBooksResponse { + message {{.MessageName}} { repeated Book books = 1; string next_page_token = 2; string {{.FieldName}} = 3;