diff --git a/docs/rules/0203/required-and-optional.md b/docs/rules/0203/required-and-optional.md deleted file mode 100644 index 9b4df4f46..000000000 --- a/docs/rules/0203/required-and-optional.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -rule: - aip: 203 - name: [core, '0203', required-and-optional] - summary: Required fields must not use the optional keyword. -permalink: /203/required-and-optional -redirect_from: - - /0203/required-and-optional ---- - -# Required fields - -This rule enforces that fields that are annotated as required do not use the -`optional` syntax, as mandated by [AIP-203][]. - -## Details - -This rule looks for fields with a `google.api.field_behavior` annotation set to -`REQUIRED`, and complains if the field also uses the proto3 `optional` syntax. - -## Examples - -**Incorrect** code for this rule: - -```proto -// Incorrect. -message Book { - string name = 1; - - // Fields must not be optional and required. - optional string title = 2 [(google.api.field_behavior) = REQUIRED]; -} -``` - -**Correct** code for this rule: - -```proto -// Correct. -message Book { - string name = 1; - - string title = 2 [(google.api.field_behavior) = REQUIRED]; -} -``` - -## Disabling - -If you need to violate this rule, use a leading comment above the field. -Remember to also include an [aip.dev/not-precedent][] comment explaining why. - -```proto -message Book { - string name = 1; - - // Required. The title of the book. - // (-- api-linter: core::0203::required-and-optional=disabled - // aip.dev/not-precedent: We need to do this because reasons. --) - optional string title = 2 [(google.api.field_behavior) = REQUIRED]; -} -``` - -If you need to violate this rule for an entire file, place the comment at the -top of the file. - -[aip-203]: https://aip.dev/203 -[aip.dev/not-precedent]: https://aip.dev/not-precedent diff --git a/rules/aip0203/aip0203.go b/rules/aip0203/aip0203.go index df421da08..53f43ab71 100644 --- a/rules/aip0203/aip0203.go +++ b/rules/aip0203/aip0203.go @@ -39,7 +39,6 @@ func AddRules(r lint.RuleRegistry) error { optionalBehaviorConflict, outputOnly, required, - requiredAndOptional, unorderedListRepeated, ) } diff --git a/rules/aip0203/required_and_optional.go b/rules/aip0203/required_and_optional.go deleted file mode 100644 index 4cabc370e..000000000 --- a/rules/aip0203/required_and_optional.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2019 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package aip0203 - -import ( - "github.com/googleapis/api-linter/lint" - "github.com/googleapis/api-linter/locations" - "github.com/googleapis/api-linter/rules/internal/utils" - "github.com/jhump/protoreflect/desc" -) - -var requiredAndOptional = &lint.FieldRule{ - Name: lint.NewRuleName(203, "required-and-optional"), - OnlyIf: func(f *desc.FieldDescriptor) bool { - return utils.GetFieldBehavior(f).Contains("REQUIRED") - }, - LintField: func(f *desc.FieldDescriptor) []lint.Problem { - if f.IsProto3Optional() { - return []lint.Problem{{ - Message: "Required fields must not use the optional keyword.", - Descriptor: f, - Location: locations.FieldLabel(f), - Suggestion: "", - }} - } - return nil - }, -} diff --git a/rules/aip0203/required_and_optional_test.go b/rules/aip0203/required_and_optional_test.go deleted file mode 100644 index e16b3af59..000000000 --- a/rules/aip0203/required_and_optional_test.go +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2019 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package aip0203 - -import ( - "testing" - - "github.com/googleapis/api-linter/rules/internal/testutils" -) - -func TestRequiredAndOptional(t *testing.T) { - req := " [(google.api.field_behavior) = REQUIRED]" - for _, test := range []struct { - name string - Optional string - Required string - problems testutils.Problems - }{ - {"Neither", "", "", nil}, - {"OptionalOnly", "optional ", "", nil}, - {"RequiredOnly", "", req, nil}, - {"Both", "optional ", req, testutils.Problems{{Suggestion: ""}}}, - } { - t.Run(test.name, func(t *testing.T) { - f := testutils.ParseProto3Tmpl(t, ` - import "google/api/field_behavior.proto"; - - message Book { - {{.Optional}}int32 page_count = 1{{.Required}}; - } - `, test) - field := f.GetMessageTypes()[0].GetFields()[0] - if diff := test.problems.SetDescriptor(field).Diff(requiredAndOptional.Lint(f)); diff != "" { - t.Errorf(diff) - } - }) - } -}