github.com/googleapis/api-linter@v1.65.2/rules/aip0132/resource_reference_type.go (about) 1 // Copyright 2022 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 aip0132 16 17 import ( 18 "github.com/googleapis/api-linter/lint" 19 "github.com/googleapis/api-linter/locations" 20 "github.com/googleapis/api-linter/rules/internal/utils" 21 "github.com/jhump/protoreflect/desc" 22 "google.golang.org/genproto/googleapis/api/annotations" 23 ) 24 25 // List methods should reference the target resource via `child_type` or the 26 // parent directly via `type`. 27 var resourceReferenceType = &lint.MethodRule{ 28 Name: lint.NewRuleName(132, "resource-reference-type"), 29 OnlyIf: func(m *desc.MethodDescriptor) bool { 30 p := m.GetInputType().FindFieldByName("parent") 31 32 var resource *annotations.ResourceDescriptor 33 resourceField := utils.GetListResourceMessage(m) 34 if resourceField != nil { 35 resource = utils.GetResource(resourceField) 36 } 37 return utils.IsListMethod(m) && p != nil && utils.GetResourceReference(p) != nil && resource != nil 38 }, 39 LintMethod: func(m *desc.MethodDescriptor) []lint.Problem { 40 // The first repeated message field must be the paginated resource. 41 repeated := utils.GetRepeatedMessageFields(m.GetOutputType()) 42 resource := utils.GetResource(repeated[0].GetMessageType()) 43 44 parent := m.GetInputType().FindFieldByName("parent") 45 ref := utils.GetResourceReference(parent) 46 47 if resource.GetType() == ref.GetType() { 48 return []lint.Problem{{ 49 Message: "List should use a `child_type` reference to the paginated resource, not a `type` reference.", 50 Descriptor: parent, 51 Location: locations.FieldResourceReference(parent), 52 }} 53 } 54 if ref.GetChildType() != "" && resource.GetType() != ref.GetChildType() { 55 return []lint.Problem{{ 56 Message: "List should use a `child_type` reference to the paginated resource.", 57 Descriptor: parent, 58 Location: locations.FieldResourceReference(parent), 59 }} 60 } 61 62 return nil 63 }, 64 }