github.com/googleapis/api-linter@v1.65.2/rules/aip0235/request_names_field.go (about) 1 // Copyright 2020 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package aip0235 16 17 import ( 18 "fmt" 19 20 "github.com/gertd/go-pluralize" 21 "github.com/googleapis/api-linter/lint" 22 "github.com/googleapis/api-linter/locations" 23 "github.com/jhump/protoreflect/desc" 24 "github.com/jhump/protoreflect/desc/builder" 25 ) 26 27 // The Batch Delete standard method should have repeated name field or repeated 28 // standard delete request message field, but the latter one is not suggested. 29 var requestNamesField = &lint.MessageRule{ 30 Name: lint.NewRuleName(235, "request-names-field"), 31 OnlyIf: isBatchDeleteRequestMessage, 32 LintMessage: func(m *desc.MessageDescriptor) (problems []lint.Problem) { 33 // Rule check: Establish that a name field is present. 34 names := m.FindFieldByName("names") 35 deleteReqMsg := m.FindFieldByName("requests") 36 37 // Rule check: Ensure that the names field is present. 38 if names == nil && deleteReqMsg == nil { 39 problems = append(problems, lint.Problem{ 40 Message: fmt.Sprintf(`Message %q has no "names" field`, m.GetName()), 41 Descriptor: m, 42 }) 43 } 44 45 // Rule check: Ensure that only the suggested names field is present. 46 if names != nil && deleteReqMsg != nil { 47 problems = append(problems, lint.Problem{ 48 Message: fmt.Sprintf(`Message %q should delete "requests" field, only keep the "names" field`, m.GetName()), 49 Descriptor: deleteReqMsg, 50 }) 51 } 52 53 // Rule check: Ensure that the names field is repeated. 54 if names != nil && !names.IsRepeated() { 55 problems = append(problems, lint.Problem{ 56 Message: `The "names" field should be repeated`, 57 Suggestion: "repeated string", 58 Descriptor: names, 59 Location: locations.FieldType(names), 60 }) 61 } 62 63 // Rule check: Ensure that the names field is the correct type. 64 if names != nil && names.GetType() != builder.FieldTypeString().GetType() { 65 problems = append(problems, lint.Problem{ 66 Message: `"names" field on Batch Delete Request should be a "string" type`, 67 Suggestion: "string", 68 Descriptor: names, 69 Location: locations.FieldType(names), 70 }) 71 } 72 73 // Rule check: Ensure that the standard delete request message field is repeated. 74 if deleteReqMsg != nil && !deleteReqMsg.IsRepeated() { 75 problems = append(problems, lint.Problem{ 76 Message: `The "requests" field should be repeated`, 77 Descriptor: deleteReqMsg, 78 }) 79 } 80 81 // Rule check: Ensure that the standard delete request message field is the 82 // correct type. Note: Use m.GetName()[11:len(m.GetName())-7]) to retrieve 83 // the resource name from the batch delete request, for example: 84 // "BatchDeleteBooksRequest" -> "Books" 85 rightTypeName := fmt.Sprintf("Delete%sRequest", pluralize.NewClient().Singular(m.GetName()[11:len(m.GetName())-7])) 86 if deleteReqMsg != nil && (deleteReqMsg.GetMessageType() == nil || deleteReqMsg.GetMessageType().GetName() != rightTypeName) { 87 problems = append(problems, lint.Problem{ 88 Message: fmt.Sprintf(`The "requests" field on Batch Delete Request should be a %q type`, rightTypeName), 89 Descriptor: deleteReqMsg, 90 Location: locations.FieldType(deleteReqMsg), 91 }) 92 } 93 return 94 }, 95 }