internal/lsp/cache: fix leaking wg.Done() and <-ioLimit
There were several returns in this function that could leak both the
wg.Done() and <-ioLimit. This refactors them into defers close to their
counterparts.
Additionally I refactored the function to favor early returns over
nested if statements.
Fixes golang/go#32368
Change-Id: I5357d11ee526c1cb7a6bd1a0f652c61d574c10ab
GitHub-Last-Rev: bfa160b9fd75c4464d2e0a2820c04ddae01de21f
GitHub-Pull-Request: golang/tools#107
Reviewed-on: https://go-review.googlesource.com/c/tools/+/179878
Reviewed-by: Ian Cottrell <iancottrell@google.com>
Run-TryBot: Ian Cottrell <iancottrell@google.com>
diff --git a/internal/lsp/cache/parse.go b/internal/lsp/cache/parse.go
index e9ee0b1..4f8cd35 100644
--- a/internal/lsp/cache/parse.go
+++ b/internal/lsp/cache/parse.go
@@ -61,32 +61,36 @@
wg.Add(1)
go func(i int, filename string) {
ioLimit <- true // wait
+ defer func() {
+ <-ioLimit // signal done
+ wg.Done()
+ }()
- if gof.ast != nil {
+ if gof.ast != nil { // already have an ast
parsed[i], errors[i] = gof.ast, nil
- } else {
- // We don't have a cached AST for this file.
- gof.read(imp.ctx)
- if gof.fc.Error != nil {
- return
- }
- src := gof.fc.Data
- if src == nil {
- parsed[i], errors[i] = nil, fmt.Errorf("No source for %v", filename)
- } else {
- // ParseFile may return both an AST and an error.
- parsed[i], errors[i] = parseFile(imp.fset, filename, src)
-
- // Fix any badly parsed parts of the AST.
- if file := parsed[i]; file != nil {
- tok := imp.fset.File(file.Pos())
- imp.view.fix(imp.ctx, parsed[i], tok, src)
- }
- }
+ return
}
- <-ioLimit // signal
- wg.Done()
+ // No cached AST for this file, so try parsing it.
+ gof.read(imp.ctx)
+ if gof.fc.Error != nil { // file content error, so abort
+ return
+ }
+
+ src := gof.fc.Data
+ if src == nil { // no source
+ parsed[i], errors[i] = nil, fmt.Errorf("No source for %v", filename)
+ return
+ }
+
+ // ParseFile may return a partial AST AND an error.
+ parsed[i], errors[i] = parseFile(imp.fset, filename, src)
+
+ // Fix any badly parsed parts of the AST.
+ if file := parsed[i]; file != nil {
+ tok := imp.fset.File(file.Pos())
+ imp.view.fix(imp.ctx, parsed[i], tok, src)
+ }
}(i, filename)
}
wg.Wait()