Skip to content

Commit f0c8801

Browse files
committed
maxlength:Fix byte slice suggestion, string alias map keys, and comments
1 parent 08a5266 commit f0c8801

3 files changed

Lines changed: 31 additions & 13 deletions

File tree

pkg/analysis/maxlength/analyzer.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -166,13 +166,17 @@ func (a *analyzer) checkArrayType(pass *analysis.Pass, arrayType *ast.ArrayType,
166166
if ident.Name == "byte" {
167167
// byte slices are a special case as they are treated as strings.
168168
// Pretend the ident is a string so that checkString can process it as expected.
169-
// In DV, +k8s:maxBytes (not +k8s:maxLength) is the correct tag for []byte fields,
169+
// In DV, k8s:maxBytes (not k8s:maxLength) is the correct tag for []byte fields,
170170
// as it constrains byte count rather than Unicode character count.
171171
i := &ast.Ident{
172172
NamePos: ident.NamePos,
173173
Name: "string",
174174
}
175-
checkString(pass, i, node, aliases, markersAccess, prefix, a.preferredMaxLengthMarker, a.needsByteSliceMaxLength)
175+
suggestedMarker := a.preferredMaxLengthMarker
176+
if suggestedMarker == markers.K8sMaxLengthMarker {
177+
suggestedMarker = markers.K8sMaxBytesMarker
178+
}
179+
checkString(pass, i, node, aliases, markersAccess, prefix, suggestedMarker, a.needsByteSliceMaxLength)
176180

177181
return
178182
}
@@ -189,12 +193,12 @@ func (a *analyzer) checkArrayType(pass *analysis.Pass, arrayType *ast.ArrayType,
189193
}
190194

191195
// checkMapType checks that map[string]V fields have a maximum properties marker.
192-
// Only string-keyed maps are checked, mirroring the DV constraint that +k8s:maxProperties
193-
// applies to map[string]V types only.
196+
// Only string-keyed maps are checked, mirroring the constraint that maxProperties
197+
// validation only applies to map[string]V types.
194198
func (a *analyzer) checkMapType(pass *analysis.Pass, mapType *ast.MapType, node ast.Node, aliases []*ast.TypeSpec, markersAccess markershelper.Markers, prefix string) {
195-
// DV +k8s:maxProperties only supports string-keyed maps.
199+
// Map maxProperties validation only supports string-keyed maps.
196200
// Skip non-string-keyed maps (e.g. map[int]string) to avoid false positives.
197-
if keyIdent, ok := mapType.Key.(*ast.Ident); !ok || keyIdent.Name != "string" {
201+
if !utils.IsStringType(pass, mapType.Key) {
198202
return
199203
}
200204

@@ -267,7 +271,7 @@ func (a *analyzer) needsStringMaxLength(markerSet markershelper.MarkerSet) bool
267271
}
268272

269273
// needsByteSliceMaxLength is like needsStringMaxLength but enforces that for DV markers,
270-
// +k8s:maxBytes is used instead of +k8s:maxLength (which counts characters).
274+
// k8s:maxBytes is used instead of k8s:maxLength (which counts characters).
271275
func (a *analyzer) needsByteSliceMaxLength(markerSet markershelper.MarkerSet) bool {
272276
switch {
273277
case markerSet.Has(markers.KubebuilderMaxLengthMarker),

pkg/analysis/maxlength/testdata/src/a/c.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,21 @@ type DVMaxLength struct {
5858
MapWithNoMaxProperties map[string]string // want `field DVMaxLength.MapWithNoMaxProperties must have a maximum properties, add kubebuilder:validation:MaxProperties marker`
5959

6060
// Non-string-keyed map — should NOT lint.
61-
// DV +k8s:maxProperties only supports string-keyed maps; linter mirrors this constraint.
61+
// Map maxProperties validation only supports string-keyed maps; linter mirrors this constraint.
6262
MapWithIntKey map[int]string
6363

6464
// DV maxLength applied to []byte — SHOULD lint.
65-
// +k8s:maxLength (counts chars) is not the correct DV tag for []byte;
66-
// +k8s:maxBytes (counts bytes) should be used instead.
65+
// k8s:maxLength (counts chars) is not the correct DV tag for []byte;
66+
// k8s:maxBytes (counts bytes) should be used instead.
6767
// +k8s:maxLength=256
6868
ByteSliceWithWrongDVMarker []byte // want `field DVMaxLength.ByteSliceWithWrongDVMarker must have a maximum length, add kubebuilder:validation:MaxLength marker`
69+
70+
// Map with string-alias key — should lint for maxProperties.
71+
MapWithStringAliasKey map[StringAliasDVMaxLength]string // want `field DVMaxLength.MapWithStringAliasKey must have a maximum properties, add kubebuilder:validation:MaxProperties marker`
72+
73+
// Map with string-alias key with marker — should NOT lint.
74+
// +kubebuilder:validation:MaxProperties:=16
75+
MapWithStringAliasKeyAndMarker map[StringAliasDVMaxLength]string
6976
}
7077

7178
// StringAliasDVMaxLength is a string type with the DV maxLength marker on the alias.

pkg/analysis/maxlength/testdata/src/b/b.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ type DVPreferredMaxLength struct {
1515
// +k8s:maxBytes=512
1616
ByteSliceWithDVMaxBytes []byte // satisfied by k8s:maxBytes — no lint
1717

18-
ByteSliceWithoutMax []byte // want `field DVPreferredMaxLength.ByteSliceWithoutMax must have a maximum length, add k8s:maxLength marker`
18+
ByteSliceWithoutMax []byte // want `field DVPreferredMaxLength.ByteSliceWithoutMax must have a maximum length, add k8s:maxBytes marker`
1919

2020
// +k8s:maxItems=128
2121
ArrayWithDVMaxItems []int // satisfied by k8s:maxItems — no lint
@@ -60,10 +60,10 @@ type DVPreferredMaxLength struct {
6060
// +kubebuilder:validation:Format:=duration
6161
KubebuilderDurationString string // kubebuilder format also exempts in DV-preferred mode — no lint
6262

63-
// +k8s:maxLength=256 on a []byte field is the WRONG DV marker; +k8s:maxBytes should be used.
63+
// k8s:maxLength=256 on a []byte field is the WRONG DV marker; k8s:maxBytes should be used.
6464
// The linter must still report the field as missing a valid max-length constraint.
6565
// +k8s:maxLength=256
66-
ByteSliceWithWrongDVMarker []byte // want `field DVPreferredMaxLength.ByteSliceWithWrongDVMarker must have a maximum length, add k8s:maxLength marker`
66+
ByteSliceWithWrongDVMarker []byte // want `field DVPreferredMaxLength.ByteSliceWithWrongDVMarker must have a maximum length, add k8s:maxBytes marker`
6767

6868
// Raw []string — needs both MaxItems and items:MaxLength.
6969
// +k8s:maxItems=16
@@ -74,6 +74,13 @@ type DVPreferredMaxLength struct {
7474
StringArrayWithMaxItemsWithoutElementLength []string // want `field DVPreferredMaxLength.StringArrayWithMaxItemsWithoutElementLength array element must have a maximum length, add kubebuilder:validation:items:MaxLength`
7575

7676
StringArrayWithoutMaxItemsOrElementLength []string // want `field DVPreferredMaxLength.StringArrayWithoutMaxItemsOrElementLength must have a maximum items, add k8s:maxItems marker` `field DVPreferredMaxLength.StringArrayWithoutMaxItemsOrElementLength array element must have a maximum length, add kubebuilder:validation:items:MaxLength`
77+
78+
// Map with string-alias key — should lint for maxProperties.
79+
MapWithStringAliasKey map[StringAliasDVMaxLength]string // want `field DVPreferredMaxLength.MapWithStringAliasKey must have a maximum properties, add k8s:maxProperties marker`
80+
81+
// Map with string-alias key with marker — should NOT lint.
82+
// +k8s:maxProperties=16
83+
MapWithStringAliasKeyAndMarker map[StringAliasDVMaxLength]string
7784
}
7885

7986
// StringAliasDVMaxLength is a string alias carrying a DV maxLength marker.

0 commit comments

Comments
 (0)