Skip to content

Commit

Permalink
lint: add elseif checker v1 (#80)
Browse files Browse the repository at this point in the history
Fixes #77
  • Loading branch information
Iskander Sharipov committed May 18, 2018
1 parent 137a1f1 commit ed22ee5
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 0 deletions.
1 change: 1 addition & 0 deletions cmd/kfulint/lint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ var tests = []*struct {
{"parenthesis"},
{"param-duplication"},
{"underef"},
{"elseif"},
{"big-copy"},
{"long-chain"},
}
Expand Down
66 changes: 66 additions & 0 deletions cmd/kfulint/testdata/elseif/checker_tests.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package checker_test

func noWarnings() {
cond1 := true
cond2 := true

if cond1 {
}

if cond1 {
} else {
}

if cond1 {
} else if cond2 {
}
}

func suggestSwitch() {
cond1 := true
cond2 := true
cond3 := true

///: should rewrite if-else to switch statement
if cond1 {
} else if cond2 {
} else {
}

///: should rewrite if-else to switch statement
if cond1 {
} else if cond2 {
} else if cond3 {
}

///: should rewrite if-else to switch statement
if cond1 {
} else if cond2 {
} else if cond3 {
} else {
}

///: should rewrite if-else to switch statement
if cond1 {
} else if cond2 {
if cond3 {
}
} else {
// Assume that top if-else statement warning is enough.
if cond1 {
} else if cond2 {
} else {
}
}
}

func describeInt(x int) string {
///: should rewrite if-else to switch statement
if x == 0 {
return "zero"
} else if x < 0 {
return "negative"
} else {
return "positive"
}
}
68 changes: 68 additions & 0 deletions lint/elseif_checker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package lint

import (
"fmt"
"go/ast"
)

type elseifChecker struct {
ctx *Context

rootStmt ast.Stmt
}

func newElseifChecker(ctx *Context) Checker {
return &elseifChecker{ctx: ctx}
}

// Check finds repeated if-else statements and suggests to replace
// them with switch statement.
//
// Features
//
// Permits single else or else-if; repeated else-if or else + else-if
// will trigger suggestion to use switch statement.
func (c *elseifChecker) Check(f *ast.File) {
ast.Inspect(f, func(x ast.Node) bool {
if stmt, ok := x.(*ast.IfStmt); ok {
c.rootStmt = stmt
return !c.checkIfStmt(stmt)
}
return true
})
}

func (c *elseifChecker) checkIfStmt(stmt *ast.IfStmt) bool {
const minThreshold = 2
if c.countIfelseLen(stmt) >= minThreshold {
c.warn()
return true
}
return false
}

func (c *elseifChecker) countIfelseLen(stmt *ast.IfStmt) int {
count := 0
for {
switch e := stmt.Else.(type) {
case *ast.IfStmt:
// Else if.
stmt = e
count++
case *ast.BlockStmt:
// Else branch.
return count + 1
default:
// No else or else if.
return count
}
}
}

func (c *elseifChecker) warn() {
c.ctx.addWarning(Warning{
Kind: "elseif",
Node: c.rootStmt,
Text: fmt.Sprintf("should rewrite if-else to switch statement"),
})
}
1 change: 1 addition & 0 deletions lint/lint.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ var checkers = map[string]func(c *Context) Checker{
"parenthesis": newParenthesisChecker,
"underef": newUnderefChecker,
"param-duplication": newParamDuplicationChecker,
"elseif": newElseifChecker,
"big-copy": newBigCopyChecker,
"long-chain": newLongChainChecker,
}
Expand Down

0 comments on commit ed22ee5

Please sign in to comment.