9
9
"go/token"
10
10
"go/types"
11
11
"go/version"
12
+ "iter"
12
13
"slices"
13
14
"strconv"
14
15
"strings"
@@ -302,32 +303,35 @@ func visit(pass *analysis.Pass, opts *Options, node ast.Node, stack []ast.Node)
302
303
}
303
304
304
305
if opts .NoRawKeys {
305
- forEachKey (pass .TypesInfo , keys , attrs , func ( key ast. Expr ) {
306
+ for key := range AllKeys (pass .TypesInfo , keys , attrs ) {
306
307
if sel , ok := key .(* ast.SelectorExpr ); ok {
307
308
key = sel .Sel // the key is defined in another package, e.g. pkg.ConstKey.
308
309
}
310
+
309
311
isConst := false
312
+
310
313
if ident , ok := key .(* ast.Ident ); ok {
311
314
if obj := pass .TypesInfo .ObjectOf (ident ); obj != nil {
312
315
if _ , ok := obj .(* types.Const ); ok {
313
316
isConst = true
314
317
}
315
318
}
316
319
}
320
+
317
321
if ! isConst {
318
322
pass .Reportf (key .Pos (), "raw keys should not be used" )
319
323
}
320
- })
324
+ }
321
325
}
322
326
323
327
checkKeysNaming (opts , pass , keys , attrs )
324
328
325
329
if len (opts .ForbiddenKeys ) > 0 {
326
- forEachKey (pass .TypesInfo , keys , attrs , func ( key ast. Expr ) {
330
+ for key := range AllKeys (pass .TypesInfo , keys , attrs ) {
327
331
if name , ok := getKeyName (key ); ok && slices .Contains (opts .ForbiddenKeys , name ) {
328
332
pass .Reportf (key .Pos (), "%q key is forbidden and should not be used" , name )
329
333
}
330
- })
334
+ }
331
335
}
332
336
333
337
if opts .ArgsOnSepLines && areArgsOnSameLine (pass .Fset , call , keys , attrs ) {
@@ -337,7 +341,7 @@ func visit(pass *analysis.Pass, opts *Options, node ast.Node, stack []ast.Node)
337
341
338
342
func checkKeysNaming (opts * Options , pass * analysis.Pass , keys , attrs []ast.Expr ) {
339
343
checkKeyNamingCase := func (caseFn func (string ) string , caseName string ) {
340
- forEachKey (pass .TypesInfo , keys , attrs , func ( key ast. Expr ) {
344
+ for key := range AllKeys (pass .TypesInfo , keys , attrs ) {
341
345
name , ok := getKeyName (key )
342
346
if ! ok || name == caseFn (name ) {
343
347
return
@@ -354,7 +358,7 @@ func checkKeysNaming(opts *Options, pass *analysis.Pass, keys, attrs []ast.Expr)
354
358
}},
355
359
}},
356
360
})
357
- })
361
+ }
358
362
}
359
363
360
364
switch opts .KeyNamingCase {
@@ -479,36 +483,52 @@ func isValidMsgStyle(msg, style string) bool {
479
483
}
480
484
}
481
485
482
- func forEachKey (info * types.Info , keys , attrs []ast.Expr , fn func (key ast.Expr )) {
483
- for _ , key := range keys {
484
- fn (key )
485
- }
486
-
487
- for _ , attr := range attrs {
488
- switch attr := attr .(type ) {
489
- case * ast.CallExpr : // e.g. slog.Int()
490
- callee := typeutil .StaticCallee (info , attr )
491
- if callee == nil {
492
- continue
493
- }
494
- if _ , ok := attrFuncs [callee .FullName ()]; ! ok {
495
- continue
486
+ func AllKeys (info * types.Info , keys , attrs []ast.Expr ) iter.Seq [ast.Expr ] {
487
+ return func (yield func (key ast.Expr ) bool ) {
488
+ for _ , key := range keys {
489
+ if ! yield (key ) {
490
+ return
496
491
}
497
- fn (attr .Args [0 ])
492
+ }
493
+
494
+ for _ , attr := range attrs {
495
+ switch attr := attr .(type ) {
496
+ case * ast.CallExpr : // e.g. slog.Int()
497
+ callee := typeutil .StaticCallee (info , attr )
498
+ if callee == nil {
499
+ continue
500
+ }
501
+ if _ , ok := attrFuncs [callee .FullName ()]; ! ok {
502
+ continue
503
+ }
498
504
499
- case * ast.CompositeLit : // slog.Attr{}
500
- switch len (attr .Elts ) {
501
- case 1 : // slog.Attr{Key: ...} | slog.Attr{Value: ...}
502
- if kv := attr .Elts [0 ].(* ast.KeyValueExpr ); kv .Key .(* ast.Ident ).Name == "Key" {
503
- fn (kv .Value )
505
+ if ! yield (attr .Args [0 ]) {
506
+ return
504
507
}
505
- case 2 : // slog.Attr{Key: ..., Value: ...} | slog.Attr{Value: ..., Key: ...} | slog.Attr{..., ...}
506
- if kv , ok := attr .Elts [0 ].(* ast.KeyValueExpr ); ok && kv .Key .(* ast.Ident ).Name == "Key" {
507
- fn (kv .Value )
508
- } else if kv , ok := attr .Elts [1 ].(* ast.KeyValueExpr ); ok && kv .Key .(* ast.Ident ).Name == "Key" {
509
- fn (kv .Value )
510
- } else {
511
- fn (attr .Elts [0 ])
508
+
509
+ case * ast.CompositeLit : // slog.Attr{}
510
+ switch len (attr .Elts ) {
511
+ case 1 : // slog.Attr{Key: ...} | slog.Attr{Value: ...}
512
+ if kv := attr .Elts [0 ].(* ast.KeyValueExpr ); kv .Key .(* ast.Ident ).Name == "Key" {
513
+ if ! yield (kv .Value ) {
514
+ return
515
+ }
516
+ }
517
+
518
+ case 2 : // slog.Attr{Key: ..., Value: ...} | slog.Attr{Value: ..., Key: ...} | slog.Attr{..., ...}
519
+ if kv , ok := attr .Elts [0 ].(* ast.KeyValueExpr ); ok && kv .Key .(* ast.Ident ).Name == "Key" {
520
+ if ! yield (kv .Value ) {
521
+ return
522
+ }
523
+ } else if kv , ok := attr .Elts [1 ].(* ast.KeyValueExpr ); ok && kv .Key .(* ast.Ident ).Name == "Key" {
524
+ if ! yield (kv .Value ) {
525
+ return
526
+ }
527
+ } else {
528
+ if ! yield (attr .Elts [0 ]) {
529
+ return
530
+ }
531
+ }
512
532
}
513
533
}
514
534
}
0 commit comments