1
0
mirror of https://github.com/golang/go synced 2024-11-18 11:04:42 -07:00

internal/lsp: use one context throughout completion

I originally made this change to see if it would help with the timeouts.
Based on the TryBot results, it doesn't -- but I still think it's more
correct to have the contexts this way. It was my mistake to put the
context on the completer in the first place, I think.

Change-Id: Ib77c8f0ac0b0d0922b82db4120820fb96cb664f4
Reviewed-on: https://go-review.googlesource.com/c/tools/+/227303
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
This commit is contained in:
Rebecca Stambler 2020-04-06 01:18:15 -04:00
parent 7db14c95bf
commit ee2abff5cf
6 changed files with 93 additions and 92 deletions

View File

@ -136,9 +136,6 @@ type completer struct {
qf types.Qualifier
opts *completionOptions
// ctx is the context associated with this completion request.
ctx context.Context
// filename is the name of the file associated with this completion request.
filename string
@ -247,13 +244,6 @@ func (p Selection) Suffix() string {
return p.content[p.cursor-p.spanRange.Start:]
}
func (c *completer) deepCompletionContext() (context.Context, context.CancelFunc) {
if c.opts.budget == 0 {
return context.WithCancel(c.ctx)
}
return context.WithDeadline(c.ctx, c.startTime.Add(c.opts.budget))
}
func (c *completer) setSurrounding(ident *ast.Ident) {
if c.surrounding != nil {
return
@ -292,7 +282,7 @@ func (c *completer) getSurrounding() *Selection {
// found adds a candidate completion. We will also search through the object's
// members for more candidates.
func (c *completer) found(cand candidate) {
func (c *completer) found(ctx context.Context, cand candidate) {
obj := cand.obj
if obj.Pkg() != nil && obj.Pkg() != c.pkg.GetTypes() && !obj.Exported() {
@ -341,7 +331,7 @@ func (c *completer) found(cand candidate) {
// We only care about named types (i.e. don't want builtin types).
if _, isNamed := obj.Type().(*types.Named); isNamed {
c.literal(obj.Type(), cand.imp)
c.literal(ctx, obj.Type(), cand.imp)
}
}
@ -370,13 +360,13 @@ func (c *completer) found(cand candidate) {
// Avoid calling c.item() for deep candidates that wouldn't be in the top
// MaxDeepCompletions anyway.
if !c.inDeepCompletion() || c.deepState.isHighScore(cand.score) {
if item, err := c.item(cand); err == nil {
if item, err := c.item(ctx, cand); err == nil {
c.items = append(c.items, item)
}
}
}
c.deepSearch(cand)
c.deepSearch(ctx, cand)
}
// candidate represents a completion candidate.
@ -482,7 +472,6 @@ func Completion(ctx context.Context, snapshot Snapshot, fh FileHandle, protoPos
pkg: pkg,
snapshot: snapshot,
qf: qualifier(file, pkg.GetTypes(), pkg.GetTypesInfo()),
ctx: ctx,
filename: fh.Identity().URI.Filename(),
file: file,
path: path,
@ -512,32 +501,40 @@ func Completion(ctx context.Context, snapshot Snapshot, fh FileHandle, protoPos
c.deepState.maxDepth = -1
}
var cancel context.CancelFunc
if c.opts.budget == 0 {
ctx, cancel = context.WithCancel(ctx)
} else {
ctx, cancel = context.WithDeadline(ctx, c.startTime.Add(c.opts.budget))
}
defer cancel()
if surrounding := c.containingIdent(src); surrounding != nil {
c.setSurrounding(surrounding)
}
c.inference = expectedCandidate(c)
c.inference = expectedCandidate(ctx, c)
defer c.sortItems()
// If we're inside a comment return comment completions
for _, comment := range file.Comments {
if comment.Pos() < rng.Start && rng.Start <= comment.End() {
c.populateCommentCompletions(comment)
c.populateCommentCompletions(ctx, comment)
return c.items, c.getSurrounding(), nil
}
}
// Struct literals are handled entirely separately.
if c.wantStructFieldCompletions() {
if err := c.structLiteralFieldName(); err != nil {
if err := c.structLiteralFieldName(ctx); err != nil {
return nil, nil, err
}
return c.items, c.getSurrounding(), nil
}
if lt := c.wantLabelCompletion(); lt != labelNone {
c.labels(lt)
c.labels(ctx, lt)
return c.items, c.getSurrounding(), nil
}
@ -555,7 +552,7 @@ func Completion(ctx context.Context, snapshot Snapshot, fh FileHandle, protoPos
case *ast.Ident:
// Is this the Sel part of a selector?
if sel, ok := path[1].(*ast.SelectorExpr); ok && sel.Sel == n {
if err := c.selector(sel); err != nil {
if err := c.selector(ctx, sel); err != nil {
return nil, nil, err
}
return c.items, c.getSurrounding(), nil
@ -573,19 +570,19 @@ func Completion(ctx context.Context, snapshot Snapshot, fh FileHandle, protoPos
return nil, nil, ErrIsDefinition{objStr: objStr}
}
}
if err := c.lexical(); err != nil {
if err := c.lexical(ctx); err != nil {
return nil, nil, err
}
// The function name hasn't been typed yet, but the parens are there:
// recv.‸(arg)
case *ast.TypeAssertExpr:
// Create a fake selector expression.
if err := c.selector(&ast.SelectorExpr{X: n.X}); err != nil {
if err := c.selector(ctx, &ast.SelectorExpr{X: n.X}); err != nil {
return nil, nil, err
}
case *ast.SelectorExpr:
if err := c.selector(n); err != nil {
if err := c.selector(ctx, n); err != nil {
return nil, nil, err
}
@ -595,7 +592,7 @@ func Completion(ctx context.Context, snapshot Snapshot, fh FileHandle, protoPos
default:
// fallback to lexical completions
if err := c.lexical(); err != nil {
if err := c.lexical(ctx); err != nil {
return nil, nil, err
}
}
@ -687,7 +684,7 @@ func (c *completer) emptySwitchStmt() bool {
// populateCommentCompletions yields completions for an exported
// variable immediately preceding comment.
func (c *completer) populateCommentCompletions(comment *ast.CommentGroup) {
func (c *completer) populateCommentCompletions(ctx context.Context, comment *ast.CommentGroup) {
// Using the comment position find the line after
fset := c.snapshot.View().Session().Cache().FileSet()
@ -720,7 +717,7 @@ func (c *completer) populateCommentCompletions(comment *ast.CommentGroup) {
}
exportedVar := c.pkg.GetTypesInfo().ObjectOf(name)
c.found(candidate{obj: exportedVar, score: stdScore})
c.found(ctx, candidate{obj: exportedVar, score: stdScore})
}
}
}
@ -748,11 +745,11 @@ const (
)
// selector finds completions for the specified selector expression.
func (c *completer) selector(sel *ast.SelectorExpr) error {
func (c *completer) selector(ctx context.Context, sel *ast.SelectorExpr) error {
// Is sel a qualified identifier?
if id, ok := sel.X.(*ast.Ident); ok {
if pkgName, ok := c.pkg.GetTypesInfo().Uses[id].(*types.PkgName); ok {
c.packageMembers(pkgName.Imported(), stdScore, nil)
c.packageMembers(ctx, pkgName.Imported(), stdScore, nil)
return nil
}
}
@ -760,21 +757,21 @@ func (c *completer) selector(sel *ast.SelectorExpr) error {
// Invariant: sel is a true selector.
tv, ok := c.pkg.GetTypesInfo().Types[sel.X]
if ok {
return c.methodsAndFields(tv.Type, tv.Addressable(), nil)
return c.methodsAndFields(ctx, tv.Type, tv.Addressable(), nil)
}
// Try unimported packages.
if id, ok := sel.X.(*ast.Ident); ok && c.opts.unimported {
if err := c.unimportedMembers(id); err != nil {
if err := c.unimportedMembers(ctx, id); err != nil {
return err
}
}
return nil
}
func (c *completer) unimportedMembers(id *ast.Ident) error {
func (c *completer) unimportedMembers(ctx context.Context, id *ast.Ident) error {
// Try loaded packages first. They're relevant, fast, and fully typed.
known, err := c.snapshot.CachedImportPaths(c.ctx)
known, err := c.snapshot.CachedImportPaths(ctx)
if err != nil {
return err
}
@ -789,8 +786,8 @@ func (c *completer) unimportedMembers(id *ast.Ident) error {
var relevances map[string]int
if len(paths) != 0 {
c.snapshot.View().RunProcessEnvFunc(c.ctx, func(opts *imports.Options) error {
relevances = imports.ScoreImportPaths(c.ctx, opts.Env, paths)
c.snapshot.View().RunProcessEnvFunc(ctx, func(opts *imports.Options) error {
relevances = imports.ScoreImportPaths(ctx, opts.Env, paths)
return nil
})
}
@ -807,14 +804,15 @@ func (c *completer) unimportedMembers(id *ast.Ident) error {
if imports.ImportPathToAssumedName(path) != pkg.GetTypes().Name() {
imp.name = pkg.GetTypes().Name()
}
c.packageMembers(pkg.GetTypes(), stdScore+.01*float64(relevance), imp)
c.packageMembers(ctx, pkg.GetTypes(), stdScore+.01*float64(relevance), imp)
if len(c.items) >= unimportedMemberTarget {
return nil
}
}
ctx, cancel := c.deepCompletionContext()
ctx, cancel := context.WithCancel(ctx)
defer cancel()
var mu sync.Mutex
add := func(pkgExport imports.PackageExport) {
mu.Lock()
@ -827,7 +825,7 @@ func (c *completer) unimportedMembers(id *ast.Ident) error {
pkg := types.NewPackage(pkgExport.Fix.StmtInfo.ImportPath, pkgExport.Fix.IdentName)
for _, export := range pkgExport.Exports {
score := stdScore + 0.01*float64(pkgExport.Fix.Relevance)
c.found(candidate{
c.found(ctx, candidate{
obj: types.NewVar(0, pkg, export, nil),
score: score,
imp: &importInfo{
@ -845,11 +843,11 @@ func (c *completer) unimportedMembers(id *ast.Ident) error {
})
}
func (c *completer) packageMembers(pkg *types.Package, score float64, imp *importInfo) {
func (c *completer) packageMembers(ctx context.Context, pkg *types.Package, score float64, imp *importInfo) {
scope := pkg.Scope()
for _, name := range scope.Names() {
obj := scope.Lookup(name)
c.found(candidate{
c.found(ctx, candidate{
obj: obj,
score: score,
imp: imp,
@ -858,7 +856,7 @@ func (c *completer) packageMembers(pkg *types.Package, score float64, imp *impor
}
}
func (c *completer) methodsAndFields(typ types.Type, addressable bool, imp *importInfo) error {
func (c *completer) methodsAndFields(ctx context.Context, typ types.Type, addressable bool, imp *importInfo) error {
mset := c.methodSetCache[methodSetKey{typ, addressable}]
if mset == nil {
if addressable && !types.IsInterface(typ) && !isPointer(typ) {
@ -872,7 +870,7 @@ func (c *completer) methodsAndFields(typ types.Type, addressable bool, imp *impo
}
for i := 0; i < mset.Len(); i++ {
c.found(candidate{
c.found(ctx, candidate{
obj: mset.At(i).Obj(),
score: stdScore,
imp: imp,
@ -882,7 +880,7 @@ func (c *completer) methodsAndFields(typ types.Type, addressable bool, imp *impo
// Add fields of T.
eachField(typ, func(v *types.Var) {
c.found(candidate{
c.found(ctx, candidate{
obj: v,
score: stdScore - 0.01,
imp: imp,
@ -894,7 +892,7 @@ func (c *completer) methodsAndFields(typ types.Type, addressable bool, imp *impo
}
// lexical finds completions in the lexical environment.
func (c *completer) lexical() error {
func (c *completer) lexical(ctx context.Context) error {
var scopes []*types.Scope // scopes[i], where i<len(path), is the possibly nil Scope of path[i].
for _, n := range c.path {
// Include *FuncType scope if pos is inside the function body.
@ -978,7 +976,7 @@ func (c *completer) lexical() error {
// If we haven't already added a candidate for an object with this name.
if _, ok := seen[obj.Name()]; !ok {
seen[obj.Name()] = struct{}{}
c.found(candidate{
c.found(ctx, candidate{
obj: obj,
score: score,
addressable: isVar(obj),
@ -1007,7 +1005,7 @@ func (c *completer) lexical() error {
if imports.ImportPathToAssumedName(pkg.Path()) != pkg.Name() {
imp.name = pkg.Name()
}
c.found(candidate{
c.found(ctx, candidate{
obj: obj,
score: stdScore,
imp: imp,
@ -1018,7 +1016,7 @@ func (c *completer) lexical() error {
}
if c.opts.unimported {
if err := c.unimportedPackages(seen); err != nil {
if err := c.unimportedPackages(ctx, seen); err != nil {
return err
}
}
@ -1036,7 +1034,7 @@ func (c *completer) lexical() error {
// our expected type is "[]int", this will add a candidate of
// "[]int{}".
if _, named := t.(*types.Named); !named {
c.literal(t, nil)
c.literal(ctx, t, nil)
}
}
@ -1046,17 +1044,14 @@ func (c *completer) lexical() error {
return nil
}
func (c *completer) unimportedPackages(seen map[string]struct{}) error {
ctx, cancel := c.deepCompletionContext()
defer cancel()
prefix := ""
func (c *completer) unimportedPackages(ctx context.Context, seen map[string]struct{}) error {
var prefix string
if c.surrounding != nil {
prefix = c.surrounding.Prefix()
}
initialItemCount := len(c.items)
known, err := c.snapshot.CachedImportPaths(c.ctx)
known, err := c.snapshot.CachedImportPaths(ctx)
if err != nil {
return err
}
@ -1071,7 +1066,7 @@ func (c *completer) unimportedPackages(seen map[string]struct{}) error {
var relevances map[string]int
if len(paths) != 0 {
c.snapshot.View().RunProcessEnvFunc(ctx, func(opts *imports.Options) error {
relevances = imports.ScoreImportPaths(c.ctx, opts.Env, paths)
relevances = imports.ScoreImportPaths(ctx, opts.Env, paths)
return nil
})
}
@ -1086,7 +1081,7 @@ func (c *completer) unimportedPackages(seen map[string]struct{}) error {
imp.name = pkg.GetTypes().Name()
}
score := 0.01 * float64(relevance)
c.found(candidate{
c.found(ctx, candidate{
obj: types.NewPkgName(0, nil, pkg.GetTypes().Name(), pkg.GetTypes()),
score: score,
imp: imp,
@ -1096,6 +1091,9 @@ func (c *completer) unimportedPackages(seen map[string]struct{}) error {
}
}
ctx, cancel := context.WithCancel(ctx)
defer cancel()
var mu sync.Mutex
add := func(pkg imports.ImportFix) {
mu.Lock()
@ -1115,7 +1113,7 @@ func (c *completer) unimportedPackages(seen map[string]struct{}) error {
// multiple packages of the same name as completion suggestions, since
// only one will be chosen.
obj := types.NewPkgName(0, nil, pkg.IdentName, types.NewPackage(pkg.StmtInfo.ImportPath, pkg.IdentName))
c.found(candidate{
c.found(ctx, candidate{
obj: obj,
score: score,
imp: &importInfo{
@ -1163,7 +1161,7 @@ func (c *completer) inConstDecl() bool {
}
// structLiteralFieldName finds completions for struct field names inside a struct literal.
func (c *completer) structLiteralFieldName() error {
func (c *completer) structLiteralFieldName(ctx context.Context) error {
clInfo := c.enclosingCompositeLiteral
// Mark fields of the composite literal that have already been set,
@ -1190,7 +1188,7 @@ func (c *completer) structLiteralFieldName() error {
for i := 0; i < t.NumFields(); i++ {
field := t.Field(i)
if !addedFields[field] {
c.found(candidate{
c.found(ctx, candidate{
obj: field,
score: highScore,
})
@ -1200,10 +1198,10 @@ func (c *completer) structLiteralFieldName() error {
// Add lexical completions if we aren't certain we are in the key part of a
// key-value pair.
if clInfo.maybeInFieldName {
return c.lexical()
return c.lexical(ctx)
}
default:
return c.lexical()
return c.lexical(ctx)
}
return nil
@ -1468,7 +1466,7 @@ type typeNameInference struct {
// expectedCandidate returns information about the expected candidate
// for an expression at the query position.
func expectedCandidate(c *completer) (inf candidateInference) {
func expectedCandidate(ctx context.Context, c *completer) (inf candidateInference) {
inf.typeName = expectTypeName(c)
if c.enclosingCompositeLiteral != nil {
@ -1592,7 +1590,7 @@ Nodes:
// inferred type from its parent node.
defer func() {
inf = c.builtinArgType(obj, node, inf)
inf.objKind = c.builtinArgKind(obj, node)
inf.objKind = c.builtinArgKind(ctx, obj, node)
}()
// The expected type of builtin arguments like append() is

View File

@ -5,6 +5,7 @@
package source
import (
"context"
"go/ast"
"go/types"
)
@ -12,8 +13,8 @@ import (
// builtinArgKind determines the expected object kind for a builtin
// 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(c.ctx, obj.Name())
func (c *completer) builtinArgKind(ctx context.Context, obj types.Object, call *ast.CallExpr) objKind {
astObj, err := c.snapshot.View().LookupBuiltin(ctx, obj.Name())
if err != nil {
return 0
}

View File

@ -23,12 +23,12 @@ import (
)
// formatCompletion creates a completion item for a given candidate.
func (c *completer) item(cand candidate) (CompletionItem, error) {
func (c *completer) item(ctx context.Context, cand candidate) (CompletionItem, error) {
obj := cand.obj
// Handle builtin types separately.
if obj.Parent() == types.Universe {
return c.formatBuiltin(cand), nil
return c.formatBuiltin(ctx, cand), nil
}
var (
@ -46,7 +46,7 @@ func (c *completer) item(cand candidate) (CompletionItem, error) {
// expandFuncCall mutates the completion label, detail, and snippet
// to that of an invocation of sig.
expandFuncCall := func(sig *types.Signature) {
params := formatParams(c.ctx, c.snapshot, c.pkg, sig, c.qf)
params := formatParams(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)
@ -67,7 +67,7 @@ func (c *completer) item(cand candidate) (CompletionItem, error) {
detail = "struct{...}" // for anonymous structs
} else if obj.IsField() {
var err error
detail, err = formatFieldType(c.ctx, c.snapshot, c.pkg, obj)
detail, err = formatFieldType(ctx, c.snapshot, c.pkg, obj)
if err != nil {
detail = types.TypeString(obj.Type(), c.qf)
}
@ -115,7 +115,7 @@ func (c *completer) item(cand candidate) (CompletionItem, error) {
// If this candidate needs an additional import statement,
// add the additional text edits needed.
if cand.imp != nil {
addlEdits, err := c.importEdits(cand.imp)
addlEdits, err := c.importEdits(ctx, cand.imp)
if err != nil {
return CompletionItem{}, err
}
@ -144,10 +144,9 @@ func (c *completer) item(cand candidate) (CompletionItem, error) {
if sel := enclosingSelector(c.path, c.pos); sel != nil {
edits, err := prependEdit(c.snapshot.View().Session().Cache().FileSet(), c.mapper, sel, prefixOp)
if err != nil {
event.Error(c.ctx, "error generating prefix edit", err)
} else {
protocolEdits = append(protocolEdits, edits...)
return CompletionItem{}, err
}
protocolEdits = append(protocolEdits, edits...)
} else {
// If there is no selector, just stick the prefix at the start.
insert = prefixOp + insert
@ -190,13 +189,13 @@ func (c *completer) item(cand candidate) (CompletionItem, error) {
if err != nil {
return item, nil
}
ident, err := findIdentifier(c.ctx, c.snapshot, pkg, file, obj.Pos())
ident, err := findIdentifier(ctx, c.snapshot, pkg, file, obj.Pos())
if err != nil {
return item, nil
}
hover, err := ident.Hover(c.ctx)
hover, err := ident.Hover(ctx)
if err != nil {
event.Error(c.ctx, "failed to find Hover", err, tag.URI.Of(uri))
event.Error(ctx, "failed to find Hover", err, tag.URI.Of(uri))
return item, nil
}
item.Documentation = hover.Synopsis
@ -207,7 +206,7 @@ func (c *completer) item(cand candidate) (CompletionItem, error) {
}
// importEdits produces the text edits necessary to add the given import to the current file.
func (c *completer) importEdits(imp *importInfo) ([]protocol.TextEdit, error) {
func (c *completer) importEdits(ctx context.Context, imp *importInfo) ([]protocol.TextEdit, error) {
if imp == nil {
return nil, nil
}
@ -223,7 +222,7 @@ func (c *completer) importEdits(imp *importInfo) ([]protocol.TextEdit, error) {
return nil, errors.Errorf("building import completion for %v: no ParseGoHandle for %s", imp.importPath, c.filename)
}
return computeOneImportFixEdits(c.ctx, c.snapshot.View(), ph, &imports.ImportFix{
return computeOneImportFixEdits(ctx, c.snapshot.View(), ph, &imports.ImportFix{
StmtInfo: imports.ImportInfo{
ImportPath: imp.importPath,
Name: imp.name,
@ -233,7 +232,7 @@ func (c *completer) importEdits(imp *importInfo) ([]protocol.TextEdit, error) {
})
}
func (c *completer) formatBuiltin(cand candidate) CompletionItem {
func (c *completer) formatBuiltin(ctx context.Context, cand candidate) CompletionItem {
obj := cand.obj
item := CompletionItem{
Label: obj.Name(),
@ -245,17 +244,17 @@ func (c *completer) formatBuiltin(cand candidate) CompletionItem {
item.Kind = protocol.ConstantCompletion
case *types.Builtin:
item.Kind = protocol.FunctionCompletion
astObj, err := c.snapshot.View().LookupBuiltin(c.ctx, obj.Name())
astObj, err := c.snapshot.View().LookupBuiltin(ctx, obj.Name())
if err != nil {
event.Error(c.ctx, "no builtin package", err)
event.Error(ctx, "no builtin package", err)
break
}
decl, ok := astObj.Decl.(*ast.FuncDecl)
if !ok {
break
}
params, _ := formatFieldList(c.ctx, c.snapshot.View(), decl.Type.Params)
results, writeResultParens := formatFieldList(c.ctx, c.snapshot.View(), decl.Type.Results)
params, _ := formatFieldList(ctx, c.snapshot.View(), decl.Type.Params)
results, writeResultParens := formatFieldList(ctx, c.snapshot.View(), decl.Type.Results)
item.Label = obj.Name()
item.Detail = "func" + formatFunction(params, results, writeResultParens)
item.snippet = c.functionCallSnippet(obj.Name(), params)

View File

@ -5,6 +5,7 @@
package source
import (
"context"
"go/ast"
"go/token"
"math"
@ -49,7 +50,7 @@ func takesLabel(n ast.Node) labelType {
// labels adds completion items for labels defined in the enclosing
// function.
func (c *completer) labels(lt labelType) {
func (c *completer) labels(ctx context.Context, lt labelType) {
if c.enclosingFunc == nil {
return
}
@ -57,7 +58,7 @@ func (c *completer) labels(lt labelType) {
addLabel := func(score float64, l *ast.LabeledStmt) {
labelObj := c.pkg.GetTypesInfo().ObjectOf(l.Label)
if labelObj != nil {
c.found(candidate{obj: labelObj, score: score})
c.found(ctx, candidate{obj: labelObj, score: score})
}
}

View File

@ -5,6 +5,7 @@
package source
import (
"context"
"go/ast"
"go/token"
"go/types"
@ -19,7 +20,7 @@ import (
// literal generates composite literal, function literal, and make()
// completion items.
func (c *completer) literal(literalType types.Type, imp *importInfo) {
func (c *completer) literal(ctx context.Context, literalType types.Type, imp *importInfo) {
if !c.opts.literal {
return
}
@ -101,9 +102,9 @@ func (c *completer) literal(literalType types.Type, imp *importInfo) {
matchName = types.TypeString(t.Elem(), qf)
}
addlEdits, err := c.importEdits(imp)
addlEdits, err := c.importEdits(ctx, imp)
if err != nil {
event.Error(c.ctx, "error adding import for literal candidate", err)
event.Error(ctx, "error adding import for literal candidate", err)
return
}
@ -116,7 +117,7 @@ func (c *completer) literal(literalType types.Type, imp *importInfo) {
// "foo.&Bar{}".
edits, err := prependEdit(c.snapshot.View().Session().Cache().FileSet(), c.mapper, sel, "&")
if err != nil {
event.Error(c.ctx, "error making edit for literal pointer completion", err)
event.Error(ctx, "error making edit for literal pointer completion", err)
return
}
addlEdits = append(addlEdits, edits...)

View File

@ -5,6 +5,7 @@
package source
import (
"context"
"go/types"
"strings"
"time"
@ -162,7 +163,7 @@ func (c *completer) shouldPrune() bool {
// deepSearch searches through cand's subordinate objects for more
// completion items.
func (c *completer) deepSearch(cand candidate) {
func (c *completer) deepSearch(ctx context.Context, cand candidate) {
if c.deepState.maxDepth == 0 {
return
}
@ -198,7 +199,7 @@ func (c *completer) deepSearch(cand candidate) {
// the deep chain.
c.deepState.push(obj, true)
// The result of a function call is not addressable.
c.methodsAndFields(sig.Results().At(0).Type(), false, cand.imp)
c.methodsAndFields(ctx, sig.Results().At(0).Type(), false, cand.imp)
c.deepState.pop()
}
}
@ -208,9 +209,9 @@ func (c *completer) deepSearch(cand candidate) {
switch obj := obj.(type) {
case *types.PkgName:
c.packageMembers(obj.Imported(), stdScore, cand.imp)
c.packageMembers(ctx, obj.Imported(), stdScore, cand.imp)
default:
c.methodsAndFields(obj.Type(), cand.addressable, cand.imp)
c.methodsAndFields(ctx, obj.Type(), cand.addressable, cand.imp)
}
// Pop the object off our search stack.