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/framework/linter"
8)
9
10func init() {
11	var info linter.CheckerInfo
12	info.Name = "defaultCaseOrder"
13	info.Tags = []string{"style"}
14	info.Summary = "Detects when default case in switch isn't on 1st or last position"
15	info.Before = `
16switch {
17case x > y:
18	// ...
19default: // <- not the best position
20	// ...
21case x == 10:
22	// ...
23}`
24	info.After = `
25switch {
26case x > y:
27	// ...
28case x == 10:
29	// ...
30default: // <- last case (could also be the first one)
31	// ...
32}`
33
34	collection.AddChecker(&info, func(ctx *linter.CheckerContext) (linter.FileWalker, error) {
35		return astwalk.WalkerForStmt(&defaultCaseOrderChecker{ctx: ctx}), nil
36	})
37}
38
39type defaultCaseOrderChecker struct {
40	astwalk.WalkHandler
41	ctx *linter.CheckerContext
42}
43
44func (c *defaultCaseOrderChecker) VisitStmt(stmt ast.Stmt) {
45	swtch, ok := stmt.(*ast.SwitchStmt)
46	if !ok {
47		return
48	}
49	for i, stmt := range swtch.Body.List {
50		caseStmt, ok := stmt.(*ast.CaseClause)
51		if !ok {
52			continue
53		}
54		// is `default` case
55		if caseStmt.List == nil {
56			if i != 0 && i != len(swtch.Body.List)-1 {
57				c.warn(caseStmt)
58			}
59		}
60	}
61}
62
63func (c *defaultCaseOrderChecker) warn(cause *ast.CaseClause) {
64	c.ctx.Warn(cause, "consider to make `default` case as first or as last case")
65}
66