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)