Skip to content

Commit

Permalink
Ignore intentional empty cases
Browse files Browse the repository at this point in the history
  • Loading branch information
KamikazeZirou committed May 12, 2021
1 parent 5775b8a commit 749808c
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 14 deletions.
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func f() {
switch v {
case 1:
case 2:
fmt.Println("case 1 or 2")
fmt.Println("execute")
}
}
```
Expand All @@ -39,3 +39,24 @@ Of course, Println() donesn't be executed.
However, it takes a while to realize this when you write it.

This Analyzer detects empty cases, making it faster to notice problems.

## Ignore intentional empty cases

Sometimes an empty case is written to indicate that nothing is to be processed on purpose.
This Analyzer ignores empty cases that have comments.

```go
func f() {
v := 1
switch v {
case 1: // This is an intentionally empty case.
case 2:
// This is an intentionally empty case.
// If you want to write a comment on a different line from the case statement, you need to put a blank line between it and the next case statement.

case 3:
fmt.Println("execute")
}
}

```
35 changes: 29 additions & 6 deletions emptycase.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package emptycase

import (
"github.com/gostaticanalysis/comment"
"go/ast"
"strings"

"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
Expand All @@ -20,7 +22,32 @@ var Analyzer = &analysis.Analyzer{
},
}

var analyzerTest = false

func run(pass *analysis.Pass) (interface{}, error) {
commentMap := comment.New(pass.Fset, pass.Files)

// Report a case with no body.
// However, if a comment is attached to it, it is considered an intentional empty case and not reported.
var emptyCaseChecker = func(caseNode ast.Node, body []ast.Stmt) {
if len(body) != 0 {
return
}

commentGroup := commentMap.Comments(caseNode)
if len(commentGroup) == 0 {
pass.Reportf(caseNode.Pos(), "empty case")
return
}

if analyzerTest {
// Comments that indicate the expected value of the analyzer test are not considered comments.
if len(commentGroup) == 1 && strings.HasPrefix(strings.TrimLeft(commentGroup[0].List[0].Text[2:], " "), "want") {
pass.Reportf(caseNode.Pos(), "empty case")
}
}
}

inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)

nodeFilter := []ast.Node{
Expand All @@ -31,13 +58,9 @@ func run(pass *analysis.Pass) (interface{}, error) {
inspect.Preorder(nodeFilter, func(n ast.Node) {
switch n := n.(type) {
case *ast.CaseClause:
if len(n.Body) == 0 {
pass.Reportf(n.Pos(), "empty case")
}
emptyCaseChecker(n, n.Body)
case *ast.CommClause:
if len(n.Body) == 0 {
pass.Reportf(n.Pos(), "empty case")
}
emptyCaseChecker(n, n.Body)
}
})

Expand Down
8 changes: 4 additions & 4 deletions emptycase_test.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package emptycase_test
package emptycase

import (
"github.com/gostaticanalysis/emptycase"
"testing"

"github.com/gostaticanalysis/testutil"
"golang.org/x/tools/go/analysis/analysistest"
)

// TestAnalyzer is a test for Analyzer.
// TestAnalyzer is a analyzerTest for Analyzer.
func TestAnalyzer(t *testing.T) {
testdata := testutil.WithModules(t, analysistest.TestData(), nil)
analysistest.Run(t, testdata, emptycase.Analyzer, "a")
analyzerTest = true
analysistest.Run(t, testdata, Analyzer, "a")
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/gostaticanalysis/emptycase
go 1.16

require (
github.com/gostaticanalysis/comment v1.4.2
github.com/gostaticanalysis/testutil v0.4.0
golang.org/x/tools v0.1.1-0.20210205202024-ef80cdb6ec6d
)
6 changes: 5 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4 h1:L8R9j+yAqZuZjsqh/z+F1NCffTKKLShY6zXTItVIZ8M=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/gostaticanalysis/comment v1.4.2 h1:hlnx5+S2fY9Zo9ePo4AhgYsYHbM2+eAv8m/s1JiCd6Q=
github.com/gostaticanalysis/comment v1.4.2/go.mod h1:KLUTGDv6HOCotCH8h2erHKmpci2ZoR8VPu34YA2uzdM=
github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M=
github.com/gostaticanalysis/testutil v0.4.0 h1:nhdCmubdmDF6VEatUNjgUZBJKWRqugoISdUv3PPQgHY=
github.com/gostaticanalysis/testutil v0.4.0/go.mod h1:bLIoPefWXrRi/ssLFWX1dx7Repi5x3CuviD3dgAZaBU=
github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI=
Expand Down
7 changes: 5 additions & 2 deletions testdata/src/a/a.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ func f() {
switch v {
case 1: // want "empty case"
case 2:
fmt.Println("case 2")
// Intentional empty case. Not treated as an error.

case 3:
fmt.Println("execute")
}
}

Expand All @@ -17,6 +20,6 @@ func g() {
select {
case <-ch: // want "empty case"
default:
fmt.Println("no value")
fmt.Println("execute")
}
}

0 comments on commit 749808c

Please sign in to comment.