1package checkers
2
3import (
4	"go/ast"
5
6	"github.com/go-critic/go-critic/checkers/internal/astwalk"
7	"github.com/go-critic/go-critic/checkers/internal/lintutil"
8	"github.com/go-critic/go-critic/framework/linter"
9	"github.com/go-toolsmith/astcast"
10	"golang.org/x/tools/go/ast/astutil"
11)
12
13func init() {
14	var info linter.CheckerInfo
15	info.Name = "newDeref"
16	info.Tags = []string{"style"}
17	info.Summary = "Detects immediate dereferencing of `new` expressions"
18	info.Before = `x := *new(bool)`
19	info.After = `x := false`
20
21	collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
22		return astwalk.WalkerForExpr(&newDerefChecker{ctx: ctx}), nil
23	})
24}
25
26type newDerefChecker struct {
27	astwalk.WalkHandler
28	ctx *linter.CheckerContext
29}
30
31func (c *newDerefChecker) VisitExpr(expr ast.Expr) {
32	deref := astcast.ToStarExpr(expr)
33	call := astcast.ToCallExpr(deref.X)
34	if astcast.ToIdent(call.Fun).Name == "new" {
35		typ := c.ctx.TypeOf(call.Args[0])
36		zv := lintutil.ZeroValueOf(astutil.Unparen(call.Args[0]), typ)
37		if zv != nil {
38			c.warn(expr, zv)
39		}
40	}
41}
42
43func (c *newDerefChecker) warn(cause, suggestion ast.Expr) {
44	c.ctx.Warn(cause, "replace `%s` with `%s`", cause, suggestion)
45}
46