mirror of
				https://github.com/mgechev/revive.git
				synced 2025-10-30 23:37:49 +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:
		| @@ -40,6 +40,9 @@ func (w lintEmptyBlock) Visit(node ast.Node) ast.Visitor { | |||||||
| 	case *ast.FuncLit: | 	case *ast.FuncLit: | ||||||
| 		w.ignore[n.Body] = true | 		w.ignore[n.Body] = true | ||||||
| 		return w | 		return w | ||||||
|  | 	case *ast.SelectStmt: | ||||||
|  | 		w.ignore[n.Body] = true | ||||||
|  | 		return w | ||||||
| 	case *ast.RangeStmt: | 	case *ast.RangeStmt: | ||||||
| 		if len(n.Body.List) == 0 { | 		if len(n.Body.List) == 0 { | ||||||
| 			w.onFailure(lint.Failure{ | 			w.onFailure(lint.Failure{ | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								testdata/empty-block.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										13
									
								
								testdata/empty-block.go
									
									
									
									
										vendored
									
									
								
							| @@ -2,6 +2,8 @@ | |||||||
|  |  | ||||||
| package fixtures | package fixtures | ||||||
|  |  | ||||||
|  | import "net/http" | ||||||
|  |  | ||||||
| func f(x int) {} // Must not match | func f(x int) {} // Must not match | ||||||
|  |  | ||||||
| type foo struct{} | type foo struct{} | ||||||
| @@ -9,6 +11,12 @@ type foo struct{} | |||||||
| func (f foo) f(x *int)  {} // Must not match | func (f foo) f(x *int)  {} // Must not match | ||||||
| func (f *foo) g(y *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) { | func g(f func() bool) { | ||||||
| 	{ // MATCH /this block is empty, you can remove it/ | 	{ // 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/ | 	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/ | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user