Skip to content

Commit eae36ea

Browse files
authored
fix(static-msg): support binary expressions (#80)
1 parent 1a45042 commit eae36ea

File tree

2 files changed

+25
-10
lines changed

2 files changed

+25
-10
lines changed

sloglint.go

+13-6
Original file line numberDiff line numberDiff line change
@@ -239,15 +239,19 @@ func visit(pass *analysis.Pass, opts *Options, node ast.Node, stack []ast.Node)
239239
}
240240

241241
msgPos := funcInfo.argsPos - 1
242+
242243
// NOTE: "With" functions have no message argument and must be skipped.
243244
if opts.StaticMsg && msgPos >= 0 && !isStaticMsg(call.Args[msgPos]) {
244245
pass.Reportf(call.Pos(), "message should be a string literal or a constant")
245246
}
246247

247248
if opts.MsgStyle != "" && msgPos >= 0 {
248-
if msg, ok := call.Args[msgPos].(*ast.BasicLit); ok && msg.Kind == token.STRING {
249-
msg.Value = msg.Value[1 : len(msg.Value)-1] // trim quotes/backticks.
250-
if ok := isValidMsgStyle(msg.Value, opts.MsgStyle); !ok {
249+
if lit, ok := call.Args[msgPos].(*ast.BasicLit); ok && lit.Kind == token.STRING {
250+
value, err := strconv.Unquote(lit.Value)
251+
if err != nil {
252+
panic("unreachable") // string literals are always quoted.
253+
}
254+
if ok := isValidMsgStyle(value, opts.MsgStyle); !ok {
251255
pass.Reportf(call.Pos(), "message should be %s", opts.MsgStyle)
252256
}
253257
}
@@ -267,7 +271,6 @@ func visit(pass *analysis.Pass, opts *Options, node ast.Node, stack []ast.Node)
267271
if typ == nil {
268272
continue
269273
}
270-
271274
switch typ.String() {
272275
case "string":
273276
keys = append(keys, args[i])
@@ -376,6 +379,11 @@ func isStaticMsg(msg ast.Expr) bool {
376379
return msg.Kind == token.STRING
377380
case *ast.Ident: // e.g. const msg = "msg"; slog.Info(msg)
378381
return msg.Obj != nil && msg.Obj.Kind == ast.Con
382+
case *ast.BinaryExpr: // e.g. slog.Info("x" + "y")
383+
if msg.Op != token.ADD {
384+
panic("unreachable") // only + can be applied to strings.
385+
}
386+
return isStaticMsg(msg.X) && isStaticMsg(msg.Y)
379387
default:
380388
return false
381389
}
@@ -455,10 +463,9 @@ func getKeyName(key ast.Expr) (string, bool) {
455463
}
456464
}
457465
if lit, ok := key.(*ast.BasicLit); ok && lit.Kind == token.STRING {
458-
// string literals are always quoted.
459466
value, err := strconv.Unquote(lit.Value)
460467
if err != nil {
461-
panic("unreachable")
468+
panic("unreachable") // string literals are always quoted.
462469
}
463470
return value, true
464471
}

testdata/src/static_msg/static_msg.go

+12-4
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,21 @@ func tests() {
2323
slog.Log(ctx, slog.LevelInfo, constMsg)
2424
slog.With("key", "value").Info(constMsg)
2525

26+
slog.Info(varMsg) // want `message should be a string literal or a constant`
27+
slog.InfoContext(ctx, varMsg) // want `message should be a string literal or a constant`
28+
slog.Log(ctx, slog.LevelInfo, varMsg) // want `message should be a string literal or a constant`
29+
slog.With("key", "value").Info(varMsg) // want `message should be a string literal or a constant`
30+
2631
slog.Info(fmt.Sprintf("msg")) // want `message should be a string literal or a constant`
2732
slog.InfoContext(ctx, fmt.Sprintf("msg")) // want `message should be a string literal or a constant`
2833
slog.Log(ctx, slog.LevelInfo, fmt.Sprintf("msg")) // want `message should be a string literal or a constant`
2934
slog.With("key", "value").Info(fmt.Sprintf("msg")) // want `message should be a string literal or a constant`
3035

31-
slog.Info(varMsg) // want `message should be a string literal or a constant`
32-
slog.InfoContext(ctx, varMsg) // want `message should be a string literal or a constant`
33-
slog.Log(ctx, slog.LevelInfo, varMsg) // want `message should be a string literal or a constant`
34-
slog.With("key", "value").Info(varMsg) // want `message should be a string literal or a constant`
36+
// binary expressions:
37+
slog.Info("msg" + "msg")
38+
slog.Info("msg" + "msg" + "msg")
39+
slog.Info("msg" + constMsg)
40+
slog.Info("msg" + varMsg) // want `message should be a string literal or a constant`
41+
slog.Info("msg" + fmt.Sprintf("msg")) // want `message should be a string literal or a constant`
42+
slog.Info("msg" + constMsg + varMsg + fmt.Sprintf("msg")) // want `message should be a string literal or a constant`
3543
}

0 commit comments

Comments
 (0)