Skip to content

Commit 3fe6ca1

Browse files
Renamed references to noreferences, updated docs, and regex
1 parent c5a8a96 commit 3fe6ca1

File tree

13 files changed

+114
-123
lines changed

13 files changed

+114
-123
lines changed

docs/linters.md

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
- [Notimestamp](#notimestamp) - Prevents usage of 'TimeStamp' fields
1919
- [OptionalFields](#optionalfields) - Validates optional field conventions
2020
- [OptionalOrRequired](#optionalorrequired) - Ensures fields are explicitly marked as optional or required
21-
- [References](#references) - Ensures field names use Ref/Refs instead of Reference/References
21+
- [NoReferences](#noreferences) - Ensures field names use Ref/Refs instead of Reference/References
2222
- [RequiredFields](#requiredfields) - Validates required field conventions
2323
- [SSATags](#ssatags) - Ensures proper Server-Side Apply (SSA) tags on array fields
2424
- [StatusOptional](#statusoptional) - Ensures status fields are marked as optional
@@ -556,17 +556,17 @@ If you prefer not to suggest fixes for pointers in required fields, you can chan
556556
If you prefer not to suggest fixes for `omitempty` in required fields, you can change the `omitempty.policy` to `Warn` or `Ignore`.
557557
If you prefer not to suggest fixes for `omitzero` in required fields, you can change the `omitzero.policy` to `Warn` and also not to consider `omitzero` policy at all, it can be set to `Forbid`.
558558

559-
## References
559+
## NoReferences
560560

561-
The `references` linter ensures that field names use 'Ref'/'Refs' instead of 'Reference'/'References'.
561+
The `noreferences` linter ensures that field names use 'Ref'/'Refs' instead of 'Reference'/'References'.
562562

563-
By default, `references` is enabled and operates in standard mode, allowing 'Ref'/'Refs' but prohibiting 'Reference'/'References' in field names.
563+
By default, `noreferences` is enabled and operates in standard mode, allowing 'Ref'/'Refs' but prohibiting 'Reference'/'References' in field names.
564564

565565
### Configuration
566566

567567
```yaml
568568
lintersConfig:
569-
references:
569+
noreferences:
570570
policy: PreferAbbreviatedReference | NoReferences # Defaults to `PreferAbbreviatedReference`.
571571
```
572572

@@ -581,24 +581,27 @@ lintersConfig:
581581

582582
### Fixes
583583

584-
The `references` linter can automatically fix field names based on the policy:
584+
The `noreferences` linter can automatically fix field names based on the policy:
585585

586586
**PreferAbbreviatedReference mode:**
587-
- Replaces 'Reference' with 'Ref' and 'References' with 'Refs' anywhere in the field name
587+
- Replaces 'Reference' with 'Ref' and 'References' with 'Refs' at the start or end of field names
588+
- This avoids false positives for words like "Preference" where "eference" appears in the middle
588589
- Examples:
589-
- `NodeReference``NodeRef`
590-
- `ReferenceNode``RefNode`
591-
- `NodeReferenceConfig``NodeRefConfig`
592-
- `NodeReferences``NodeRefs`
590+
- `NodeReference``NodeRef` (end)
591+
- `ReferenceNode``RefNode` (start)
592+
- `NodeReferences``NodeRefs` (end)
593+
- `ReferencesCount``RefsCount` (start)
594+
- `PreferenceType` → no change (middle - not flagged)
593595

594596
**NoReferences mode:**
595597
- Removes all reference-related words (Ref/Refs/Reference/References) from the beginning or end of field names
598+
- Like PreferAbbreviatedReference, this only matches at word boundaries to avoid false positives
596599
- Examples:
597-
- `RefNode``Node`
598-
- `NodeRef``Node`
599-
- `ReferenceName``Name`
600-
- `ConfigReferences``Config`
601-
- `ReferenceCount``Count`
600+
- `RefNode``Node` (start)
601+
- `NodeRef``Node` (end)
602+
- `ReferenceName``Name` (start)
603+
- `ConfigReferences``Config` (end)
604+
- `ReferenceCount``Count` (start)
602605

603606
## SSATags
604607

pkg/analysis/references/analyzer.go renamed to pkg/analysis/noreferences/analyzer.go

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
16-
package references
16+
package noreferences
1717

1818
import (
1919
"errors"
@@ -26,13 +26,13 @@ import (
2626
)
2727

2828
const (
29-
name = "references"
29+
name = "noreferences"
3030
doc = "Enforces that fields use Ref/Refs and not Reference/References"
3131
)
3232

3333
var errUnexpectedInitializerType = errors.New("expected namingconventions.Initializer() to be of type initializer.ConfigurableAnalyzerInitializer, but was not")
3434

35-
// newAnalyzer creates a new analyzer for the references linter that is a wrapper around the namingconventions linter.
35+
// newAnalyzer creates a new analyzer for the noreferences linter that is a wrapper around the namingconventions linter.
3636
func newAnalyzer(cfg *Config) *analysis.Analyzer {
3737
if cfg == nil {
3838
cfg = &Config{}
@@ -56,15 +56,15 @@ func newAnalyzer(cfg *Config) *analysis.Analyzer {
5656
}
5757

5858
// Validate generated namingconventions configuration
59-
errs := configInit.ValidateConfig(ncConfig, field.NewPath("references"))
59+
errs := configInit.ValidateConfig(ncConfig, field.NewPath("noreferences"))
6060
if err := errs.ToAggregate(); err != nil {
61-
panic(fmt.Errorf("references linter has an invalid namingconventions configuration: %w", err))
61+
panic(fmt.Errorf("noreferences linter has an invalid namingconventions configuration: %w", err))
6262
}
6363

6464
// Initialize the wrapped analyzer
6565
analyzer, err := configInit.Init(ncConfig)
6666
if err != nil {
67-
panic(fmt.Errorf("references linter encountered an error initializing wrapped namingconventions analyzer: %w", err))
67+
panic(fmt.Errorf("noreferences linter encountered an error initializing wrapped namingconventions analyzer: %w", err))
6868
}
6969

7070
analyzer.Name = name
@@ -78,42 +78,36 @@ func buildConventions(policy Policy) []namingconventions.Convention {
7878
switch policy {
7979
case PolicyPreferAbbreviatedReference:
8080
// Replace "Reference" or "References" with "Ref" or "Refs"
81-
// Using a single regex with optional 's' capture group to handle both cases
81+
// At start: [Rr]eference(s?) matches Reference/References (case insensitive R)
82+
// At end: Reference(s?)$ matches Reference/References (capital R only to avoid "*preference")
8283
return []namingconventions.Convention{
8384
{
8485
Name: "reference-to-ref",
85-
ViolationMatcher: "(?i)reference(s?)",
86+
ViolationMatcher: "^[Rr]eference(s?)|Reference(s?)$",
8687
Operation: namingconventions.OperationReplacement,
87-
Replacement: "Ref$1",
88+
Replacement: "Ref$1$2",
8889
Message: "field names should use 'Ref' instead of 'Reference'",
8990
},
9091
}
9192

9293
case PolicyNoReferences:
9394
// Drop any reference-related words from field names
94-
// Using a regex that matches Ref/Refs/Reference/References at start or end
95-
// At start: matches when followed by an uppercase letter, preserving that letter
96-
// At end: matches at the end of the field name
95+
// At start: matches [Rr]ef(erence)?s? followed by uppercase letter, preserving that letter ($3)
96+
// At end: matches Ref(erence)?s? at end (capital R to avoid "*preference")
97+
// When at start, $3 captures and preserves the next uppercase letter
98+
// When at end, $3 is empty, effectively dropping the text
9799
return []namingconventions.Convention{
98100
{
99101
Name: "no-references",
100-
ViolationMatcher: "^([Rr]ef(?:erence)?s?)([A-Z])|([Rr]ef(?:erence)?s?)$",
102+
ViolationMatcher: "^[Rr]ef(erence)?(s?)([A-Z])|Ref(erence)?(s?)$",
101103
Operation: namingconventions.OperationReplacement,
102-
Replacement: "$2",
104+
Replacement: "$3",
103105
Message: "field names should not contain reference-related words",
104106
},
105107
}
106108

107109
default:
108-
// Should not happen due to validation, but return PreferAbbreviatedReference conventions as fallback
109-
return []namingconventions.Convention{
110-
{
111-
Name: "reference-to-ref",
112-
ViolationMatcher: "(?i)reference(s?)",
113-
Operation: namingconventions.OperationReplacement,
114-
Replacement: "Ref$1",
115-
Message: "field names should use 'Ref' instead of 'Reference'",
116-
},
117-
}
110+
// Should not happen due to validation
111+
panic(fmt.Errorf("invalid policy: %s", policy))
118112
}
119113
}

pkg/analysis/references/analyzer_test.go renamed to pkg/analysis/noreferences/analyzer_test.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,25 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
16-
package references_test
16+
package noreferences_test
1717

1818
import (
1919
"testing"
2020

2121
"golang.org/x/tools/go/analysis/analysistest"
22-
"sigs.k8s.io/kube-api-linter/pkg/analysis/references"
22+
"sigs.k8s.io/kube-api-linter/pkg/analysis/noreferences"
2323
)
2424

2525
func TestPreferAbbreviatedReference(t *testing.T) {
2626
testdata := analysistest.TestData()
2727

28-
cfg := &references.Config{
29-
Policy: references.PolicyPreferAbbreviatedReference,
28+
cfg := &noreferences.Config{
29+
Policy: noreferences.PolicyPreferAbbreviatedReference,
3030
}
3131

32-
analyzer, err := references.Initializer().Init(cfg)
32+
analyzer, err := noreferences.Initializer().Init(cfg)
3333
if err != nil {
34-
t.Fatalf("initializing references linter: %v", err)
34+
t.Fatalf("initializing noreferences linter: %v", err)
3535
}
3636

3737
analysistest.RunWithSuggestedFixes(t, testdata, analyzer, "a")
@@ -41,11 +41,11 @@ func TestEmptyConfig(t *testing.T) {
4141
testdata := analysistest.TestData()
4242

4343
// Test with empty config - should default to PreferAbbreviatedReference behavior
44-
cfg := &references.Config{}
44+
cfg := &noreferences.Config{}
4545

46-
analyzer, err := references.Initializer().Init(cfg)
46+
analyzer, err := noreferences.Initializer().Init(cfg)
4747
if err != nil {
48-
t.Fatalf("initializing references linter: %v", err)
48+
t.Fatalf("initializing noreferences linter: %v", err)
4949
}
5050

5151
// With default config (empty Policy), it should default to PreferAbbreviatedReference behavior
@@ -56,13 +56,13 @@ func TestEmptyConfig(t *testing.T) {
5656
func TestNoReferences(t *testing.T) {
5757
testdata := analysistest.TestData()
5858

59-
cfg := &references.Config{
60-
Policy: references.PolicyNoReferences,
59+
cfg := &noreferences.Config{
60+
Policy: noreferences.PolicyNoReferences,
6161
}
6262

63-
analyzer, err := references.Initializer().Init(cfg)
63+
analyzer, err := noreferences.Initializer().Init(cfg)
6464
if err != nil {
65-
t.Fatalf("initializing references linter: %v", err)
65+
t.Fatalf("initializing noreferences linter: %v", err)
6666
}
6767

6868
analysistest.RunWithSuggestedFixes(t, testdata, analyzer, "b")

pkg/analysis/references/config.go renamed to pkg/analysis/noreferences/config.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
16-
package references
16+
package noreferences
1717

1818
// policy defines the policy for handling references in field names.
1919
type Policy string
@@ -27,7 +27,7 @@ const (
2727
PolicyNoReferences Policy = "NoReferences"
2828
)
2929

30-
// Config represents the configuration for the references linter.
30+
// Config represents the configuration for the noreferences linter.
3131
type Config struct {
3232
// policy controls how reference-related words are handled in field names.
3333
// When set to PreferAbbreviatedReference (default), Reference/References are replaced with Ref/Refs.

pkg/analysis/references/doc.go renamed to pkg/analysis/noreferences/doc.go

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,25 @@ limitations under the License.
1515
*/
1616

1717
/*
18-
The `references` linter ensures that field names use 'Ref'/'Refs' instead of 'Reference'/'References'.
19-
By default, `references` is enabled and enforces this naming convention.
18+
The `noreferences` linter ensures that field names use 'Ref'/'Refs' instead of 'Reference'/'References'.
19+
By default, `noreferences` is enabled and enforces this naming convention.
2020
The linter checks that 'Reference' anywhere in field names (beginning, middle, or end) is replaced with 'Ref'.
2121
Similarly, 'References' anywhere in field names is replaced with 'Refs'.
2222
2323
Example configuration:
24-
**Default behavior (allow Ref/Refs in field names):**
25-
```yaml
26-
lintersConfig:
24+
Default behavior (allow Ref/Refs in field names):
2725
28-
references:
29-
policy: AllowRefAndRefs
26+
lintersConfig:
27+
noreferences:
28+
policy: PreferAbbreviatedReference
3029
31-
```
32-
**Strict mode (forbid Ref/Refs in field names):**
33-
```yaml
34-
lintersConfig:
30+
Strict mode (forbid Ref/Refs in field names):
3531
36-
references:
37-
policy: ForbidRefAndRefs
32+
lintersConfig:
33+
noreferences:
34+
policy: NoReferences
3835
39-
```
40-
When `policy` is set to `AllowRefAndRefs` (the default), fields containing 'Ref' or 'Refs' are allowed.
41-
The policy can be set to `ForbidRefAndRefs` to also report errors for 'Ref' or 'Refs' in field names.
36+
When `policy` is set to `PreferAbbreviatedReference` (the default), fields containing 'Ref' or 'Refs' are allowed.
37+
The policy can be set to `NoReferences` to also report errors for 'Ref' or 'Refs' in field names.
4238
*/
43-
package references
39+
package noreferences

pkg/analysis/references/initializer.go renamed to pkg/analysis/noreferences/initializer.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
16-
package references
16+
package noreferences
1717

1818
import (
1919
"golang.org/x/tools/go/analysis"
@@ -41,7 +41,7 @@ func initAnalyzer(cfg *Config) (*analysis.Analyzer, error) {
4141
return newAnalyzer(cfg), nil
4242
}
4343

44-
// validateConfig validates the configuration for the references linter.
44+
// validateConfig validates the configuration for the noreferences linter.
4545
func validateConfig(cfg *Config, fldPath *field.Path) field.ErrorList {
4646
if cfg == nil {
4747
return nil // nil config is valid, will use defaults

pkg/analysis/references/initializer_test.go renamed to pkg/analysis/noreferences/initializer_test.go

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,44 +13,44 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1313
See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
16-
package references_test
16+
package noreferences_test
1717

1818
import (
1919
. "github.com/onsi/ginkgo/v2"
2020
. "github.com/onsi/gomega"
2121

2222
"k8s.io/apimachinery/pkg/util/validation/field"
2323
"sigs.k8s.io/kube-api-linter/pkg/analysis/initializer"
24-
"sigs.k8s.io/kube-api-linter/pkg/analysis/references"
24+
"sigs.k8s.io/kube-api-linter/pkg/analysis/noreferences"
2525
)
2626

27-
var _ = Describe("references initializer", func() {
27+
var _ = Describe("noreferences initializer", func() {
2828
Context("config validation", func() {
2929
type testCase struct {
30-
config *references.Config
30+
config *noreferences.Config
3131
expectedErr string
3232
}
3333

3434
DescribeTable("should validate the provided config", func(in testCase) {
35-
ci, ok := references.Initializer().(initializer.ConfigurableAnalyzerInitializer)
35+
ci, ok := noreferences.Initializer().(initializer.ConfigurableAnalyzerInitializer)
3636
Expect(ok).To(BeTrue())
3737

38-
errs := ci.ValidateConfig(in.config, field.NewPath("references"))
38+
errs := ci.ValidateConfig(in.config, field.NewPath("noreferences"))
3939
if len(in.expectedErr) > 0 {
4040
Expect(errs.ToAggregate()).To(MatchError(in.expectedErr))
4141
} else {
4242
Expect(errs).To(HaveLen(0), "No errors were expected")
4343
}
4444
},
45-
Entry("With a valid references configuration with policy=NoReferences", testCase{
46-
config: &references.Config{
47-
Policy: references.PolicyNoReferences,
45+
Entry("With a valid noreferences configuration with policy=NoReferences", testCase{
46+
config: &noreferences.Config{
47+
Policy: noreferences.PolicyNoReferences,
4848
},
4949
expectedErr: "",
5050
}),
51-
Entry("With a valid references configuration with policy=PreferAbbreviatedReference", testCase{
52-
config: &references.Config{
53-
Policy: references.PolicyPreferAbbreviatedReference,
51+
Entry("With a valid noreferences configuration with policy=PreferAbbreviatedReference", testCase{
52+
config: &noreferences.Config{
53+
Policy: noreferences.PolicyPreferAbbreviatedReference,
5454
},
5555
expectedErr: "",
5656
}),
@@ -59,14 +59,14 @@ var _ = Describe("references initializer", func() {
5959
expectedErr: "",
6060
}),
6161
Entry("With an empty config", testCase{
62-
config: &references.Config{},
62+
config: &noreferences.Config{},
6363
expectedErr: "",
6464
}),
6565
Entry("With an invalid policy value", testCase{
66-
config: &references.Config{
66+
config: &noreferences.Config{
6767
Policy: "InvalidPolicy",
6868
},
69-
expectedErr: "references.policy: Unsupported value: \"InvalidPolicy\": supported values: \"PreferAbbreviatedReference\", \"NoReferences\"",
69+
expectedErr: "noreferences.policy: Unsupported value: \"InvalidPolicy\": supported values: \"PreferAbbreviatedReference\", \"NoReferences\"",
7070
}),
7171
)
7272
})

0 commit comments

Comments
 (0)