internal/lsp/cache: initialize view before LookupBuiltin

This will crash otherwise.

Change-Id: I4fbce813283291792ed21fa5d83186ec59543ff1
Reviewed-on: https://go-review.googlesource.com/c/tools/+/214948
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
diff --git a/internal/lsp/cache/view.go b/internal/lsp/cache/view.go
index b6a529c..8e7ddf8 100644
--- a/internal/lsp/cache/view.go
+++ b/internal/lsp/cache/view.go
@@ -181,8 +181,11 @@
 	return newView, err
 }
 
-func (v *view) LookupBuiltin(name string) (*ast.Object, error) {
-	data := v.builtin.handle.Get(context.Background())
+func (v *view) LookupBuiltin(ctx context.Context, name string) (*ast.Object, error) {
+	if err := v.awaitInitialized(ctx); err != nil {
+		return nil, err
+	}
+	data := v.builtin.handle.Get(ctx)
 	if data == nil {
 		return nil, errors.Errorf("unexpected nil builtin package")
 	}
diff --git a/internal/lsp/source/completion_builtin.go b/internal/lsp/source/completion_builtin.go
index ddead70..64da769 100644
--- a/internal/lsp/source/completion_builtin.go
+++ b/internal/lsp/source/completion_builtin.go
@@ -13,7 +13,7 @@
 // argument. It attempts to use the AST hints from builtin.go where
 // possible.
 func (c *completer) builtinArgKind(obj types.Object, call *ast.CallExpr) objKind {
-	astObj, err := c.snapshot.View().LookupBuiltin(obj.Name())
+	astObj, err := c.snapshot.View().LookupBuiltin(c.ctx, obj.Name())
 	if err != nil {
 		return 0
 	}
diff --git a/internal/lsp/source/completion_format.go b/internal/lsp/source/completion_format.go
index f9a5aa4..950e06b 100644
--- a/internal/lsp/source/completion_format.go
+++ b/internal/lsp/source/completion_format.go
@@ -47,7 +47,7 @@
 	// expandFuncCall mutates the completion label, detail, and snippet
 	// to that of an invocation of sig.
 	expandFuncCall := func(sig *types.Signature) {
-		params := formatParams(c.snapshot, c.pkg, sig, c.qf)
+		params := formatParams(c.ctx, c.snapshot, c.pkg, sig, c.qf)
 		snip = c.functionCallSnippet(label, params)
 		results, writeParens := formatResults(sig.Results(), c.qf)
 		detail = "func" + formatFunction(params, results, writeParens)
@@ -68,7 +68,7 @@
 			detail = "struct{...}" // for anonymous structs
 		} else if obj.IsField() {
 			var err error
-			detail, err = formatFieldType(c.snapshot, c.pkg, obj, c.qf)
+			detail, err = formatFieldType(c.ctx, c.snapshot, c.pkg, obj, c.qf)
 			if err != nil {
 				detail = types.TypeString(obj.Type(), c.qf)
 			}
@@ -190,7 +190,7 @@
 	if err != nil {
 		return item, nil
 	}
-	ident, err := findIdentifier(c.snapshot, pkg, file, obj.Pos())
+	ident, err := findIdentifier(c.ctx, c.snapshot, pkg, file, obj.Pos())
 	if err != nil {
 		return item, nil
 	}
@@ -245,7 +245,7 @@
 		item.Kind = protocol.ConstantCompletion
 	case *types.Builtin:
 		item.Kind = protocol.FunctionCompletion
-		astObj, err := c.snapshot.View().LookupBuiltin(obj.Name())
+		astObj, err := c.snapshot.View().LookupBuiltin(c.ctx, obj.Name())
 		if err != nil {
 			log.Error(c.ctx, "no builtin package", err)
 			break
diff --git a/internal/lsp/source/identifier.go b/internal/lsp/source/identifier.go
index d4c7c95..987bae2 100644
--- a/internal/lsp/source/identifier.go
+++ b/internal/lsp/source/identifier.go
@@ -79,19 +79,19 @@
 	if err != nil {
 		return nil, err
 	}
-	return findIdentifier(snapshot, pkg, file, rng.Start)
+	return findIdentifier(ctx, snapshot, pkg, file, rng.Start)
 }
 
 var ErrNoIdentFound = errors.New("no identifier found")
 
-func findIdentifier(snapshot Snapshot, pkg Package, file *ast.File, pos token.Pos) (*IdentifierInfo, error) {
-	if result, err := identifier(snapshot, pkg, file, pos); err != nil || result != nil {
+func findIdentifier(ctx context.Context, snapshot Snapshot, pkg Package, file *ast.File, pos token.Pos) (*IdentifierInfo, error) {
+	if result, err := identifier(ctx, snapshot, pkg, file, pos); err != nil || result != nil {
 		return result, err
 	}
 	// If the position is not an identifier but immediately follows
 	// an identifier or selector period (as is common when
 	// requesting a completion), use the path to the preceding node.
-	ident, err := identifier(snapshot, pkg, file, pos-1)
+	ident, err := identifier(ctx, snapshot, pkg, file, pos-1)
 	if ident == nil && err == nil {
 		err = ErrNoIdentFound
 	}
@@ -99,7 +99,7 @@
 }
 
 // identifier checks a single position for a potential identifier.
-func identifier(s Snapshot, pkg Package, file *ast.File, pos token.Pos) (*IdentifierInfo, error) {
+func identifier(ctx context.Context, s Snapshot, pkg Package, file *ast.File, pos token.Pos) (*IdentifierInfo, error) {
 	var err error
 
 	// Handle import specs separately, as there is no formal position for a package declaration.
@@ -153,7 +153,7 @@
 
 	// Handle builtins separately.
 	if result.Declaration.obj.Parent() == types.Universe {
-		astObj, err := view.LookupBuiltin(result.Name)
+		astObj, err := view.LookupBuiltin(ctx, result.Name)
 		if err != nil {
 			return nil, err
 		}
diff --git a/internal/lsp/source/signature_help.go b/internal/lsp/source/signature_help.go
index ac7141b..bb6a83f 100644
--- a/internal/lsp/source/signature_help.go
+++ b/internal/lsp/source/signature_help.go
@@ -101,7 +101,7 @@
 	}
 
 	qf := qualifier(file, pkg.GetTypes(), pkg.GetTypesInfo())
-	params := formatParams(snapshot, pkg, sig, qf)
+	params := formatParams(ctx, snapshot, pkg, sig, qf)
 	results, writeResultParens := formatResults(sig.Results(), qf)
 	activeParam := activeParameter(callExpr, sig.Params().Len(), sig.Variadic(), rng.Start)
 
@@ -136,7 +136,7 @@
 }
 
 func builtinSignature(ctx context.Context, v View, callExpr *ast.CallExpr, name string, pos token.Pos) (*SignatureInformation, error) {
-	astObj, err := v.LookupBuiltin(name)
+	astObj, err := v.LookupBuiltin(ctx, name)
 	if err != nil {
 		return nil, err
 	}
diff --git a/internal/lsp/source/util.go b/internal/lsp/source/util.go
index 9d729ec..7039fb8 100644
--- a/internal/lsp/source/util.go
+++ b/internal/lsp/source/util.go
@@ -488,11 +488,11 @@
 	return false
 }
 
-func formatParams(s Snapshot, pkg Package, sig *types.Signature, qf types.Qualifier) []string {
+func formatParams(ctx context.Context, s Snapshot, pkg Package, sig *types.Signature, qf types.Qualifier) []string {
 	params := make([]string, 0, sig.Params().Len())
 	for i := 0; i < sig.Params().Len(); i++ {
 		el := sig.Params().At(i)
-		typ, err := formatFieldType(s, pkg, el, qf)
+		typ, err := formatFieldType(ctx, s, pkg, el, qf)
 		if err != nil {
 			typ = types.TypeString(el.Type(), qf)
 		}
@@ -511,12 +511,12 @@
 	return params
 }
 
-func formatFieldType(s Snapshot, srcpkg Package, obj types.Object, qf types.Qualifier) (string, error) {
+func formatFieldType(ctx context.Context, s Snapshot, srcpkg Package, obj types.Object, qf types.Qualifier) (string, error) {
 	file, pkg, err := findPosInPackage(s.View(), srcpkg, obj.Pos())
 	if err != nil {
 		return "", err
 	}
-	ident, err := findIdentifier(s, pkg, file, obj.Pos())
+	ident, err := findIdentifier(ctx, s, pkg, file, obj.Pos())
 	if err != nil {
 		return "", err
 	}
diff --git a/internal/lsp/source/view.go b/internal/lsp/source/view.go
index e8da7bc..729ed5e 100644
--- a/internal/lsp/source/view.go
+++ b/internal/lsp/source/view.go
@@ -93,7 +93,7 @@
 	Folder() span.URI
 
 	// LookupBuiltin returns the go/ast.Object for the given name in the builtin package.
-	LookupBuiltin(name string) (*ast.Object, error)
+	LookupBuiltin(ctx context.Context, name string) (*ast.Object, error)
 
 	// BackgroundContext returns a context used for all background processing
 	// on behalf of this view.