func (c *completer) addCandidate(ctx context.Context, cand *candidate) {
	obj := cand.obj
	if c.matchingCandidate(cand) {
		cand.score *= highScore
		if p := c.penalty(cand); p > 0 {
			cand.score *= (1 - p)
		}
	} else if isTypeName(obj) {
		if _, isNamed := obj.Type().(*types.Named); isNamed {
			c.literal(ctx, obj.Type(), cand.imp)
		}
	}
	if cand.hasMod(invoke) {
		if sig, ok := obj.Type().Underlying().(*types.Signature); ok && sig.Recv() != nil {
			cand.score *= 0.9
		}
	}
	if !obj.Exported() && obj.Parent() != types.Universe {
		cand.score *= 1.1
	}
	if cand.hasMod(index) {
		cand.score *= 0.9
	}
	cand.score -= cand.score * c.deepState.scorePenalty(cand)
	if cand.score < 0 {
		cand.score = 0
	}
	cand.name = deepCandName(cand)
	if item, err := c.item(ctx, *cand); err == nil {
		c.items = append(c.items, item)
	}
}
addCandidate adds a completion candidate to suggestions, without searching
its members for more candidates.
package completion
import (
	"context"
	"go/types"
	"strings"
	"time"
)
const MaxDeepCompletions = 3
type deepCompletionState struct {
	enabled bool
	queueClosed bool
	thisQueue []candidate
	nextQueue []candidate
	highScores [MaxDeepCompletions]float64
	candidateCount int
}
func (s *deepCompletionState) enqueue(cand candidate) {
	s.nextQueue = append(s.nextQueue, cand)
}
func (s *deepCompletionState) dequeue() *candidate {
	var cand *candidate
	cand, s.thisQueue = &s.thisQueue[len(s.thisQueue)-1], s.thisQueue[:len(s.thisQueue)-1]
	return cand
}
func (s *deepCompletionState) scorePenalty(cand *candidate) float64 {
	var deepPenalty float64
	for _, dc := range cand.path {
		deepPenalty++
		if !dc.Exported() {
			deepPenalty -= 0.1
		}
		if _, isSig := dc.Type().Underlying().(*types.Signature); isSig {
			deepPenalty += 0.1
		}
	}
	return deepPenalty / 10
}
func (s *deepCompletionState) isHighScore(score float64) bool {
	for i, deepScore := range s.highScores {
		if score <= deepScore {
			continue
		}
		if deepScore != 0 && i != len(s.highScores)-1 {
			copy(s.highScores[i+1:], s.highScores[i:])
		}
		s.highScores[i] = score
		return true
	}
	return false
}
func (s *deepCompletionState) newPath(cand candidate, obj types.Object) []types.Object {
	path := make([]types.Object, len(cand.path)+1)
	copy(path, cand.path)
	path[len(path)-1] = obj
	return path
}
func (c *completer) deepSearch(ctx context.Context) {
	defer func() {
		c.deepState.thisQueue = c.deepState.thisQueue[:0]
		c.deepState.nextQueue = c.deepState.nextQueue[:0]
	}()
	for len(c.deepState.nextQueue) > 0 {
		c.deepState.thisQueue, c.deepState.nextQueue = c.deepState.nextQueue, c.deepState.thisQueue[:0]
	outer:
		for _, cand := range c.deepState.thisQueue {
			obj := cand.obj
			if obj == nil {
				continue
			}
			if len(cand.path) == 0 {
				if c.seen[obj] {
					continue
				}
				c.seen[obj] = true
			}
			if !c.completionContext.packageCompletion &&
				obj.Pkg() != nil && obj.Pkg() != c.pkg.GetTypes() && !obj.Exported() {
				continue
			}
			if c.wantTypeName() && obj.Type() != nil && !isTypeName(obj) && !isPkgName(obj) {
				continue
			}
			for _, seenObj := range cand.path {
				if seenObj == obj {
					continue outer
				}
			}
			c.addCandidate(ctx, &cand)
			c.deepState.candidateCount++
			if c.opts.budget > 0 && c.deepState.candidateCount%100 == 0 {
				spent := float64(time.Since(c.startTime)) / float64(c.opts.budget)
				select {
				case <-ctx.Done():
					return
				default:
					if !c.deepState.queueClosed && spent >= 0.85 {
						c.deepState.queueClosed = true
					}
				}
			}
			if !c.deepState.enabled || c.deepState.queueClosed {
				continue
			}
			if isTypeName(obj) {
				continue
			}
			if obj.Type() == nil {
				continue
			}
			if v, ok := obj.(*types.Var); ok && v.Embedded() {
				continue
			}
			if sig, ok := obj.Type().Underlying().(*types.Signature); ok {
				if sig.Params().Len() == 0 && sig.Results().Len() == 1 {
					path := c.deepState.newPath(cand, obj)
					c.methodsAndFields(sig.Results().At(0).Type(), false, cand.imp, func(newCand candidate) {
						newCand.pathInvokeMask = cand.pathInvokeMask | (1 << uint64(len(cand.path)))
						newCand.path = path
						c.deepState.enqueue(newCand)
					})
				}
			}
			path := c.deepState.newPath(cand, obj)
			switch obj := obj.(type) {
			case *types.PkgName:
				c.packageMembers(obj.Imported(), stdScore, cand.imp, func(newCand candidate) {
					newCand.pathInvokeMask = cand.pathInvokeMask
					newCand.path = path
					c.deepState.enqueue(newCand)
				})
			default:
				c.methodsAndFields(obj.Type(), cand.addressable, cand.imp, func(newCand candidate) {
					newCand.pathInvokeMask = cand.pathInvokeMask
					newCand.path = path
					c.deepState.enqueue(newCand)
				})
			}
		}
	}
}