internal/lsp: add nil checks for ASTs and token

Fixes golang/go#32120
Updates golang/go#32132

Change-Id: Ib4bb8a4818be7dec468c46b72afc3dd57b35f155
Reviewed-on: https://go-review.googlesource.com/c/tools/+/178158
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Cottrell <iancottrell@google.com>
diff --git a/internal/lsp/link.go b/internal/lsp/link.go
index fd8eb49..155787f 100644
--- a/internal/lsp/link.go
+++ b/internal/lsp/link.go
@@ -20,14 +20,13 @@
 	if err != nil {
 		return nil, err
 	}
-	// find the import block
-	ast := f.GetAST(ctx)
-	if ast == nil {
+	file := f.GetAST(ctx)
+	if file == nil {
 		return nil, fmt.Errorf("no AST for %v", uri)
 	}
-
+	// Add a Godoc link for each imported package.
 	var result []protocol.DocumentLink
-	for _, imp := range ast.Imports {
+	for _, imp := range file.Imports {
 		spn, err := span.NewRange(f.GetFileSet(ctx), imp.Pos(), imp.End()).Span()
 		if err != nil {
 			return nil, err
diff --git a/internal/lsp/source/completion.go b/internal/lsp/source/completion.go
index a95001f..de010b7 100644
--- a/internal/lsp/source/completion.go
+++ b/internal/lsp/source/completion.go
@@ -222,6 +222,9 @@
 // may tolerate imperfect matches as valid completion results, since users may make typos.
 func Completion(ctx context.Context, f GoFile, pos token.Pos) ([]CompletionItem, *Selection, error) {
 	file := f.GetAST(ctx)
+	if file == nil {
+		return nil, nil, fmt.Errorf("no AST for %s", f.URI())
+	}
 	pkg := f.GetPackage(ctx)
 	if pkg == nil || pkg.IsIllTyped() {
 		return nil, nil, fmt.Errorf("package for %s is ill typed", f.URI())
diff --git a/internal/lsp/source/format.go b/internal/lsp/source/format.go
index 682f075..ba85ff5 100644
--- a/internal/lsp/source/format.go
+++ b/internal/lsp/source/format.go
@@ -20,12 +20,15 @@
 
 // Format formats a file with a given range.
 func Format(ctx context.Context, f GoFile, rng span.Range) ([]TextEdit, error) {
+	file := f.GetAST(ctx)
+	if file == nil {
+		return nil, fmt.Errorf("no AST for %s", f.URI())
+	}
 	pkg := f.GetPackage(ctx)
 	if hasParseErrors(pkg.GetErrors()) {
 		return nil, fmt.Errorf("%s has parse errors, not formatting", f.URI())
 	}
-	fAST := f.GetAST(ctx)
-	path, exact := astutil.PathEnclosingInterval(fAST, rng.Start, rng.End)
+	path, exact := astutil.PathEnclosingInterval(file, rng.Start, rng.End)
 	if !exact || len(path) == 0 {
 		return nil, fmt.Errorf("no exact AST node matching the specified range")
 	}
@@ -53,7 +56,11 @@
 
 // Imports formats a file using the goimports tool.
 func Imports(ctx context.Context, f GoFile, rng span.Range) ([]TextEdit, error) {
-	formatted, err := imports.Process(f.GetToken(ctx).Name(), f.GetContent(ctx), nil)
+	tok := f.GetToken(ctx)
+	if tok == nil {
+		return nil, fmt.Errorf("no token file for %s", f.URI())
+	}
+	formatted, err := imports.Process(tok.Name(), f.GetContent(ctx), nil)
 	if err != nil {
 		return nil, err
 	}
diff --git a/internal/lsp/source/highlight.go b/internal/lsp/source/highlight.go
index 8e81139..bf3cb46 100644
--- a/internal/lsp/source/highlight.go
+++ b/internal/lsp/source/highlight.go
@@ -14,9 +14,12 @@
 )
 
 func Highlight(ctx context.Context, f GoFile, pos token.Pos) []span.Span {
-	fAST := f.GetAST(ctx)
+	file := f.GetAST(ctx)
+	if file == nil {
+		return nil
+	}
 	fset := f.GetFileSet(ctx)
-	path, _ := astutil.PathEnclosingInterval(fAST, pos, pos)
+	path, _ := astutil.PathEnclosingInterval(file, pos, pos)
 	if len(path) == 0 {
 		return nil
 	}
diff --git a/internal/lsp/source/identifier.go b/internal/lsp/source/identifier.go
index 4e870af..763494f 100644
--- a/internal/lsp/source/identifier.go
+++ b/internal/lsp/source/identifier.go
@@ -53,19 +53,22 @@
 
 // identifier checks a single position for a potential identifier.
 func identifier(ctx context.Context, v View, f GoFile, pos token.Pos) (*IdentifierInfo, error) {
-	fAST := f.GetAST(ctx)
+	file := f.GetAST(ctx)
+	if file == nil {
+		return nil, fmt.Errorf("no AST for %s", f.URI())
+	}
 	pkg := f.GetPackage(ctx)
 	if pkg == nil || pkg.IsIllTyped() {
 		return nil, fmt.Errorf("package for %s is ill typed", f.URI())
 	}
 
-	path, _ := astutil.PathEnclosingInterval(fAST, pos, pos)
+	path, _ := astutil.PathEnclosingInterval(file, pos, pos)
 	if path == nil {
 		return nil, fmt.Errorf("can't find node enclosing position")
 	}
 
 	// Handle import specs separately, as there is no formal position for a package declaration.
-	if result, err := importSpec(f, fAST, pkg, pos); result != nil || err != nil {
+	if result, err := importSpec(f, file, pkg, pos); result != nil || err != nil {
 		return result, err
 	}
 
diff --git a/internal/lsp/source/signature_help.go b/internal/lsp/source/signature_help.go
index 5a4500a..e5214ec 100644
--- a/internal/lsp/source/signature_help.go
+++ b/internal/lsp/source/signature_help.go
@@ -25,7 +25,10 @@
 }
 
 func SignatureHelp(ctx context.Context, f GoFile, pos token.Pos) (*SignatureInformation, error) {
-	fAST := f.GetAST(ctx)
+	file := f.GetAST(ctx)
+	if file == nil {
+		return nil, fmt.Errorf("no AST for %s", f.URI())
+	}
 	pkg := f.GetPackage(ctx)
 	if pkg == nil || pkg.IsIllTyped() {
 		return nil, fmt.Errorf("package for %s is ill typed", f.URI())
@@ -33,7 +36,7 @@
 
 	// Find a call expression surrounding the query position.
 	var callExpr *ast.CallExpr
-	path, _ := astutil.PathEnclosingInterval(fAST, pos, pos)
+	path, _ := astutil.PathEnclosingInterval(file, pos, pos)
 	if path == nil {
 		return nil, fmt.Errorf("cannot find node enclosing position")
 	}
@@ -74,7 +77,7 @@
 		return nil, fmt.Errorf("cannot find signature for Fun %[1]T (%[1]v)", callExpr.Fun)
 	}
 
-	qf := qualifier(fAST, pkg.GetTypes(), pkg.GetTypesInfo())
+	qf := qualifier(file, pkg.GetTypes(), pkg.GetTypesInfo())
 	params := formatParams(sig.Params(), sig.Variadic(), qf)
 	results, writeResultParens := formatResults(sig.Results(), qf)
 	activeParam := activeParameter(callExpr, sig.Params().Len(), sig.Variadic(), pos)
diff --git a/internal/lsp/source/symbols.go b/internal/lsp/source/symbols.go
index f91f8f4..aba8f814 100644
--- a/internal/lsp/source/symbols.go
+++ b/internal/lsp/source/symbols.go
@@ -43,7 +43,13 @@
 func DocumentSymbols(ctx context.Context, f GoFile) []Symbol {
 	fset := f.GetFileSet(ctx)
 	file := f.GetAST(ctx)
+	if file == nil {
+		return nil
+	}
 	pkg := f.GetPackage(ctx)
+	if pkg == nil || pkg.IsIllTyped() {
+		return nil
+	}
 	info := pkg.GetTypesInfo()
 	q := qualifier(file, pkg.GetTypes(), info)