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>
This commit is contained in:
Rebecca Stambler 2019-05-20 15:23:02 -04:00
parent faf83c64e9
commit 7e7c6e5214
7 changed files with 40 additions and 16 deletions

View File

@ -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

View File

@ -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())

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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)

View File

@ -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)