internal/lsp: prevent too much open files issues

On MacOS the default open file limit is 256 files per process. For big
projects this could cause issues when reading all files (more or less)
at the same time.

By moving up the `parseLimit` so the reading of the file is only done
when it is allowed to start parsing the file, we stay well below the 256
files per process (as the `parseLimit` is currently set to 20).

Since `parseLimit` is actually only used to limit IO access, let's also
rename the const to `parseLimit`.

Change-Id: Ie8744030875d84d0d6095ee4ec2d9d553911bed1
Reviewed-on: https://go-review.googlesource.com/c/tools/+/189437
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
diff --git a/internal/lsp/cache/parse.go b/internal/lsp/cache/parse.go
index 3ef28f1..b842f84 100644
--- a/internal/lsp/cache/parse.go
+++ b/internal/lsp/cache/parse.go
@@ -18,8 +18,8 @@
 	errors "golang.org/x/xerrors"
 )
 
-// Limits the number of parallel parser calls per process.
-var parseLimit = make(chan struct{}, 20)
+// Limits the number of parallel file reads per process.
+var ioLimit = make(chan struct{}, 20)
 
 // parseKey uniquely identifies a parsed Go file.
 type parseKey struct {
@@ -77,12 +77,14 @@
 func parseGo(ctx context.Context, c *cache, fh source.FileHandle, mode source.ParseMode) (*ast.File, error) {
 	ctx, done := trace.StartSpan(ctx, "cache.parseGo", telemetry.File.Of(fh.Identity().URI.Filename()))
 	defer done()
+
+	ioLimit <- struct{}{}
 	buf, _, err := fh.Read(ctx)
+	<-ioLimit // Make sure to release the token, even when an error is returned.
 	if err != nil {
 		return nil, err
 	}
-	parseLimit <- struct{}{}
-	defer func() { <-parseLimit }()
+
 	parserMode := parser.AllErrors | parser.ParseComments
 	if mode == source.ParseHeader {
 		parserMode = parser.ImportsOnly | parser.ParseComments
diff --git a/internal/lsp/cache/view.go b/internal/lsp/cache/view.go
index ef65e64..4f529f1 100644
--- a/internal/lsp/cache/view.go
+++ b/internal/lsp/cache/view.go
@@ -509,7 +509,8 @@
 		pathStat, err := os.Stat(fname)
 		if os.IsNotExist(err) {
 			return nil, err
-		} else if err != nil {
+		}
+		if err != nil {
 			return nil, nil // the file may exist, return without an error
 		}
 		for _, c := range candidates {