Skip to content

Commit 8037397

Browse files
committed
Switch NoDurations linter to type checker
1 parent 9c73035 commit 8037397

File tree

1 file changed

+20
-58
lines changed

1 file changed

+20
-58
lines changed

pkg/analysis/nodurations/analyzer.go

Lines changed: 20 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ limitations under the License.
1717
package nodurations
1818

1919
import (
20-
"fmt"
2120
"go/ast"
2221

2322
"golang.org/x/tools/go/analysis"
@@ -45,78 +44,41 @@ func run(pass *analysis.Pass) (any, error) {
4544
return nil, kalerrors.ErrCouldNotGetInspector
4645
}
4746

48-
inspect.InspectFields(func(field *ast.Field, _ extractjsontags.FieldTagInfo, markersAccess markers.Markers, qualifiedFieldName string) {
49-
checkField(pass, field, qualifiedFieldName)
47+
typeChecker := utils.NewTypeChecker(isDurationType, checkDuration)
48+
49+
inspect.InspectFields(func(field *ast.Field, _ extractjsontags.FieldTagInfo, _ markers.Markers, _ string) {
50+
typeChecker.CheckNode(pass, field)
5051
})
5152

5253
inspect.InspectTypeSpec(func(typeSpec *ast.TypeSpec, markersAccess markers.Markers) {
53-
checkTypeSpec(pass, typeSpec, typeSpec, "type")
54+
typeChecker.CheckNode(pass, typeSpec)
5455
})
5556

5657
return nil, nil //nolint:nilnil
5758
}
5859

59-
func checkField(pass *analysis.Pass, field *ast.Field, qualifiedFieldName string) {
60-
prefix := fmt.Sprintf("field %s", qualifiedFieldName)
61-
62-
checkTypeExpr(pass, field.Type, field, prefix)
63-
}
64-
65-
//nolint:cyclop
66-
func checkTypeExpr(pass *analysis.Pass, typeExpr ast.Expr, node ast.Node, prefix string) {
67-
switch typ := typeExpr.(type) {
68-
case *ast.SelectorExpr:
69-
pkg, ok := typ.X.(*ast.Ident)
70-
if !ok {
71-
return
72-
}
73-
74-
if typ.X == nil || (pkg.Name != "time" && pkg.Name != "metav1") {
75-
return
76-
}
77-
78-
// Array element is not a metav1.Condition.
79-
if typ.Sel == nil || typ.Sel.Name != "Duration" {
80-
return
81-
}
82-
83-
pass.Reportf(node.Pos(), "%s should not use a Duration. Use an integer type with units in the name to avoid the need for clients to implement Go style duration parsing.", prefix)
84-
case *ast.Ident:
85-
checkIdent(pass, typ, node, prefix)
86-
case *ast.StarExpr:
87-
checkTypeExpr(pass, typ.X, node, fmt.Sprintf("%s pointer", prefix))
88-
case *ast.ArrayType:
89-
checkTypeExpr(pass, typ.Elt, node, fmt.Sprintf("%s array element", prefix))
90-
case *ast.MapType:
91-
checkTypeExpr(pass, typ.Key, node, fmt.Sprintf("%s map key", prefix))
92-
checkTypeExpr(pass, typ.Value, node, fmt.Sprintf("%s map value", prefix))
93-
}
94-
}
95-
96-
// checkIdent calls the checkFunc with the ident, when we have hit a built-in type.
97-
// If the ident is not a built in, we look at the underlying type until we hit a built-in type.
98-
func checkIdent(pass *analysis.Pass, ident *ast.Ident, node ast.Node, prefix string) {
99-
if utils.IsBasicType(pass, ident) {
100-
// We've hit a built-in type, no need to check further.
101-
return
60+
func isDurationType(pass *analysis.Pass, expr ast.Expr) bool {
61+
typ, ok := expr.(*ast.SelectorExpr)
62+
if !ok {
63+
return false
10264
}
10365

104-
tSpec, ok := utils.LookupTypeSpec(pass, ident)
66+
pkg, ok := typ.X.(*ast.Ident)
10567
if !ok {
106-
return
68+
return false
10769
}
10870

109-
// The field is using a type alias, check if the alias is an int.
110-
checkTypeSpec(pass, tSpec, node, fmt.Sprintf("%s type", prefix))
111-
}
71+
if typ.X == nil || (pkg.Name != "time" && pkg.Name != "metav1") {
72+
return false
73+
}
11274

113-
func checkTypeSpec(pass *analysis.Pass, tSpec *ast.TypeSpec, node ast.Node, prefix string) {
114-
if tSpec.Name == nil {
115-
return
75+
if typ.Sel == nil || typ.Sel.Name != "Duration" {
76+
return false
11677
}
11778

118-
typeName := tSpec.Name.Name
119-
prefix = fmt.Sprintf("%s %s", prefix, typeName)
79+
return true
80+
}
12081

121-
checkTypeExpr(pass, tSpec.Type, node, prefix)
82+
func checkDuration(pass *analysis.Pass, expr ast.Expr, node ast.Node, prefix string) {
83+
pass.Reportf(node.Pos(), "%s should not use a Duration. Use an integer type with units in the name to avoid the need for clients to implement Go style duration parsing.", prefix)
12284
}

0 commit comments

Comments
 (0)