@@ -80,23 +80,27 @@ func isDuration(x types.Type) bool {
8080// isUnacceptableExpr returns true if the argument is not an acceptable time.Duration expression
8181func isUnacceptableExpr (pass * analysis.Pass , expr ast.Expr ) bool {
8282 switch e := expr .(type ) {
83- case * ast.BasicLit : // constants are acceptable
83+ case * ast.BasicLit :
8484 return false
85- case * ast.CallExpr : // explicit casting of constants such as `time.Duration(10)` is acceptable
85+ case * ast.CallExpr :
8686 return ! isAcceptableCast (pass , e )
87+ case * ast.BinaryExpr :
88+ return ! isAcceptableNestedExpr (pass , e )
89+ case * ast.UnaryExpr :
90+ return ! isAcceptableNestedExpr (pass , e )
8791 }
8892 return true
8993}
9094
91- // isAcceptableCast returns true if the argument is a constant expression cast to time.Duration
95+ // isAcceptableCast returns true if the argument is an acceptable expression cast to time.Duration
9296func isAcceptableCast (pass * analysis.Pass , e * ast.CallExpr ) bool {
9397 // check that there's a single argument
9498 if len (e .Args ) != 1 {
9599 return false
96100 }
97101
98102 // check that the argument is acceptable
99- if ! isAcceptableCastArg (pass , e .Args [0 ]) {
103+ if ! isAcceptableNestedExpr (pass , e .Args [0 ]) {
100104 return false
101105 }
102106
@@ -106,6 +110,10 @@ func isAcceptableCast(pass *analysis.Pass, e *ast.CallExpr) bool {
106110 return false
107111 }
108112
113+ return isDurationCast (selector )
114+ }
115+
116+ func isDurationCast (selector * ast.SelectorExpr ) bool {
109117 pkg , ok := selector .X .(* ast.Ident )
110118 if ! ok {
111119 return false
@@ -118,16 +126,22 @@ func isAcceptableCast(pass *analysis.Pass, e *ast.CallExpr) bool {
118126 return selector .Sel .Name == "Duration"
119127}
120128
121- func isAcceptableCastArg (pass * analysis.Pass , n ast.Expr ) bool {
129+ func isAcceptableNestedExpr (pass * analysis.Pass , n ast.Expr ) bool {
122130 switch e := n .(type ) {
123131 case * ast.BasicLit :
124132 return true
125133 case * ast.BinaryExpr :
126- return isAcceptableCastArg (pass , e .X ) && isAcceptableCastArg (pass , e .Y )
127- default :
128- argType := pass .TypesInfo .TypeOf (n )
129- return ! isDuration (argType )
134+ return isAcceptableNestedExpr (pass , e .X ) && isAcceptableNestedExpr (pass , e .Y )
135+ case * ast.UnaryExpr :
136+ return isAcceptableNestedExpr (pass , e .X )
137+ case * ast.Ident :
138+ t := pass .TypesInfo .TypeOf (e )
139+ return ! isDuration (t )
140+ case * ast.CallExpr :
141+ t := pass .TypesInfo .TypeOf (e )
142+ return ! isDuration (t )
130143 }
144+ return false
131145}
132146
133147func formatNode (node ast.Node ) string {
@@ -140,8 +154,8 @@ func formatNode(node ast.Node) string {
140154 return buf .String ()
141155}
142156
143- func printAST (node ast.Node ) {
144- fmt .Printf (">>> %s\n " , formatNode (node ))
157+ func printAST (msg string , node ast.Node ) {
158+ fmt .Printf (">>> %s: \n %s \n \n \n " , msg , formatNode (node ))
145159 ast .Fprint (os .Stdout , nil , node , nil )
146160 fmt .Println ("--------------" )
147161}
0 commit comments