github.com/googleapis/api-linter@v1.65.2/rules/aip0132/response_unknown_fields.go (about)

     1  // Copyright 2019 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  	"strings"
    19  
    20  	"bitbucket.org/creachadair/stringset"
    21  	"github.com/googleapis/api-linter/lint"
    22  	"github.com/googleapis/api-linter/rules/internal/utils"
    23  	"github.com/jhump/protoreflect/desc"
    24  )
    25  
    26  // The resource itself is not included here, but also permitted.
    27  // This is covered in code in the rule itself.
    28  var respAllowedFields = stringset.New(
    29  	"next_page_token",       // AIP-158
    30  	"total_size",            // AIP-132
    31  	"unreachable",           // AIP-217
    32  	"unreachable_locations", // Wrong, but a separate AIP-217 rule catches it.
    33  )
    34  
    35  var responseUnknownFields = &lint.FieldRule{
    36  	Name: lint.NewRuleName(132, "response-unknown-fields"),
    37  	OnlyIf: func(f *desc.FieldDescriptor) bool {
    38  		return utils.IsListResponseMessage(f.GetOwner())
    39  	},
    40  	LintField: func(f *desc.FieldDescriptor) []lint.Problem {
    41  		// A repeated variant of the resource should be permitted.
    42  		resource := utils.ListResponseResourceName(f.GetOwner())
    43  		if strings.HasSuffix(resource, "_revisions") {
    44  			// This is an AIP-162 ListFooRevisions response, which is subtly
    45  			// different from an AIP-132 List response. We need to modify the RPC
    46  			// name to what the AIP-132 List response would be in order to permit
    47  			// the resource field properly.
    48  			resource = utils.ToPlural(strings.TrimSuffix(resource, "_revisions"))
    49  		}
    50  		if f.GetName() == resource {
    51  			return nil
    52  		}
    53  
    54  		// It is not the resource field; check it against the whitelist.
    55  		if !respAllowedFields.Contains(f.GetName()) {
    56  			return []lint.Problem{{
    57  				Message:    "List responses should only contain fields explicitly described in AIPs.",
    58  				Descriptor: f,
    59  			}}
    60  		}
    61  		return nil
    62  	},
    63  }