From 7e7c6e521403f4a79ffde46e1136f2f5e1c17953 Mon Sep 17 00:00:00 2001 From: Rebecca Stambler Date: Mon, 20 May 2019 15:23:02 -0400 Subject: [PATCH] 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 TryBot-Result: Gobot Gobot Reviewed-by: Ian Cottrell --- internal/lsp/link.go | 9 ++++----- internal/lsp/source/completion.go | 3 +++ internal/lsp/source/format.go | 13 ++++++++++--- internal/lsp/source/highlight.go | 7 +++++-- internal/lsp/source/identifier.go | 9 ++++++--- internal/lsp/source/signature_help.go | 9 ++++++--- internal/lsp/source/symbols.go | 6 ++++++ 7 files changed, 40 insertions(+), 16 deletions(-) diff --git a/internal/lsp/link.go b/internal/lsp/link.go index fd8eb49d..155787ff 100644 --- a/internal/lsp/link.go +++ b/internal/lsp/link.go @@ -20,14 +20,13 @@ func (s *Server) documentLink(ctx context.Context, params *protocol.DocumentLink 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 a95001fe..de010b7c 100644 --- a/internal/lsp/source/completion.go +++ b/internal/lsp/source/completion.go @@ -222,6 +222,9 @@ func (c *completer) found(obj types.Object, weight float64) { // 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 682f0756..ba85ff52 100644 --- a/internal/lsp/source/format.go +++ b/internal/lsp/source/format.go @@ -20,12 +20,15 @@ import ( // 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 @@ func hasParseErrors(errors []packages.Error) bool { // 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 8e81139e..bf3cb46f 100644 --- a/internal/lsp/source/highlight.go +++ b/internal/lsp/source/highlight.go @@ -14,9 +14,12 @@ import ( ) 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 4e870af4..763494ff 100644 --- a/internal/lsp/source/identifier.go +++ b/internal/lsp/source/identifier.go @@ -53,19 +53,22 @@ func Identifier(ctx context.Context, v View, f GoFile, pos token.Pos) (*Identifi // 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 5a4500ab..e5214ec2 100644 --- a/internal/lsp/source/signature_help.go +++ b/internal/lsp/source/signature_help.go @@ -25,7 +25,10 @@ type ParameterInformation struct { } 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 @@ func SignatureHelp(ctx context.Context, f GoFile, pos token.Pos) (*SignatureInfo // 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 @@ func SignatureHelp(ctx context.Context, f GoFile, pos token.Pos) (*SignatureInfo 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 f91f8f4d..aba8f814 100644 --- a/internal/lsp/source/symbols.go +++ b/internal/lsp/source/symbols.go @@ -43,7 +43,13 @@ type Symbol struct { 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)