Skip to content

Commit bb82f00

Browse files
authored
fix(AIP-203): field-behavior-required ignore imported request types (#1504)
fixes a bug where the method input type used as the starting point for the `field-behavior-required` recursion did not check if the input type itself was from the same package. It is not a super common practice in general, but appears a lot for APIs that mix in the google.iam.v1 IAM Policy service RPCs and reuse their request messages. Same thing could happen with `google.api.HttpBody` which is sometimes used as a RPC input type. Updates #1503
1 parent 66a2194 commit bb82f00

File tree

2 files changed

+24
-3
lines changed

2 files changed

+24
-3
lines changed

rules/aip0203/field_behavior_required.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ var fieldBehaviorRequired = &lint.MethodRule{
4949
func problems(m *desc.MessageDescriptor, pkg string, visited map[desc.Descriptor]bool) []lint.Problem {
5050
var ps []lint.Problem
5151

52+
// Ensure the input type, or recursively visited message, is part of the
53+
// same package before linting.
54+
if m.GetFile().GetPackage() != pkg {
55+
return nil
56+
}
57+
5258
for _, f := range m.GetFields() {
5359
// ignore the field if it was already visited
5460
if ok := visited[f]; ok {
@@ -68,7 +74,7 @@ func problems(m *desc.MessageDescriptor, pkg string, visited map[desc.Descriptor
6874
}
6975
}
7076

71-
if mt := f.GetMessageType(); mt != nil && !mt.IsMapEntry() && mt.GetFile().GetPackage() == pkg {
77+
if mt := f.GetMessageType(); mt != nil && !mt.IsMapEntry() {
7278
ps = append(ps, problems(mt, pkg, visited)...)
7379
}
7480
}

rules/aip0203/field_behavior_required_test.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,26 +253,37 @@ func TestFieldBehaviorRequired_NestedMessages_MultipleFile(t *testing.T) {
253253
name string
254254
MessageType string
255255
MessageFieldName string
256+
RequestMessage string
256257
problems testutils.Problems
257258
}{
258259
{
259260
"ValidAnnotatedAndChildAnnotated",
260261
"Annotated",
261262
"annotated",
263+
"UpdateBookRequest",
262264
nil,
263265
},
264266
{
265267
"ValidAnnotatedAndChildInOtherPackageUnannotated",
266268
"unannotated.NonAnnotated",
267269
"non_annotated",
270+
"UpdateBookRequest",
268271
nil,
269272
},
270273
{
271274
"InvalidChildNotAnnotated",
272275
"NonAnnotated",
273276
"non_annotated",
277+
"UpdateBookRequest",
274278
testutils.Problems{{Message: "must be set"}},
275279
},
280+
{
281+
"SkipRequestInOtherPackageUnannotated",
282+
"Annotated", // set this so that the template compiles
283+
"annotated", // set this so that the template compiles
284+
"unannotated.NonAnnotated", // unannotated message as request
285+
nil,
286+
},
276287
}
277288
for _, tc := range testCases {
278289
t.Run(tc.name, func(t *testing.T) {
@@ -284,7 +295,7 @@ func TestFieldBehaviorRequired_NestedMessages_MultipleFile(t *testing.T) {
284295
import "unannotated.proto";
285296
286297
service Library {
287-
rpc UpdateBook(UpdateBookRequest) returns (UpdateBookResponse) {
298+
rpc UpdateBook({{.RequestMessage}}) returns (UpdateBookResponse) {
288299
}
289300
}
290301
@@ -317,7 +328,11 @@ func TestFieldBehaviorRequired_NestedMessages_MultipleFile(t *testing.T) {
317328
package apilinter.test.unannotated;
318329
319330
message NonAnnotated {
320-
string nested = 1;
331+
OtherNonAnnotated nested = 1;
332+
}
333+
334+
message OtherNonAnnotated {
335+
string foo = 1;
321336
}
322337
`
323338

0 commit comments

Comments
 (0)