1
0
mirror of https://github.com/mgechev/revive.git synced 2025-02-09 13:37:14 +02:00

empty-block: Fix false positive on select {} (#805)

This fixes a false positive reported by revive on the following:

    select {}

This is a way to block the program indefinitely.
It is used in cases like:

- Running a long-running server in a background thread
  and blocking `main` from exiting until the application dies.
  This is something you might do if your process has
  multiple servers/listeners in the same process.

  ```go
  go grpcListenAndServe()
  go httpListenAndServe()
  go logFlusher()

  select {}
  ```

- In programs compiled to WASM to prevent the application from exiting,
  so that the Javascript components may interact with it.

  ```go
  func main() {
    js.Global().Set("foo", foo)
    select {}
  }
  ```

  Without this, one may see an error like,
  "Error: Go program has already exited"

As a workaround, these programs can block forever
by receiving from a throwaway channel (`<-make(chan struct{})`),
but `select {}` is still a completely valid way of doing this,
so supporting it makes sense.

The issue was previously reported in #698 but was closed
because the author was satisfied with a `//nolint` comment.

Now that this rule is part of the default rule set (#799)
the case for addressing the false positive is stronger.

Resolves #804
This commit is contained in:
Abhinav Gupta 2023-03-16 13:39:52 -07:00 committed by GitHub
parent 5db07b5c97
commit b03e54f617
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 16 additions and 0 deletions

View File

@ -40,6 +40,9 @@ func (w lintEmptyBlock) Visit(node ast.Node) ast.Visitor {
case *ast.FuncLit:
w.ignore[n.Body] = true
return w
case *ast.SelectStmt:
w.ignore[n.Body] = true
return w
case *ast.RangeStmt:
if len(n.Body.List) == 0 {
w.onFailure(lint.Failure{

View File

@ -2,6 +2,8 @@
package fixtures
import "net/http"
func f(x int) {} // Must not match
type foo struct{}
@ -9,6 +11,12 @@ type foo struct{}
func (f foo) f(x *int) {} // Must not match
func (f *foo) g(y *int) {} // Must not match
func h() {
go http.ListenAndServe()
select {} // Must not match
}
func g(f func() bool) {
{ // MATCH /this block is empty, you can remove it/
}
@ -44,4 +52,9 @@ func g(f func() bool) {
for range s { // MATCH /this block is empty, you can remove it/
}
select {
case _, ok := <-c:
if ok { // MATCH /this block is empty, you can remove it/
}
}
}