Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201105173854-bc9fc8d8c4bc / internal / lsp / source / completion / completion.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201105173854-bc9fc8d8c4bc/internal/lsp/source/completion/completion.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201105173854-bc9fc8d8c4bc/internal/lsp/source/completion/completion.go
new file mode 100644 (file)
index 0000000..78dac5b
--- /dev/null
@@ -0,0 +1,2773 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package completion provides core functionality for code completion in Go
+// editors and tools.
+package completion
+
+import (
+       "context"
+       "fmt"
+       "go/ast"
+       "go/constant"
+       "go/scanner"
+       "go/token"
+       "go/types"
+       "math"
+       "sort"
+       "strconv"
+       "strings"
+       "sync"
+       "time"
+       "unicode"
+
+       "golang.org/x/tools/go/ast/astutil"
+       "golang.org/x/tools/internal/event"
+       "golang.org/x/tools/internal/imports"
+       "golang.org/x/tools/internal/lsp/fuzzy"
+       "golang.org/x/tools/internal/lsp/protocol"
+       "golang.org/x/tools/internal/lsp/snippet"
+       "golang.org/x/tools/internal/lsp/source"
+       errors "golang.org/x/xerrors"
+)
+
+type CompletionItem struct {
+       // Label is the primary text the user sees for this completion item.
+       Label string
+
+       // Detail is supplemental information to present to the user.
+       // This often contains the type or return type of the completion item.
+       Detail string
+
+       // InsertText is the text to insert if this item is selected.
+       // Any of the prefix that has already been typed is not trimmed.
+       // The insert text does not contain snippets.
+       InsertText string
+
+       Kind protocol.CompletionItemKind
+
+       // An optional array of additional TextEdits that are applied when
+       // selecting this completion.
+       //
+       // Additional text edits should be used to change text unrelated to the current cursor position
+       // (for example adding an import statement at the top of the file if the completion item will
+       // insert an unqualified type).
+       AdditionalTextEdits []protocol.TextEdit
+
+       // Depth is how many levels were searched to find this completion.
+       // For example when completing "foo<>", "fooBar" is depth 0, and
+       // "fooBar.Baz" is depth 1.
+       Depth int
+
+       // Score is the internal relevance score.
+       // A higher score indicates that this completion item is more relevant.
+       Score float64
+
+       // snippet is the LSP snippet for the completion item. The LSP
+       // specification contains details about LSP snippets. For example, a
+       // snippet for a function with the following signature:
+       //
+       //     func foo(a, b, c int)
+       //
+       // would be:
+       //
+       //     foo(${1:a int}, ${2: b int}, ${3: c int})
+       //
+       // If Placeholders is false in the CompletionOptions, the above
+       // snippet would instead be:
+       //
+       //     foo(${1:})
+       snippet *snippet.Builder
+
+       // Documentation is the documentation for the completion item.
+       Documentation string
+
+       // obj is the object from which this candidate was derived, if any.
+       // obj is for internal use only.
+       obj types.Object
+}
+
+// completionOptions holds completion specific configuration.
+type completionOptions struct {
+       unimported        bool
+       documentation     bool
+       fullDocumentation bool
+       placeholders      bool
+       literal           bool
+       matcher           source.Matcher
+       budget            time.Duration
+}
+
+// Snippet is a convenience returns the snippet if available, otherwise
+// the InsertText.
+// used for an item, depending on if the callee wants placeholders or not.
+func (i *CompletionItem) Snippet() string {
+       if i.snippet != nil {
+               return i.snippet.String()
+       }
+       return i.InsertText
+}
+
+// Scoring constants are used for weighting the relevance of different candidates.
+const (
+       // stdScore is the base score for all completion items.
+       stdScore float64 = 1.0
+
+       // highScore indicates a very relevant completion item.
+       highScore float64 = 10.0
+
+       // lowScore indicates an irrelevant or not useful completion item.
+       lowScore float64 = 0.01
+)
+
+// matcher matches a candidate's label against the user input. The
+// returned score reflects the quality of the match. A score of zero
+// indicates no match, and a score of one means a perfect match.
+type matcher interface {
+       Score(candidateLabel string) (score float32)
+}
+
+// prefixMatcher implements case sensitive prefix matching.
+type prefixMatcher string
+
+func (pm prefixMatcher) Score(candidateLabel string) float32 {
+       if strings.HasPrefix(candidateLabel, string(pm)) {
+               return 1
+       }
+       return -1
+}
+
+// insensitivePrefixMatcher implements case insensitive prefix matching.
+type insensitivePrefixMatcher string
+
+func (ipm insensitivePrefixMatcher) Score(candidateLabel string) float32 {
+       if strings.HasPrefix(strings.ToLower(candidateLabel), string(ipm)) {
+               return 1
+       }
+       return -1
+}
+
+// completer contains the necessary information for a single completion request.
+type completer struct {
+       snapshot source.Snapshot
+       pkg      source.Package
+       qf       types.Qualifier
+       opts     *completionOptions
+
+       // completionContext contains information about the trigger for this
+       // completion request.
+       completionContext completionContext
+
+       // fh is a handle to the file associated with this completion request.
+       fh source.FileHandle
+
+       // filename is the name of the file associated with this completion request.
+       filename string
+
+       // file is the AST of the file associated with this completion request.
+       file *ast.File
+
+       // pos is the position at which the request was triggered.
+       pos token.Pos
+
+       // path is the path of AST nodes enclosing the position.
+       path []ast.Node
+
+       // seen is the map that ensures we do not return duplicate results.
+       seen map[types.Object]bool
+
+       // items is the list of completion items returned.
+       items []CompletionItem
+
+       // completionCallbacks is a list of callbacks to collect completions that
+       // require expensive operations. This includes operations where we search
+       // through the entire module cache.
+       completionCallbacks []func(opts *imports.Options) error
+
+       // surrounding describes the identifier surrounding the position.
+       surrounding *Selection
+
+       // inference contains information we've inferred about ideal
+       // candidates such as the candidate's type.
+       inference candidateInference
+
+       // enclosingFunc contains information about the function enclosing
+       // the position.
+       enclosingFunc *funcInfo
+
+       // enclosingCompositeLiteral contains information about the composite literal
+       // enclosing the position.
+       enclosingCompositeLiteral *compLitInfo
+
+       // deepState contains the current state of our deep completion search.
+       deepState deepCompletionState
+
+       // matcher matches the candidates against the surrounding prefix.
+       matcher matcher
+
+       // methodSetCache caches the types.NewMethodSet call, which is relatively
+       // expensive and can be called many times for the same type while searching
+       // for deep completions.
+       methodSetCache map[methodSetKey]*types.MethodSet
+
+       // mapper converts the positions in the file from which the completion originated.
+       mapper *protocol.ColumnMapper
+
+       // startTime is when we started processing this completion request. It does
+       // not include any time the request spent in the queue.
+       startTime time.Time
+}
+
+// funcInfo holds info about a function object.
+type funcInfo struct {
+       // sig is the function declaration enclosing the position.
+       sig *types.Signature
+
+       // body is the function's body.
+       body *ast.BlockStmt
+}
+
+type compLitInfo struct {
+       // cl is the *ast.CompositeLit enclosing the position.
+       cl *ast.CompositeLit
+
+       // clType is the type of cl.
+       clType types.Type
+
+       // kv is the *ast.KeyValueExpr enclosing the position, if any.
+       kv *ast.KeyValueExpr
+
+       // inKey is true if we are certain the position is in the key side
+       // of a key-value pair.
+       inKey bool
+
+       // maybeInFieldName is true if inKey is false and it is possible
+       // we are completing a struct field name. For example,
+       // "SomeStruct{<>}" will be inKey=false, but maybeInFieldName=true
+       // because we _could_ be completing a field name.
+       maybeInFieldName bool
+}
+
+type importInfo struct {
+       importPath string
+       name       string
+       pkg        source.Package
+}
+
+type methodSetKey struct {
+       typ         types.Type
+       addressable bool
+}
+
+type completionContext struct {
+       // triggerCharacter is the character used to trigger completion at current
+       // position, if any.
+       triggerCharacter string
+
+       // triggerKind is information about how a completion was triggered.
+       triggerKind protocol.CompletionTriggerKind
+
+       // commentCompletion is true if we are completing a comment.
+       commentCompletion bool
+
+       // packageCompletion is true if we are completing a package name.
+       packageCompletion bool
+}
+
+// A Selection represents the cursor position and surrounding identifier.
+type Selection struct {
+       content string
+       cursor  token.Pos
+       source.MappedRange
+}
+
+func (p Selection) Content() string {
+       return p.content
+}
+
+func (p Selection) Start() token.Pos {
+       return p.MappedRange.SpanRange().Start
+}
+
+func (p Selection) End() token.Pos {
+       return p.MappedRange.SpanRange().End
+}
+
+func (p Selection) Prefix() string {
+       return p.content[:p.cursor-p.SpanRange().Start]
+}
+
+func (p Selection) Suffix() string {
+       return p.content[p.cursor-p.SpanRange().Start:]
+}
+
+func (c *completer) setSurrounding(ident *ast.Ident) {
+       if c.surrounding != nil {
+               return
+       }
+       if !(ident.Pos() <= c.pos && c.pos <= ident.End()) {
+               return
+       }
+
+       c.surrounding = &Selection{
+               content: ident.Name,
+               cursor:  c.pos,
+               // Overwrite the prefix only.
+               MappedRange: source.NewMappedRange(c.snapshot.FileSet(), c.mapper, ident.Pos(), ident.End()),
+       }
+
+       c.setMatcherFromPrefix(c.surrounding.Prefix())
+}
+
+func (c *completer) setMatcherFromPrefix(prefix string) {
+       switch c.opts.matcher {
+       case source.Fuzzy:
+               c.matcher = fuzzy.NewMatcher(prefix)
+       case source.CaseSensitive:
+               c.matcher = prefixMatcher(prefix)
+       default:
+               c.matcher = insensitivePrefixMatcher(strings.ToLower(prefix))
+       }
+}
+
+func (c *completer) getSurrounding() *Selection {
+       if c.surrounding == nil {
+               c.surrounding = &Selection{
+                       content:     "",
+                       cursor:      c.pos,
+                       MappedRange: source.NewMappedRange(c.snapshot.FileSet(), c.mapper, c.pos, c.pos),
+               }
+       }
+       return c.surrounding
+}
+
+// candidate represents a completion candidate.
+type candidate struct {
+       // obj is the types.Object to complete to.
+       obj types.Object
+
+       // score is used to rank candidates.
+       score float64
+
+       // name is the deep object name path, e.g. "foo.bar"
+       name string
+
+       // detail is additional information about this item. If not specified,
+       // defaults to type string for the object.
+       detail string
+
+       // path holds the path from the search root (excluding the candidate
+       // itself) for a deep candidate.
+       path []types.Object
+
+       // names tracks the names of objects from search root (excluding the
+       // candidate itself) for a deep candidate. This also includes
+       // expanded calls for function invocations.
+       names []string
+
+       // expandFuncCall is true if obj should be invoked in the completion.
+       // For example, expandFuncCall=true yields "foo()", expandFuncCall=false yields "foo".
+       expandFuncCall bool
+
+       // takeAddress is true if the completion should take a pointer to obj.
+       // For example, takeAddress=true yields "&foo", takeAddress=false yields "foo".
+       takeAddress bool
+
+       // addressable is true if a pointer can be taken to the candidate.
+       addressable bool
+
+       // makePointer is true if the candidate type name T should be made into *T.
+       makePointer bool
+
+       // dereference is a count of how many times to dereference the candidate obj.
+       // For example, dereference=2 turns "foo" into "**foo" when formatting.
+       dereference int
+
+       // variadic is true if this candidate fills a variadic param and
+       // needs "..." appended.
+       variadic bool
+
+       // imp is the import that needs to be added to this package in order
+       // for this candidate to be valid. nil if no import needed.
+       imp *importInfo
+}
+
+// ErrIsDefinition is an error that informs the user they got no
+// completions because they tried to complete the name of a new object
+// being defined.
+type ErrIsDefinition struct {
+       objStr string
+}
+
+func (e ErrIsDefinition) Error() string {
+       msg := "this is a definition"
+       if e.objStr != "" {
+               msg += " of " + e.objStr
+       }
+       return msg
+}
+
+// Completion returns a list of possible candidates for completion, given a
+// a file and a position.
+//
+// The selection is computed based on the preceding identifier and can be used by
+// the client to score the quality of the completion. For instance, some clients
+// may tolerate imperfect matches as valid completion results, since users may make typos.
+func Completion(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle, protoPos protocol.Position, protoContext protocol.CompletionContext) ([]CompletionItem, *Selection, error) {
+       ctx, done := event.Start(ctx, "completion.Completion")
+       defer done()
+
+       startTime := time.Now()
+
+       pkg, pgf, err := source.GetParsedFile(ctx, snapshot, fh, source.NarrowestPackage)
+       if err != nil || pgf.File.Package == token.NoPos {
+               // If we can't parse this file or find position for the package
+               // keyword, it may be missing a package declaration. Try offering
+               // suggestions for the package declaration.
+               // Note that this would be the case even if the keyword 'package' is
+               // present but no package name exists.
+               items, surrounding, innerErr := packageClauseCompletions(ctx, snapshot, fh, protoPos)
+               if innerErr != nil {
+                       // return the error for GetParsedFile since it's more relevant in this situation.
+                       return nil, nil, errors.Errorf("getting file for Completion: %w (package completions: %v)", err, innerErr)
+
+               }
+               return items, surrounding, nil
+       }
+       spn, err := pgf.Mapper.PointSpan(protoPos)
+       if err != nil {
+               return nil, nil, err
+       }
+       rng, err := spn.Range(pgf.Mapper.Converter)
+       if err != nil {
+               return nil, nil, err
+       }
+       // Completion is based on what precedes the cursor.
+       // Find the path to the position before pos.
+       path, _ := astutil.PathEnclosingInterval(pgf.File, rng.Start-1, rng.Start-1)
+       if path == nil {
+               return nil, nil, errors.Errorf("cannot find node enclosing position")
+       }
+
+       pos := rng.Start
+
+       // Check if completion at this position is valid. If not, return early.
+       switch n := path[0].(type) {
+       case *ast.BasicLit:
+               // Skip completion inside literals except for ImportSpec
+               if len(path) > 1 {
+                       if _, ok := path[1].(*ast.ImportSpec); ok {
+                               break
+                       }
+               }
+               return nil, nil, nil
+       case *ast.CallExpr:
+               if n.Ellipsis.IsValid() && pos > n.Ellipsis && pos <= n.Ellipsis+token.Pos(len("...")) {
+                       // Don't offer completions inside or directly after "...". For
+                       // example, don't offer completions at "<>" in "foo(bar...<>").
+                       return nil, nil, nil
+               }
+       case *ast.Ident:
+               // reject defining identifiers
+               if obj, ok := pkg.GetTypesInfo().Defs[n]; ok {
+                       if v, ok := obj.(*types.Var); ok && v.IsField() && v.Embedded() {
+                               // An anonymous field is also a reference to a type.
+                       } else if pgf.File.Name == n {
+                               // Don't skip completions if Ident is for package name.
+                               break
+                       } else {
+                               objStr := ""
+                               if obj != nil {
+                                       qual := types.RelativeTo(pkg.GetTypes())
+                                       objStr = types.ObjectString(obj, qual)
+                               }
+                               return nil, nil, ErrIsDefinition{objStr: objStr}
+                       }
+               }
+       }
+
+       opts := snapshot.View().Options()
+       c := &completer{
+               pkg:      pkg,
+               snapshot: snapshot,
+               qf:       source.Qualifier(pgf.File, pkg.GetTypes(), pkg.GetTypesInfo()),
+               completionContext: completionContext{
+                       triggerCharacter: protoContext.TriggerCharacter,
+                       triggerKind:      protoContext.TriggerKind,
+               },
+               fh:                        fh,
+               filename:                  fh.URI().Filename(),
+               file:                      pgf.File,
+               path:                      path,
+               pos:                       pos,
+               seen:                      make(map[types.Object]bool),
+               enclosingFunc:             enclosingFunction(path, pkg.GetTypesInfo()),
+               enclosingCompositeLiteral: enclosingCompositeLiteral(path, rng.Start, pkg.GetTypesInfo()),
+               deepState: deepCompletionState{
+                       enabled: opts.DeepCompletion,
+               },
+               opts: &completionOptions{
+                       matcher:           opts.Matcher,
+                       unimported:        opts.CompleteUnimported,
+                       documentation:     opts.CompletionDocumentation && opts.HoverKind != source.NoDocumentation,
+                       fullDocumentation: opts.HoverKind == source.FullDocumentation,
+                       placeholders:      opts.UsePlaceholders,
+                       literal:           opts.LiteralCompletions && opts.InsertTextFormat == protocol.SnippetTextFormat,
+                       budget:            opts.CompletionBudget,
+               },
+               // default to a matcher that always matches
+               matcher:        prefixMatcher(""),
+               methodSetCache: make(map[methodSetKey]*types.MethodSet),
+               mapper:         pgf.Mapper,
+               startTime:      startTime,
+       }
+
+       var cancel context.CancelFunc
+       if c.opts.budget == 0 {
+               ctx, cancel = context.WithCancel(ctx)
+       } else {
+               // timeoutDuration is the completion budget remaining. If less than
+               // 10ms, set to 10ms
+               timeoutDuration := time.Until(c.startTime.Add(c.opts.budget))
+               if timeoutDuration < 10*time.Millisecond {
+                       timeoutDuration = 10 * time.Millisecond
+               }
+               ctx, cancel = context.WithTimeout(ctx, timeoutDuration)
+       }
+       defer cancel()
+
+       if surrounding := c.containingIdent(pgf.Src); surrounding != nil {
+               c.setSurrounding(surrounding)
+       }
+
+       c.inference = expectedCandidate(ctx, c)
+
+       err = c.collectCompletions(ctx)
+       if err != nil {
+               return nil, nil, err
+       }
+
+       // Deep search collected candidates and their members for more candidates.
+       c.deepSearch(ctx)
+       c.deepState.searchQueue = nil
+
+       for _, callback := range c.completionCallbacks {
+               if err := c.snapshot.RunProcessEnvFunc(ctx, callback); err != nil {
+                       return nil, nil, err
+               }
+       }
+
+       // Search candidates populated by expensive operations like
+       // unimportedMembers etc. for more completion items.
+       c.deepSearch(ctx)
+
+       // Statement candidates offer an entire statement in certain contexts, as
+       // opposed to a single object. Add statement candidates last because they
+       // depend on other candidates having already been collected.
+       c.addStatementCandidates()
+
+       c.sortItems()
+       return c.items, c.getSurrounding(), nil
+}
+
+// collectCompletions adds possible completion candidates to either the deep
+// search queue or completion items directly for different completion contexts.
+func (c *completer) collectCompletions(ctx context.Context) error {
+       // Inside import blocks, return completions for unimported packages.
+       for _, importSpec := range c.file.Imports {
+               if !(importSpec.Path.Pos() <= c.pos && c.pos <= importSpec.Path.End()) {
+                       continue
+               }
+               return c.populateImportCompletions(ctx, importSpec)
+       }
+
+       // Inside comments, offer completions for the name of the relevant symbol.
+       for _, comment := range c.file.Comments {
+               if comment.Pos() < c.pos && c.pos <= comment.End() {
+                       c.populateCommentCompletions(ctx, comment)
+                       return nil
+               }
+       }
+
+       // Struct literals are handled entirely separately.
+       if c.wantStructFieldCompletions() {
+               // If we are definitely completing a struct field name, deep completions
+               // don't make sense.
+               if c.enclosingCompositeLiteral.inKey {
+                       c.deepState.enabled = false
+               }
+               return c.structLiteralFieldName(ctx)
+       }
+
+       if lt := c.wantLabelCompletion(); lt != labelNone {
+               c.labels(lt)
+               return nil
+       }
+
+       if c.emptySwitchStmt() {
+               // Empty switch statements only admit "default" and "case" keywords.
+               c.addKeywordItems(map[string]bool{}, highScore, CASE, DEFAULT)
+               return nil
+       }
+
+       switch n := c.path[0].(type) {
+       case *ast.Ident:
+               if c.file.Name == n {
+                       return c.packageNameCompletions(ctx, c.fh.URI(), n)
+               } else if sel, ok := c.path[1].(*ast.SelectorExpr); ok && sel.Sel == n {
+                       // Is this the Sel part of a selector?
+                       return c.selector(ctx, sel)
+               }
+               return c.lexical(ctx)
+       // The function name hasn't been typed yet, but the parens are there:
+       //   recv.‸(arg)
+       case *ast.TypeAssertExpr:
+               // Create a fake selector expression.
+               return c.selector(ctx, &ast.SelectorExpr{X: n.X})
+       case *ast.SelectorExpr:
+               return c.selector(ctx, n)
+       // At the file scope, only keywords are allowed.
+       case *ast.BadDecl, *ast.File:
+               c.addKeywordCompletions()
+       default:
+               // fallback to lexical completions
+               return c.lexical(ctx)
+       }
+
+       return nil
+}
+
+// containingIdent returns the *ast.Ident containing pos, if any. It
+// synthesizes an *ast.Ident to allow completion in the face of
+// certain syntax errors.
+func (c *completer) containingIdent(src []byte) *ast.Ident {
+       // In the normal case, our leaf AST node is the identifer being completed.
+       if ident, ok := c.path[0].(*ast.Ident); ok {
+               return ident
+       }
+
+       pos, tkn, lit := c.scanToken(src)
+       if !pos.IsValid() {
+               return nil
+       }
+
+       fakeIdent := &ast.Ident{Name: lit, NamePos: pos}
+
+       if _, isBadDecl := c.path[0].(*ast.BadDecl); isBadDecl {
+               // You don't get *ast.Idents at the file level, so look for bad
+               // decls and use the manually extracted token.
+               return fakeIdent
+       } else if c.emptySwitchStmt() {
+               // Only keywords are allowed in empty switch statements.
+               // *ast.Idents are not parsed, so we must use the manually
+               // extracted token.
+               return fakeIdent
+       } else if tkn.IsKeyword() {
+               // Otherwise, manually extract the prefix if our containing token
+               // is a keyword. This improves completion after an "accidental
+               // keyword", e.g. completing to "variance" in "someFunc(var<>)".
+               return fakeIdent
+       }
+
+       return nil
+}
+
+// scanToken scans pgh's contents for the token containing pos.
+func (c *completer) scanToken(contents []byte) (token.Pos, token.Token, string) {
+       tok := c.snapshot.FileSet().File(c.pos)
+
+       var s scanner.Scanner
+       s.Init(tok, contents, nil, 0)
+       for {
+               tknPos, tkn, lit := s.Scan()
+               if tkn == token.EOF || tknPos >= c.pos {
+                       return token.NoPos, token.ILLEGAL, ""
+               }
+
+               if len(lit) > 0 && tknPos <= c.pos && c.pos <= tknPos+token.Pos(len(lit)) {
+                       return tknPos, tkn, lit
+               }
+       }
+}
+
+func (c *completer) sortItems() {
+       sort.SliceStable(c.items, func(i, j int) bool {
+               // Sort by score first.
+               if c.items[i].Score != c.items[j].Score {
+                       return c.items[i].Score > c.items[j].Score
+               }
+
+               // Then sort by label so order stays consistent. This also has the
+               // effect of prefering shorter candidates.
+               return c.items[i].Label < c.items[j].Label
+       })
+}
+
+// emptySwitchStmt reports whether pos is in an empty switch or select
+// statement.
+func (c *completer) emptySwitchStmt() bool {
+       block, ok := c.path[0].(*ast.BlockStmt)
+       if !ok || len(block.List) > 0 || len(c.path) == 1 {
+               return false
+       }
+
+       switch c.path[1].(type) {
+       case *ast.SwitchStmt, *ast.TypeSwitchStmt, *ast.SelectStmt:
+               return true
+       default:
+               return false
+       }
+}
+
+// populateImportCompletions yields completions for an import path around the cursor.
+//
+// Completions are suggested at the directory depth of the given import path so
+// that we don't overwhelm the user with a large list of possibilities. As an
+// example, a completion for the prefix "golang" results in "golang.org/".
+// Completions for "golang.org/" yield its subdirectories
+// (i.e. "golang.org/x/"). The user is meant to accept completion suggestions
+// until they reach a complete import path.
+func (c *completer) populateImportCompletions(ctx context.Context, searchImport *ast.ImportSpec) error {
+       // deepSearch is not valuable for import completions.
+       c.deepState.enabled = false
+
+       importPath := searchImport.Path.Value
+
+       // Extract the text between the quotes (if any) in an import spec.
+       // prefix is the part of import path before the cursor.
+       prefixEnd := c.pos - searchImport.Path.Pos()
+       prefix := strings.Trim(importPath[:prefixEnd], `"`)
+
+       // The number of directories in the import path gives us the depth at
+       // which to search.
+       depth := len(strings.Split(prefix, "/")) - 1
+
+       content := importPath
+       start, end := searchImport.Path.Pos(), searchImport.Path.End()
+       namePrefix, nameSuffix := `"`, `"`
+       // If a starting quote is present, adjust surrounding to either after the
+       // cursor or after the first slash (/), except if cursor is at the starting
+       // quote. Otherwise we provide a completion including the starting quote.
+       if strings.HasPrefix(importPath, `"`) && c.pos > searchImport.Path.Pos() {
+               content = content[1:]
+               start++
+               if depth > 0 {
+                       // Adjust textEdit start to replacement range. For ex: if current
+                       // path was "golang.or/x/to<>ols/internal/", where <> is the cursor
+                       // position, start of the replacement range would be after
+                       // "golang.org/x/".
+                       path := strings.SplitAfter(prefix, "/")
+                       numChars := len(strings.Join(path[:len(path)-1], ""))
+                       content = content[numChars:]
+                       start += token.Pos(numChars)
+               }
+               namePrefix = ""
+       }
+
+       // We won't provide an ending quote if one is already present, except if
+       // cursor is after the ending quote but still in import spec. This is
+       // because cursor has to be in our textEdit range.
+       if strings.HasSuffix(importPath, `"`) && c.pos < searchImport.Path.End() {
+               end--
+               content = content[:len(content)-1]
+               nameSuffix = ""
+       }
+
+       c.surrounding = &Selection{
+               content:     content,
+               cursor:      c.pos,
+               MappedRange: source.NewMappedRange(c.snapshot.FileSet(), c.mapper, start, end),
+       }
+
+       seenImports := make(map[string]struct{})
+       for _, importSpec := range c.file.Imports {
+               if importSpec.Path.Value == importPath {
+                       continue
+               }
+               seenImportPath, err := strconv.Unquote(importSpec.Path.Value)
+               if err != nil {
+                       return err
+               }
+               seenImports[seenImportPath] = struct{}{}
+       }
+
+       var mu sync.Mutex // guard c.items locally, since searchImports is called in parallel
+       seen := make(map[string]struct{})
+       searchImports := func(pkg imports.ImportFix) {
+               path := pkg.StmtInfo.ImportPath
+               if _, ok := seenImports[path]; ok {
+                       return
+               }
+
+               // Any package path containing fewer directories than the search
+               // prefix is not a match.
+               pkgDirList := strings.Split(path, "/")
+               if len(pkgDirList) < depth+1 {
+                       return
+               }
+               pkgToConsider := strings.Join(pkgDirList[:depth+1], "/")
+
+               name := pkgDirList[depth]
+               // if we're adding an opening quote to completion too, set name to full
+               // package path since we'll need to overwrite that range.
+               if namePrefix == `"` {
+                       name = pkgToConsider
+               }
+
+               score := pkg.Relevance
+               if len(pkgDirList)-1 == depth {
+                       score *= highScore
+               } else {
+                       // For incomplete package paths, add a terminal slash to indicate that the
+                       // user should keep triggering completions.
+                       name += "/"
+                       pkgToConsider += "/"
+               }
+
+               if _, ok := seen[pkgToConsider]; ok {
+                       return
+               }
+               seen[pkgToConsider] = struct{}{}
+
+               mu.Lock()
+               defer mu.Unlock()
+
+               name = namePrefix + name + nameSuffix
+               obj := types.NewPkgName(0, nil, name, types.NewPackage(pkgToConsider, name))
+               c.deepState.enqueue(candidate{
+                       obj:    obj,
+                       detail: fmt.Sprintf("%q", pkgToConsider),
+                       score:  score,
+               })
+       }
+
+       c.completionCallbacks = append(c.completionCallbacks, func(opts *imports.Options) error {
+               return imports.GetImportPaths(ctx, searchImports, prefix, c.filename, c.pkg.GetTypes().Name(), opts.Env)
+       })
+       return nil
+}
+
+// populateCommentCompletions yields completions for comments preceding or in declarations.
+func (c *completer) populateCommentCompletions(ctx context.Context, comment *ast.CommentGroup) {
+       // If the completion was triggered by a period, ignore it. These types of
+       // completions will not be useful in comments.
+       if c.completionContext.triggerCharacter == "." {
+               return
+       }
+
+       // Using the comment position find the line after
+       file := c.snapshot.FileSet().File(comment.End())
+       if file == nil {
+               return
+       }
+
+       // Deep completion doesn't work properly in comments since we don't
+       // have a type object to complete further.
+       c.deepState.enabled = false
+       c.completionContext.commentCompletion = true
+
+       // Documentation isn't useful in comments, since it might end up being the
+       // comment itself.
+       c.opts.documentation = false
+
+       commentLine := file.Line(comment.End())
+
+       // comment is valid, set surrounding as word boundaries around cursor
+       c.setSurroundingForComment(comment)
+
+       // Using the next line pos, grab and parse the exported symbol on that line
+       for _, n := range c.file.Decls {
+               declLine := file.Line(n.Pos())
+               // if the comment is not in, directly above or on the same line as a declaration
+               if declLine != commentLine && declLine != commentLine+1 &&
+                       !(n.Pos() <= comment.Pos() && comment.End() <= n.End()) {
+                       continue
+               }
+               switch node := n.(type) {
+               // handle const, vars, and types
+               case *ast.GenDecl:
+                       for _, spec := range node.Specs {
+                               switch spec := spec.(type) {
+                               case *ast.ValueSpec:
+                                       for _, name := range spec.Names {
+                                               if name.String() == "_" {
+                                                       continue
+                                               }
+                                               obj := c.pkg.GetTypesInfo().ObjectOf(name)
+                                               c.deepState.enqueue(candidate{obj: obj, score: stdScore})
+                                       }
+                               case *ast.TypeSpec:
+                                       // add TypeSpec fields to completion
+                                       switch typeNode := spec.Type.(type) {
+                                       case *ast.StructType:
+                                               c.addFieldItems(ctx, typeNode.Fields)
+                                       case *ast.FuncType:
+                                               c.addFieldItems(ctx, typeNode.Params)
+                                               c.addFieldItems(ctx, typeNode.Results)
+                                       case *ast.InterfaceType:
+                                               c.addFieldItems(ctx, typeNode.Methods)
+                                       }
+
+                                       if spec.Name.String() == "_" {
+                                               continue
+                                       }
+
+                                       obj := c.pkg.GetTypesInfo().ObjectOf(spec.Name)
+                                       // Type name should get a higher score than fields but not highScore by default
+                                       // since field near a comment cursor gets a highScore
+                                       score := stdScore * 1.1
+                                       // If type declaration is on the line after comment, give it a highScore.
+                                       if declLine == commentLine+1 {
+                                               score = highScore
+                                       }
+
+                                       c.deepState.enqueue(candidate{obj: obj, score: score})
+                               }
+                       }
+               // handle functions
+               case *ast.FuncDecl:
+                       c.addFieldItems(ctx, node.Recv)
+                       c.addFieldItems(ctx, node.Type.Params)
+                       c.addFieldItems(ctx, node.Type.Results)
+
+                       // collect receiver struct fields
+                       if node.Recv != nil {
+                               for _, fields := range node.Recv.List {
+                                       for _, name := range fields.Names {
+                                               obj := c.pkg.GetTypesInfo().ObjectOf(name)
+                                               if obj == nil {
+                                                       continue
+                                               }
+
+                                               recvType := obj.Type().Underlying()
+                                               if ptr, ok := recvType.(*types.Pointer); ok {
+                                                       recvType = ptr.Elem()
+                                               }
+                                               recvStruct, ok := recvType.Underlying().(*types.Struct)
+                                               if !ok {
+                                                       continue
+                                               }
+                                               for i := 0; i < recvStruct.NumFields(); i++ {
+                                                       field := recvStruct.Field(i)
+                                                       c.deepState.enqueue(candidate{obj: field, score: lowScore})
+                                               }
+                                       }
+                               }
+                       }
+
+                       if node.Name.String() == "_" {
+                               continue
+                       }
+
+                       obj := c.pkg.GetTypesInfo().ObjectOf(node.Name)
+                       if obj == nil || obj.Pkg() != nil && obj.Pkg() != c.pkg.GetTypes() {
+                               continue
+                       }
+
+                       c.deepState.enqueue(candidate{obj: obj, score: highScore})
+               }
+       }
+}
+
+// sets word boundaries surrounding a cursor for a comment
+func (c *completer) setSurroundingForComment(comments *ast.CommentGroup) {
+       var cursorComment *ast.Comment
+       for _, comment := range comments.List {
+               if c.pos >= comment.Pos() && c.pos <= comment.End() {
+                       cursorComment = comment
+                       break
+               }
+       }
+       // if cursor isn't in the comment
+       if cursorComment == nil {
+               return
+       }
+
+       // index of cursor in comment text
+       cursorOffset := int(c.pos - cursorComment.Pos())
+       start, end := cursorOffset, cursorOffset
+       for start > 0 && isValidIdentifierChar(cursorComment.Text[start-1]) {
+               start--
+       }
+       for end < len(cursorComment.Text) && isValidIdentifierChar(cursorComment.Text[end]) {
+               end++
+       }
+
+       c.surrounding = &Selection{
+               content: cursorComment.Text[start:end],
+               cursor:  c.pos,
+               MappedRange: source.NewMappedRange(c.snapshot.FileSet(), c.mapper,
+                       token.Pos(int(cursorComment.Slash)+start), token.Pos(int(cursorComment.Slash)+end)),
+       }
+       c.setMatcherFromPrefix(c.surrounding.Prefix())
+}
+
+// isValidIdentifierChar returns true if a byte is a valid go identifier character
+// i.e unicode letter or digit or undescore
+func isValidIdentifierChar(char byte) bool {
+       charRune := rune(char)
+       return unicode.In(charRune, unicode.Letter, unicode.Digit) || char == '_'
+}
+
+// adds struct fields, interface methods, function declaration fields to completion
+func (c *completer) addFieldItems(ctx context.Context, fields *ast.FieldList) {
+       if fields == nil {
+               return
+       }
+
+       cursor := c.surrounding.cursor
+       for _, field := range fields.List {
+               for _, name := range field.Names {
+                       if name.String() == "_" {
+                               continue
+                       }
+                       obj := c.pkg.GetTypesInfo().ObjectOf(name)
+                       if obj == nil {
+                               continue
+                       }
+
+                       // if we're in a field comment/doc, score that field as more relevant
+                       score := stdScore
+                       if field.Comment != nil && field.Comment.Pos() <= cursor && cursor <= field.Comment.End() {
+                               score = highScore
+                       } else if field.Doc != nil && field.Doc.Pos() <= cursor && cursor <= field.Doc.End() {
+                               score = highScore
+                       }
+
+                       c.deepState.enqueue(candidate{obj: obj, score: score})
+               }
+       }
+}
+
+func (c *completer) wantStructFieldCompletions() bool {
+       clInfo := c.enclosingCompositeLiteral
+       if clInfo == nil {
+               return false
+       }
+
+       return clInfo.isStruct() && (clInfo.inKey || clInfo.maybeInFieldName)
+}
+
+func (c *completer) wantTypeName() bool {
+       return !c.completionContext.commentCompletion && c.inference.typeName.wantTypeName
+}
+
+// See https://golang.org/issue/36001. Unimported completions are expensive.
+const (
+       maxUnimportedPackageNames = 5
+       unimportedMemberTarget    = 100
+)
+
+// selector finds completions for the specified selector expression.
+func (c *completer) selector(ctx context.Context, sel *ast.SelectorExpr) error {
+       c.inference.objChain = objChain(c.pkg.GetTypesInfo(), sel.X)
+
+       // Is sel a qualified identifier?
+       if id, ok := sel.X.(*ast.Ident); ok {
+               if pkgName, ok := c.pkg.GetTypesInfo().Uses[id].(*types.PkgName); ok {
+                       candidates := c.packageMembers(pkgName.Imported(), stdScore, nil)
+                       for _, cand := range candidates {
+                               c.deepState.enqueue(cand)
+                       }
+                       return nil
+               }
+       }
+
+       // Invariant: sel is a true selector.
+       tv, ok := c.pkg.GetTypesInfo().Types[sel.X]
+       if ok {
+               candidates := c.methodsAndFields(tv.Type, tv.Addressable(), nil)
+               for _, cand := range candidates {
+                       c.deepState.enqueue(cand)
+               }
+               return nil
+       }
+
+       // Try unimported packages.
+       if id, ok := sel.X.(*ast.Ident); ok && c.opts.unimported {
+               if err := c.unimportedMembers(ctx, id); err != nil {
+                       return err
+               }
+       }
+       return nil
+}
+
+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(ctx)
+       if err != nil {
+               return err
+       }
+
+       var paths []string
+       for path, pkg := range known {
+               if pkg.GetTypes().Name() != id.Name {
+                       continue
+               }
+               paths = append(paths, path)
+       }
+
+       var relevances map[string]float64
+       if len(paths) != 0 {
+               if err := c.snapshot.RunProcessEnvFunc(ctx, func(opts *imports.Options) error {
+                       var err error
+                       relevances, err = imports.ScoreImportPaths(ctx, opts.Env, paths)
+                       return err
+               }); err != nil {
+                       return err
+               }
+       }
+       sort.Slice(paths, func(i, j int) bool {
+               return relevances[paths[i]] > relevances[paths[j]]
+       })
+
+       for _, path := range paths {
+               pkg := known[path]
+               if pkg.GetTypes().Name() != id.Name {
+                       continue
+               }
+               imp := &importInfo{
+                       importPath: path,
+                       pkg:        pkg,
+               }
+               if imports.ImportPathToAssumedName(path) != pkg.GetTypes().Name() {
+                       imp.name = pkg.GetTypes().Name()
+               }
+               candidates := c.packageMembers(pkg.GetTypes(), unimportedScore(relevances[path]), imp)
+               for _, cand := range candidates {
+                       c.deepState.enqueue(cand)
+               }
+               if len(c.items) >= unimportedMemberTarget {
+                       return nil
+               }
+       }
+
+       ctx, cancel := context.WithCancel(ctx)
+
+       var mu sync.Mutex
+       add := func(pkgExport imports.PackageExport) {
+               mu.Lock()
+               defer mu.Unlock()
+               if _, ok := known[pkgExport.Fix.StmtInfo.ImportPath]; ok {
+                       return // We got this one above.
+               }
+
+               // Continue with untyped proposals.
+               pkg := types.NewPackage(pkgExport.Fix.StmtInfo.ImportPath, pkgExport.Fix.IdentName)
+               for _, export := range pkgExport.Exports {
+                       score := unimportedScore(pkgExport.Fix.Relevance)
+                       c.deepState.enqueue(candidate{
+                               obj:   types.NewVar(0, pkg, export, nil),
+                               score: score,
+                               imp: &importInfo{
+                                       importPath: pkgExport.Fix.StmtInfo.ImportPath,
+                                       name:       pkgExport.Fix.StmtInfo.Name,
+                               },
+                       })
+               }
+               if len(c.items) >= unimportedMemberTarget {
+                       cancel()
+               }
+       }
+
+       c.completionCallbacks = append(c.completionCallbacks, func(opts *imports.Options) error {
+               defer cancel()
+               return imports.GetPackageExports(ctx, add, id.Name, c.filename, c.pkg.GetTypes().Name(), opts.Env)
+       })
+       return nil
+}
+
+// unimportedScore returns a score for an unimported package that is generally
+// lower than other candidates.
+func unimportedScore(relevance float64) float64 {
+       return (stdScore + .1*relevance) / 2
+}
+
+func (c *completer) packageMembers(pkg *types.Package, score float64, imp *importInfo) []candidate {
+       var candidates []candidate
+       scope := pkg.Scope()
+       for _, name := range scope.Names() {
+               obj := scope.Lookup(name)
+               candidates = append(candidates, candidate{
+                       obj:         obj,
+                       score:       score,
+                       imp:         imp,
+                       addressable: isVar(obj),
+               })
+       }
+       return candidates
+}
+
+func (c *completer) methodsAndFields(typ types.Type, addressable bool, imp *importInfo) []candidate {
+       mset := c.methodSetCache[methodSetKey{typ, addressable}]
+       if mset == nil {
+               if addressable && !types.IsInterface(typ) && !isPointer(typ) {
+                       // Add methods of *T, which includes methods with receiver T.
+                       mset = types.NewMethodSet(types.NewPointer(typ))
+               } else {
+                       // Add methods of T.
+                       mset = types.NewMethodSet(typ)
+               }
+               c.methodSetCache[methodSetKey{typ, addressable}] = mset
+       }
+
+       var candidates []candidate
+       for i := 0; i < mset.Len(); i++ {
+               candidates = append(candidates, candidate{
+                       obj:         mset.At(i).Obj(),
+                       score:       stdScore,
+                       imp:         imp,
+                       addressable: addressable || isPointer(typ),
+               })
+       }
+
+       // Add fields of T.
+       eachField(typ, func(v *types.Var) {
+               candidates = append(candidates, candidate{
+                       obj:         v,
+                       score:       stdScore - 0.01,
+                       imp:         imp,
+                       addressable: addressable || isPointer(typ),
+               })
+       })
+
+       return candidates
+}
+
+// lexical finds completions in the lexical environment.
+func (c *completer) lexical(ctx context.Context) error {
+       scopes := source.CollectScopes(c.pkg.GetTypesInfo(), c.path, c.pos)
+       scopes = append(scopes, c.pkg.GetTypes().Scope(), types.Universe)
+
+       var (
+               builtinIota = types.Universe.Lookup("iota")
+               builtinNil  = types.Universe.Lookup("nil")
+       )
+
+       // Track seen variables to avoid showing completions for shadowed variables.
+       // This works since we look at scopes from innermost to outermost.
+       seen := make(map[string]struct{})
+
+       // Process scopes innermost first.
+       for i, scope := range scopes {
+               if scope == nil {
+                       continue
+               }
+
+       Names:
+               for _, name := range scope.Names() {
+                       declScope, obj := scope.LookupParent(name, c.pos)
+                       if declScope != scope {
+                               continue // Name was declared in some enclosing scope, or not at all.
+                       }
+
+                       // If obj's type is invalid, find the AST node that defines the lexical block
+                       // containing the declaration of obj. Don't resolve types for packages.
+                       if !isPkgName(obj) && !typeIsValid(obj.Type()) {
+                               // Match the scope to its ast.Node. If the scope is the package scope,
+                               // use the *ast.File as the starting node.
+                               var node ast.Node
+                               if i < len(c.path) {
+                                       node = c.path[i]
+                               } else if i == len(c.path) { // use the *ast.File for package scope
+                                       node = c.path[i-1]
+                               }
+                               if node != nil {
+                                       if resolved := resolveInvalid(c.snapshot.FileSet(), obj, node, c.pkg.GetTypesInfo()); resolved != nil {
+                                               obj = resolved
+                                       }
+                               }
+                       }
+
+                       // Don't use LHS of value spec in RHS.
+                       if vs := enclosingValueSpec(c.path); vs != nil {
+                               for _, ident := range vs.Names {
+                                       if obj.Pos() == ident.Pos() {
+                                               continue Names
+                                       }
+                               }
+                       }
+
+                       // Don't suggest "iota" outside of const decls.
+                       if obj == builtinIota && !c.inConstDecl() {
+                               continue
+                       }
+
+                       // Rank outer scopes lower than inner.
+                       score := stdScore * math.Pow(.99, float64(i))
+
+                       // Dowrank "nil" a bit so it is ranked below more interesting candidates.
+                       if obj == builtinNil {
+                               score /= 2
+                       }
+
+                       // 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.deepState.enqueue(candidate{
+                                       obj:         obj,
+                                       score:       score,
+                                       addressable: isVar(obj),
+                               })
+                       }
+               }
+       }
+
+       if c.inference.objType != nil {
+               if named, _ := source.Deref(c.inference.objType).(*types.Named); named != nil {
+                       // If we expected a named type, check the type's package for
+                       // completion items. This is useful when the current file hasn't
+                       // imported the type's package yet.
+
+                       if named.Obj() != nil && named.Obj().Pkg() != nil {
+                               pkg := named.Obj().Pkg()
+
+                               // Make sure the package name isn't already in use by another
+                               // object, and that this file doesn't import the package yet.
+                               if _, ok := seen[pkg.Name()]; !ok && pkg != c.pkg.GetTypes() && !alreadyImports(c.file, pkg.Path()) {
+                                       seen[pkg.Name()] = struct{}{}
+                                       obj := types.NewPkgName(0, nil, pkg.Name(), pkg)
+                                       imp := &importInfo{
+                                               importPath: pkg.Path(),
+                                       }
+                                       if imports.ImportPathToAssumedName(pkg.Path()) != pkg.Name() {
+                                               imp.name = pkg.Name()
+                                       }
+                                       c.deepState.enqueue(candidate{
+                                               obj:   obj,
+                                               score: stdScore,
+                                               imp:   imp,
+                                       })
+                               }
+                       }
+               }
+       }
+
+       if c.opts.unimported {
+               if err := c.unimportedPackages(ctx, seen); err != nil {
+                       return err
+               }
+       }
+
+       if t := c.inference.objType; t != nil {
+               t = source.Deref(t)
+
+               // If we have an expected type and it is _not_ a named type,
+               // handle it specially. Non-named types like "[]int" will never be
+               // considered via a lexical search, so we need to directly inject
+               // them.
+               if _, named := t.(*types.Named); !named {
+                       // If our expected type is "[]int", this will add a literal
+                       // candidate of "[]int{}".
+                       c.literal(ctx, t, nil)
+
+                       if _, isBasic := t.(*types.Basic); !isBasic {
+                               // If we expect a non-basic type name (e.g. "[]int"), hack up
+                               // a named type whose name is literally "[]int". This allows
+                               // us to reuse our object based completion machinery.
+                               fakeNamedType := candidate{
+                                       obj:   types.NewTypeName(token.NoPos, nil, types.TypeString(t, c.qf), t),
+                                       score: stdScore,
+                               }
+                               // Make sure the type name matches before considering
+                               // candidate. This cuts down on useless candidates.
+                               if c.matchingTypeName(&fakeNamedType) {
+                                       c.deepState.enqueue(fakeNamedType)
+                               }
+                       }
+               }
+       }
+
+       // Add keyword completion items appropriate in the current context.
+       c.addKeywordCompletions()
+
+       return nil
+}
+
+func (c *completer) unimportedPackages(ctx context.Context, seen map[string]struct{}) error {
+       var prefix string
+       if c.surrounding != nil {
+               prefix = c.surrounding.Prefix()
+       }
+       count := 0
+
+       known, err := c.snapshot.CachedImportPaths(ctx)
+       if err != nil {
+               return err
+       }
+       var paths []string
+       for path, pkg := range known {
+               if !strings.HasPrefix(pkg.GetTypes().Name(), prefix) {
+                       continue
+               }
+               paths = append(paths, path)
+       }
+
+       var relevances map[string]float64
+       if len(paths) != 0 {
+               if err := c.snapshot.RunProcessEnvFunc(ctx, func(opts *imports.Options) error {
+                       var err error
+                       relevances, err = imports.ScoreImportPaths(ctx, opts.Env, paths)
+                       return err
+               }); err != nil {
+                       return err
+               }
+       }
+       sort.Slice(paths, func(i, j int) bool {
+               return relevances[paths[i]] > relevances[paths[j]]
+       })
+
+       for _, path := range paths {
+               pkg := known[path]
+               if _, ok := seen[pkg.GetTypes().Name()]; ok {
+                       continue
+               }
+               imp := &importInfo{
+                       importPath: path,
+                       pkg:        pkg,
+               }
+               if imports.ImportPathToAssumedName(path) != pkg.GetTypes().Name() {
+                       imp.name = pkg.GetTypes().Name()
+               }
+               if count >= maxUnimportedPackageNames {
+                       return nil
+               }
+               c.deepState.enqueue(candidate{
+                       obj:   types.NewPkgName(0, nil, pkg.GetTypes().Name(), pkg.GetTypes()),
+                       score: unimportedScore(relevances[path]),
+                       imp:   imp,
+               })
+               count++
+       }
+
+       ctx, cancel := context.WithCancel(ctx)
+
+       var mu sync.Mutex
+       add := func(pkg imports.ImportFix) {
+               mu.Lock()
+               defer mu.Unlock()
+               if _, ok := seen[pkg.IdentName]; ok {
+                       return
+               }
+               if _, ok := relevances[pkg.StmtInfo.ImportPath]; ok {
+                       return
+               }
+
+               if count >= maxUnimportedPackageNames {
+                       cancel()
+                       return
+               }
+
+               // Do not add the unimported packages to seen, since we can have
+               // 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.deepState.enqueue(candidate{
+                       obj:   obj,
+                       score: unimportedScore(pkg.Relevance),
+                       imp: &importInfo{
+                               importPath: pkg.StmtInfo.ImportPath,
+                               name:       pkg.StmtInfo.Name,
+                       },
+               })
+               count++
+       }
+       c.completionCallbacks = append(c.completionCallbacks, func(opts *imports.Options) error {
+               defer cancel()
+               return imports.GetAllCandidates(ctx, add, prefix, c.filename, c.pkg.GetTypes().Name(), opts.Env)
+       })
+       return nil
+}
+
+// alreadyImports reports whether f has an import with the specified path.
+func alreadyImports(f *ast.File, path string) bool {
+       for _, s := range f.Imports {
+               if source.ImportPath(s) == path {
+                       return true
+               }
+       }
+       return false
+}
+
+func (c *completer) inConstDecl() bool {
+       for _, n := range c.path {
+               if decl, ok := n.(*ast.GenDecl); ok && decl.Tok == token.CONST {
+                       return true
+               }
+       }
+       return false
+}
+
+// structLiteralFieldName finds completions for struct field names inside a struct literal.
+func (c *completer) structLiteralFieldName(ctx context.Context) error {
+       clInfo := c.enclosingCompositeLiteral
+
+       // Mark fields of the composite literal that have already been set,
+       // except for the current field.
+       addedFields := make(map[*types.Var]bool)
+       for _, el := range clInfo.cl.Elts {
+               if kvExpr, ok := el.(*ast.KeyValueExpr); ok {
+                       if clInfo.kv == kvExpr {
+                               continue
+                       }
+
+                       if key, ok := kvExpr.Key.(*ast.Ident); ok {
+                               if used, ok := c.pkg.GetTypesInfo().Uses[key]; ok {
+                                       if usedVar, ok := used.(*types.Var); ok {
+                                               addedFields[usedVar] = true
+                                       }
+                               }
+                       }
+               }
+       }
+
+       switch t := clInfo.clType.(type) {
+       case *types.Struct:
+               for i := 0; i < t.NumFields(); i++ {
+                       field := t.Field(i)
+                       if !addedFields[field] {
+                               c.deepState.enqueue(candidate{
+                                       obj:   field,
+                                       score: highScore,
+                               })
+                       }
+               }
+
+               // 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(ctx)
+               }
+       default:
+               return c.lexical(ctx)
+       }
+
+       return nil
+}
+
+func (cl *compLitInfo) isStruct() bool {
+       _, ok := cl.clType.(*types.Struct)
+       return ok
+}
+
+// enclosingCompositeLiteral returns information about the composite literal enclosing the
+// position.
+func enclosingCompositeLiteral(path []ast.Node, pos token.Pos, info *types.Info) *compLitInfo {
+       for _, n := range path {
+               switch n := n.(type) {
+               case *ast.CompositeLit:
+                       // The enclosing node will be a composite literal if the user has just
+                       // opened the curly brace (e.g. &x{<>) or the completion request is triggered
+                       // from an already completed composite literal expression (e.g. &x{foo: 1, <>})
+                       //
+                       // The position is not part of the composite literal unless it falls within the
+                       // curly braces (e.g. "foo.Foo<>Struct{}").
+                       if !(n.Lbrace < pos && pos <= n.Rbrace) {
+                               // Keep searching since we may yet be inside a composite literal.
+                               // For example "Foo{B: Ba<>{}}".
+                               break
+                       }
+
+                       tv, ok := info.Types[n]
+                       if !ok {
+                               return nil
+                       }
+
+                       clInfo := compLitInfo{
+                               cl:     n,
+                               clType: source.Deref(tv.Type).Underlying(),
+                       }
+
+                       var (
+                               expr    ast.Expr
+                               hasKeys bool
+                       )
+                       for _, el := range n.Elts {
+                               // Remember the expression that the position falls in, if any.
+                               if el.Pos() <= pos && pos <= el.End() {
+                                       expr = el
+                               }
+
+                               if kv, ok := el.(*ast.KeyValueExpr); ok {
+                                       hasKeys = true
+                                       // If expr == el then we know the position falls in this expression,
+                                       // so also record kv as the enclosing *ast.KeyValueExpr.
+                                       if expr == el {
+                                               clInfo.kv = kv
+                                               break
+                                       }
+                               }
+                       }
+
+                       if clInfo.kv != nil {
+                               // If in a *ast.KeyValueExpr, we know we are in the key if the position
+                               // is to the left of the colon (e.g. "Foo{F<>: V}".
+                               clInfo.inKey = pos <= clInfo.kv.Colon
+                       } else if hasKeys {
+                               // If we aren't in a *ast.KeyValueExpr but the composite literal has
+                               // other *ast.KeyValueExprs, we must be on the key side of a new
+                               // *ast.KeyValueExpr (e.g. "Foo{F: V, <>}").
+                               clInfo.inKey = true
+                       } else {
+                               switch clInfo.clType.(type) {
+                               case *types.Struct:
+                                       if len(n.Elts) == 0 {
+                                               // If the struct literal is empty, next could be a struct field
+                                               // name or an expression (e.g. "Foo{<>}" could become "Foo{F:}"
+                                               // or "Foo{someVar}").
+                                               clInfo.maybeInFieldName = true
+                                       } else if len(n.Elts) == 1 {
+                                               // If there is one expression and the position is in that expression
+                                               // and the expression is an identifier, we may be writing a field
+                                               // name or an expression (e.g. "Foo{F<>}").
+                                               _, clInfo.maybeInFieldName = expr.(*ast.Ident)
+                                       }
+                               case *types.Map:
+                                       // If we aren't in a *ast.KeyValueExpr we must be adding a new key
+                                       // to the map.
+                                       clInfo.inKey = true
+                               }
+                       }
+
+                       return &clInfo
+               default:
+                       if breaksExpectedTypeInference(n, pos) {
+                               return nil
+                       }
+               }
+       }
+
+       return nil
+}
+
+// enclosingFunction returns the signature and body of the function
+// enclosing the given position.
+func enclosingFunction(path []ast.Node, info *types.Info) *funcInfo {
+       for _, node := range path {
+               switch t := node.(type) {
+               case *ast.FuncDecl:
+                       if obj, ok := info.Defs[t.Name]; ok {
+                               return &funcInfo{
+                                       sig:  obj.Type().(*types.Signature),
+                                       body: t.Body,
+                               }
+                       }
+               case *ast.FuncLit:
+                       if typ, ok := info.Types[t]; ok {
+                               return &funcInfo{
+                                       sig:  typ.Type.(*types.Signature),
+                                       body: t.Body,
+                               }
+                       }
+               }
+       }
+       return nil
+}
+
+func (c *completer) expectedCompositeLiteralType() types.Type {
+       clInfo := c.enclosingCompositeLiteral
+       switch t := clInfo.clType.(type) {
+       case *types.Slice:
+               if clInfo.inKey {
+                       return types.Typ[types.Int]
+               }
+               return t.Elem()
+       case *types.Array:
+               if clInfo.inKey {
+                       return types.Typ[types.Int]
+               }
+               return t.Elem()
+       case *types.Map:
+               if clInfo.inKey {
+                       return t.Key()
+               }
+               return t.Elem()
+       case *types.Struct:
+               // If we are completing a key (i.e. field name), there is no expected type.
+               if clInfo.inKey {
+                       return nil
+               }
+
+               // If we are in a key-value pair, but not in the key, then we must be on the
+               // value side. The expected type of the value will be determined from the key.
+               if clInfo.kv != nil {
+                       if key, ok := clInfo.kv.Key.(*ast.Ident); ok {
+                               for i := 0; i < t.NumFields(); i++ {
+                                       if field := t.Field(i); field.Name() == key.Name {
+                                               return field.Type()
+                                       }
+                               }
+                       }
+               } else {
+                       // If we aren't in a key-value pair and aren't in the key, we must be using
+                       // implicit field names.
+
+                       // The order of the literal fields must match the order in the struct definition.
+                       // Find the element that the position belongs to and suggest that field's type.
+                       if i := exprAtPos(c.pos, clInfo.cl.Elts); i < t.NumFields() {
+                               return t.Field(i).Type()
+                       }
+               }
+       }
+       return nil
+}
+
+// typeModifier represents an operator that changes the expected type.
+type typeModifier struct {
+       mod      typeMod
+       arrayLen int64
+}
+
+type typeMod int
+
+const (
+       dereference typeMod = iota // pointer indirection: "*"
+       reference                  // adds level of pointer: "&" for values, "*" for type names
+       chanRead                   // channel read operator ("<-")
+       slice                      // make a slice type ("[]" in "[]int")
+       array                      // make an array type ("[2]" in "[2]int")
+)
+
+type objKind int
+
+const (
+       kindAny   objKind = 0
+       kindArray objKind = 1 << iota
+       kindSlice
+       kindChan
+       kindMap
+       kindStruct
+       kindString
+       kindInt
+       kindBool
+       kindBytes
+       kindPtr
+       kindFloat
+       kindComplex
+       kindError
+       kindStringer
+       kindFunc
+)
+
+// penalizedObj represents an object that should be disfavored as a
+// completion candidate.
+type penalizedObj struct {
+       // objChain is the full "chain", e.g. "foo.bar().baz" becomes
+       // []types.Object{foo, bar, baz}.
+       objChain []types.Object
+       // penalty is score penalty in the range (0, 1).
+       penalty float64
+}
+
+// candidateInference holds information we have inferred about a type that can be
+// used at the current position.
+type candidateInference struct {
+       // objType is the desired type of an object used at the query position.
+       objType types.Type
+
+       // objKind is a mask of expected kinds of types such as "map", "slice", etc.
+       objKind objKind
+
+       // variadic is true if we are completing the initial variadic
+       // parameter. For example:
+       //   append([]T{}, <>)      // objType=T variadic=true
+       //   append([]T{}, T{}, <>) // objType=T variadic=false
+       variadic bool
+
+       // modifiers are prefixes such as "*", "&" or "<-" that influence how
+       // a candidate type relates to the expected type.
+       modifiers []typeModifier
+
+       // convertibleTo is a type our candidate type must be convertible to.
+       convertibleTo types.Type
+
+       // typeName holds information about the expected type name at
+       // position, if any.
+       typeName typeNameInference
+
+       // assignees are the types that would receive a function call's
+       // results at the position. For example:
+       //
+       // foo := 123
+       // foo, bar := <>
+       //
+       // at "<>", the assignees are [int, <invalid>].
+       assignees []types.Type
+
+       // variadicAssignees is true if we could be completing an inner
+       // function call that fills out an outer function call's variadic
+       // params. For example:
+       //
+       // func foo(int, ...string) {}
+       //
+       // foo(<>)         // variadicAssignees=true
+       // foo(bar<>)      // variadicAssignees=true
+       // foo(bar, baz<>) // variadicAssignees=false
+       variadicAssignees bool
+
+       // penalized holds expressions that should be disfavored as
+       // candidates. For example, it tracks expressions already used in a
+       // switch statement's other cases. Each expression is tracked using
+       // its entire object "chain" allowing differentiation between
+       // "a.foo" and "b.foo" when "a" and "b" are the same type.
+       penalized []penalizedObj
+
+       // objChain contains the chain of objects representing the
+       // surrounding *ast.SelectorExpr. For example, if we are completing
+       // "foo.bar.ba<>", objChain will contain []types.Object{foo, bar}.
+       objChain []types.Object
+}
+
+// typeNameInference holds information about the expected type name at
+// position.
+type typeNameInference struct {
+       // wantTypeName is true if we expect the name of a type.
+       wantTypeName bool
+
+       // modifiers are prefixes such as "*", "&" or "<-" that influence how
+       // a candidate type relates to the expected type.
+       modifiers []typeModifier
+
+       // assertableFrom is a type that must be assertable to our candidate type.
+       assertableFrom types.Type
+
+       // wantComparable is true if we want a comparable type.
+       wantComparable bool
+
+       // seenTypeSwitchCases tracks types that have already been used by
+       // the containing type switch.
+       seenTypeSwitchCases []types.Type
+
+       // compLitType is true if we are completing a composite literal type
+       // name, e.g "foo<>{}".
+       compLitType bool
+}
+
+// expectedCandidate returns information about the expected candidate
+// for an expression at the query position.
+func expectedCandidate(ctx context.Context, c *completer) (inf candidateInference) {
+       inf.typeName = expectTypeName(c)
+
+       if c.enclosingCompositeLiteral != nil {
+               inf.objType = c.expectedCompositeLiteralType()
+       }
+
+Nodes:
+       for i, node := range c.path {
+               switch node := node.(type) {
+               case *ast.BinaryExpr:
+                       // Determine if query position comes from left or right of op.
+                       e := node.X
+                       if c.pos < node.OpPos {
+                               e = node.Y
+                       }
+                       if tv, ok := c.pkg.GetTypesInfo().Types[e]; ok {
+                               switch node.Op {
+                               case token.LAND, token.LOR:
+                                       // Don't infer "bool" type for "&&" or "||". Often you want
+                                       // to compose a boolean expression from non-boolean
+                                       // candidates.
+                               default:
+                                       inf.objType = tv.Type
+                               }
+                               break Nodes
+                       }
+               case *ast.AssignStmt:
+                       // Only rank completions if you are on the right side of the token.
+                       if c.pos > node.TokPos {
+                               i := exprAtPos(c.pos, node.Rhs)
+                               if i >= len(node.Lhs) {
+                                       i = len(node.Lhs) - 1
+                               }
+                               if tv, ok := c.pkg.GetTypesInfo().Types[node.Lhs[i]]; ok {
+                                       inf.objType = tv.Type
+                               }
+
+                               // If we have a single expression on the RHS, record the LHS
+                               // assignees so we can favor multi-return function calls with
+                               // matching result values.
+                               if len(node.Rhs) <= 1 {
+                                       for _, lhs := range node.Lhs {
+                                               inf.assignees = append(inf.assignees, c.pkg.GetTypesInfo().TypeOf(lhs))
+                                       }
+                               } else {
+                                       // Otherwse, record our single assignee, even if its type is
+                                       // not available. We use this info to downrank functions
+                                       // with the wrong number of result values.
+                                       inf.assignees = append(inf.assignees, c.pkg.GetTypesInfo().TypeOf(node.Lhs[i]))
+                               }
+                       }
+                       return inf
+               case *ast.ValueSpec:
+                       if node.Type != nil && c.pos > node.Type.End() {
+                               inf.objType = c.pkg.GetTypesInfo().TypeOf(node.Type)
+                       }
+                       return inf
+               case *ast.CallExpr:
+                       // Only consider CallExpr args if position falls between parens.
+                       if node.Lparen < c.pos && c.pos <= node.Rparen {
+                               // For type conversions like "int64(foo)" we can only infer our
+                               // desired type is convertible to int64.
+                               if typ := typeConversion(node, c.pkg.GetTypesInfo()); typ != nil {
+                                       inf.convertibleTo = typ
+                                       break Nodes
+                               }
+
+                               if tv, ok := c.pkg.GetTypesInfo().Types[node.Fun]; ok {
+                                       if sig, ok := tv.Type.(*types.Signature); ok {
+                                               numParams := sig.Params().Len()
+                                               if numParams == 0 {
+                                                       return inf
+                                               }
+
+                                               exprIdx := exprAtPos(c.pos, node.Args)
+
+                                               // If we have one or zero arg expressions, we may be
+                                               // completing to a function call that returns multiple
+                                               // values, in turn getting passed in to the surrounding
+                                               // call. Record the assignees so we can favor function
+                                               // calls that return matching values.
+                                               if len(node.Args) <= 1 && exprIdx == 0 {
+                                                       for i := 0; i < sig.Params().Len(); i++ {
+                                                               inf.assignees = append(inf.assignees, sig.Params().At(i).Type())
+                                                       }
+
+                                                       // Record that we may be completing into variadic parameters.
+                                                       inf.variadicAssignees = sig.Variadic()
+                                               }
+
+                                               // Make sure not to run past the end of expected parameters.
+                                               if exprIdx >= numParams {
+                                                       inf.objType = sig.Params().At(numParams - 1).Type()
+                                               } else {
+                                                       inf.objType = sig.Params().At(exprIdx).Type()
+                                               }
+
+                                               if sig.Variadic() && exprIdx >= (numParams-1) {
+                                                       // If we are completing a variadic param, deslice the variadic type.
+                                                       inf.objType = deslice(inf.objType)
+                                                       // Record whether we are completing the initial variadic param.
+                                                       inf.variadic = exprIdx == numParams-1 && len(node.Args) <= numParams
+
+                                                       // Check if we can infer object kind from printf verb.
+                                                       inf.objKind |= printfArgKind(c.pkg.GetTypesInfo(), node, exprIdx)
+                                               }
+                                       }
+                               }
+
+                               if funIdent, ok := node.Fun.(*ast.Ident); ok {
+                                       obj := c.pkg.GetTypesInfo().ObjectOf(funIdent)
+
+                                       if obj != nil && obj.Parent() == types.Universe {
+                                               // Defer call to builtinArgType so we can provide it the
+                                               // inferred type from its parent node.
+                                               defer func() {
+                                                       inf = c.builtinArgType(obj, node, inf)
+                                                       inf.objKind = c.builtinArgKind(ctx, obj, node)
+                                               }()
+
+                                               // The expected type of builtin arguments like append() is
+                                               // the expected type of the builtin call itself. For
+                                               // example:
+                                               //
+                                               // var foo []int = append(<>)
+                                               //
+                                               // To find the expected type at <> we "skip" the append()
+                                               // node and get the expected type one level up, which is
+                                               // []int.
+                                               continue Nodes
+                                       }
+                               }
+
+                               return inf
+                       }
+               case *ast.ReturnStmt:
+                       if c.enclosingFunc != nil {
+                               sig := c.enclosingFunc.sig
+                               // Find signature result that corresponds to our return statement.
+                               if resultIdx := exprAtPos(c.pos, node.Results); resultIdx < len(node.Results) {
+                                       if resultIdx < sig.Results().Len() {
+                                               inf.objType = sig.Results().At(resultIdx).Type()
+                                       }
+                               }
+                       }
+                       return inf
+               case *ast.CaseClause:
+                       if swtch, ok := findSwitchStmt(c.path[i+1:], c.pos, node).(*ast.SwitchStmt); ok {
+                               if tv, ok := c.pkg.GetTypesInfo().Types[swtch.Tag]; ok {
+                                       inf.objType = tv.Type
+
+                                       // Record which objects have already been used in the case
+                                       // statements so we don't suggest them again.
+                                       for _, cc := range swtch.Body.List {
+                                               for _, caseExpr := range cc.(*ast.CaseClause).List {
+                                                       // Don't record the expression we are currently completing.
+                                                       if caseExpr.Pos() < c.pos && c.pos <= caseExpr.End() {
+                                                               continue
+                                                       }
+
+                                                       if objs := objChain(c.pkg.GetTypesInfo(), caseExpr); len(objs) > 0 {
+                                                               inf.penalized = append(inf.penalized, penalizedObj{objChain: objs, penalty: 0.1})
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       return inf
+               case *ast.SliceExpr:
+                       // Make sure position falls within the brackets (e.g. "foo[a:<>]").
+                       if node.Lbrack < c.pos && c.pos <= node.Rbrack {
+                               inf.objType = types.Typ[types.Int]
+                       }
+                       return inf
+               case *ast.IndexExpr:
+                       // Make sure position falls within the brackets (e.g. "foo[<>]").
+                       if node.Lbrack < c.pos && c.pos <= node.Rbrack {
+                               if tv, ok := c.pkg.GetTypesInfo().Types[node.X]; ok {
+                                       switch t := tv.Type.Underlying().(type) {
+                                       case *types.Map:
+                                               inf.objType = t.Key()
+                                       case *types.Slice, *types.Array:
+                                               inf.objType = types.Typ[types.Int]
+                                       }
+                               }
+                       }
+                       return inf
+               case *ast.SendStmt:
+                       // Make sure we are on right side of arrow (e.g. "foo <- <>").
+                       if c.pos > node.Arrow+1 {
+                               if tv, ok := c.pkg.GetTypesInfo().Types[node.Chan]; ok {
+                                       if ch, ok := tv.Type.Underlying().(*types.Chan); ok {
+                                               inf.objType = ch.Elem()
+                                       }
+                               }
+                       }
+                       return inf
+               case *ast.RangeStmt:
+                       if source.NodeContains(node.X, c.pos) {
+                               inf.objKind |= kindSlice | kindArray | kindMap | kindString
+                               if node.Value == nil {
+                                       inf.objKind |= kindChan
+                               }
+                       }
+                       return inf
+               case *ast.StarExpr:
+                       inf.modifiers = append(inf.modifiers, typeModifier{mod: dereference})
+               case *ast.UnaryExpr:
+                       switch node.Op {
+                       case token.AND:
+                               inf.modifiers = append(inf.modifiers, typeModifier{mod: reference})
+                       case token.ARROW:
+                               inf.modifiers = append(inf.modifiers, typeModifier{mod: chanRead})
+                       }
+               case *ast.DeferStmt, *ast.GoStmt:
+                       inf.objKind |= kindFunc
+                       return inf
+               default:
+                       if breaksExpectedTypeInference(node, c.pos) {
+                               return inf
+                       }
+               }
+       }
+
+       return inf
+}
+
+// objChain decomposes e into a chain of objects if possible. For
+// example, "foo.bar().baz" will yield []types.Object{foo, bar, baz}.
+// If any part can't be turned into an object, return nil.
+func objChain(info *types.Info, e ast.Expr) []types.Object {
+       var objs []types.Object
+
+       for e != nil {
+               switch n := e.(type) {
+               case *ast.Ident:
+                       obj := info.ObjectOf(n)
+                       if obj == nil {
+                               return nil
+                       }
+                       objs = append(objs, obj)
+                       e = nil
+               case *ast.SelectorExpr:
+                       obj := info.ObjectOf(n.Sel)
+                       if obj == nil {
+                               return nil
+                       }
+                       objs = append(objs, obj)
+                       e = n.X
+               case *ast.CallExpr:
+                       if len(n.Args) > 0 {
+                               return nil
+                       }
+                       e = n.Fun
+               default:
+                       return nil
+               }
+       }
+
+       // Reverse order so the layout matches the syntactic order.
+       for i := 0; i < len(objs)/2; i++ {
+               objs[i], objs[len(objs)-1-i] = objs[len(objs)-1-i], objs[i]
+       }
+
+       return objs
+}
+
+// applyTypeModifiers applies the list of type modifiers to a type.
+// It returns nil if the modifiers could not be applied.
+func (ci candidateInference) applyTypeModifiers(typ types.Type, addressable bool) types.Type {
+       for _, mod := range ci.modifiers {
+               switch mod.mod {
+               case dereference:
+                       // For every "*" indirection operator, remove a pointer layer
+                       // from candidate type.
+                       if ptr, ok := typ.Underlying().(*types.Pointer); ok {
+                               typ = ptr.Elem()
+                       } else {
+                               return nil
+                       }
+               case reference:
+                       // For every "&" address operator, add another pointer layer to
+                       // candidate type, if the candidate is addressable.
+                       if addressable {
+                               typ = types.NewPointer(typ)
+                       } else {
+                               return nil
+                       }
+               case chanRead:
+                       // For every "<-" operator, remove a layer of channelness.
+                       if ch, ok := typ.(*types.Chan); ok {
+                               typ = ch.Elem()
+                       } else {
+                               return nil
+                       }
+               }
+       }
+
+       return typ
+}
+
+// applyTypeNameModifiers applies the list of type modifiers to a type name.
+func (ci candidateInference) applyTypeNameModifiers(typ types.Type) types.Type {
+       for _, mod := range ci.typeName.modifiers {
+               switch mod.mod {
+               case reference:
+                       typ = types.NewPointer(typ)
+               case array:
+                       typ = types.NewArray(typ, mod.arrayLen)
+               case slice:
+                       typ = types.NewSlice(typ)
+               }
+       }
+       return typ
+}
+
+// matchesVariadic returns true if we are completing a variadic
+// parameter and candType is a compatible slice type.
+func (ci candidateInference) matchesVariadic(candType types.Type) bool {
+       return ci.variadic && ci.objType != nil && types.AssignableTo(candType, types.NewSlice(ci.objType))
+}
+
+// findSwitchStmt returns an *ast.CaseClause's corresponding *ast.SwitchStmt or
+// *ast.TypeSwitchStmt. path should start from the case clause's first ancestor.
+func findSwitchStmt(path []ast.Node, pos token.Pos, c *ast.CaseClause) ast.Stmt {
+       // Make sure position falls within a "case <>:" clause.
+       if exprAtPos(pos, c.List) >= len(c.List) {
+               return nil
+       }
+       // A case clause is always nested within a block statement in a switch statement.
+       if len(path) < 2 {
+               return nil
+       }
+       if _, ok := path[0].(*ast.BlockStmt); !ok {
+               return nil
+       }
+       switch s := path[1].(type) {
+       case *ast.SwitchStmt:
+               return s
+       case *ast.TypeSwitchStmt:
+               return s
+       default:
+               return nil
+       }
+}
+
+// breaksExpectedTypeInference reports if an expression node's type is unrelated
+// to its child expression node types. For example, "Foo{Bar: x.Baz(<>)}" should
+// expect a function argument, not a composite literal value.
+func breaksExpectedTypeInference(n ast.Node, pos token.Pos) bool {
+       switch n := n.(type) {
+       case *ast.CompositeLit:
+               // Doesn't break inference if pos is in type name.
+               // For example: "Foo<>{Bar: 123}"
+               return !source.NodeContains(n.Type, pos)
+       case *ast.CallExpr:
+               // Doesn't break inference if pos is in func name.
+               // For example: "Foo<>(123)"
+               return !source.NodeContains(n.Fun, pos)
+       case *ast.FuncLit, *ast.IndexExpr, *ast.SliceExpr:
+               return true
+       default:
+               return false
+       }
+}
+
+// expectTypeName returns information about the expected type name at position.
+func expectTypeName(c *completer) typeNameInference {
+       var inf typeNameInference
+
+Nodes:
+       for i, p := range c.path {
+               switch n := p.(type) {
+               case *ast.FieldList:
+                       // Expect a type name if pos is in a FieldList. This applies to
+                       // FuncType params/results, FuncDecl receiver, StructType, and
+                       // InterfaceType. We don't need to worry about the field name
+                       // because completion bails out early if pos is in an *ast.Ident
+                       // that defines an object.
+                       inf.wantTypeName = true
+                       break Nodes
+               case *ast.CaseClause:
+                       // Expect type names in type switch case clauses.
+                       if swtch, ok := findSwitchStmt(c.path[i+1:], c.pos, n).(*ast.TypeSwitchStmt); ok {
+                               // The case clause types must be assertable from the type switch parameter.
+                               ast.Inspect(swtch.Assign, func(n ast.Node) bool {
+                                       if ta, ok := n.(*ast.TypeAssertExpr); ok {
+                                               inf.assertableFrom = c.pkg.GetTypesInfo().TypeOf(ta.X)
+                                               return false
+                                       }
+                                       return true
+                               })
+                               inf.wantTypeName = true
+
+                               // Track the types that have already been used in this
+                               // switch's case statements so we don't recommend them.
+                               for _, e := range swtch.Body.List {
+                                       for _, typeExpr := range e.(*ast.CaseClause).List {
+                                               // Skip if type expression contains pos. We don't want to
+                                               // count it as already used if the user is completing it.
+                                               if typeExpr.Pos() < c.pos && c.pos <= typeExpr.End() {
+                                                       continue
+                                               }
+
+                                               if t := c.pkg.GetTypesInfo().TypeOf(typeExpr); t != nil {
+                                                       inf.seenTypeSwitchCases = append(inf.seenTypeSwitchCases, t)
+                                               }
+                                       }
+                               }
+
+                               break Nodes
+                       }
+                       return typeNameInference{}
+               case *ast.TypeAssertExpr:
+                       // Expect type names in type assert expressions.
+                       if n.Lparen < c.pos && c.pos <= n.Rparen {
+                               // The type in parens must be assertable from the expression type.
+                               inf.assertableFrom = c.pkg.GetTypesInfo().TypeOf(n.X)
+                               inf.wantTypeName = true
+                               break Nodes
+                       }
+                       return typeNameInference{}
+               case *ast.StarExpr:
+                       inf.modifiers = append(inf.modifiers, typeModifier{mod: reference})
+               case *ast.CompositeLit:
+                       // We want a type name if position is in the "Type" part of a
+                       // composite literal (e.g. "Foo<>{}").
+                       if n.Type != nil && n.Type.Pos() <= c.pos && c.pos <= n.Type.End() {
+                               inf.wantTypeName = true
+                               inf.compLitType = true
+
+                               if i < len(c.path)-1 {
+                                       // Track preceding "&" operator. Technically it applies to
+                                       // the composite literal and not the type name, but if
+                                       // affects our type completion nonetheless.
+                                       if u, ok := c.path[i+1].(*ast.UnaryExpr); ok && u.Op == token.AND {
+                                               inf.modifiers = append(inf.modifiers, typeModifier{mod: reference})
+                                       }
+                               }
+                       }
+                       break Nodes
+               case *ast.ArrayType:
+                       // If we are inside the "Elt" part of an array type, we want a type name.
+                       if n.Elt.Pos() <= c.pos && c.pos <= n.Elt.End() {
+                               inf.wantTypeName = true
+                               if n.Len == nil {
+                                       // No "Len" expression means a slice type.
+                                       inf.modifiers = append(inf.modifiers, typeModifier{mod: slice})
+                               } else {
+                                       // Try to get the array type using the constant value of "Len".
+                                       tv, ok := c.pkg.GetTypesInfo().Types[n.Len]
+                                       if ok && tv.Value != nil && tv.Value.Kind() == constant.Int {
+                                               if arrayLen, ok := constant.Int64Val(tv.Value); ok {
+                                                       inf.modifiers = append(inf.modifiers, typeModifier{mod: array, arrayLen: arrayLen})
+                                               }
+                                       }
+                               }
+
+                               // ArrayTypes can be nested, so keep going if our parent is an
+                               // ArrayType.
+                               if i < len(c.path)-1 {
+                                       if _, ok := c.path[i+1].(*ast.ArrayType); ok {
+                                               continue Nodes
+                                       }
+                               }
+
+                               break Nodes
+                       }
+               case *ast.MapType:
+                       inf.wantTypeName = true
+                       if n.Key != nil {
+                               inf.wantComparable = source.NodeContains(n.Key, c.pos)
+                       } else {
+                               // If the key is empty, assume we are completing the key if
+                               // pos is directly after the "map[".
+                               inf.wantComparable = c.pos == n.Pos()+token.Pos(len("map["))
+                       }
+                       break Nodes
+               case *ast.ValueSpec:
+                       inf.wantTypeName = source.NodeContains(n.Type, c.pos)
+                       break Nodes
+               case *ast.TypeSpec:
+                       inf.wantTypeName = source.NodeContains(n.Type, c.pos)
+               default:
+                       if breaksExpectedTypeInference(p, c.pos) {
+                               return typeNameInference{}
+                       }
+               }
+       }
+
+       return inf
+}
+
+func (c *completer) fakeObj(T types.Type) *types.Var {
+       return types.NewVar(token.NoPos, c.pkg.GetTypes(), "", T)
+}
+
+// anyCandType reports whether f returns true for any candidate type
+// derivable from c. For example, from "foo" we might derive "&foo",
+// and "foo()".
+func (c *candidate) anyCandType(f func(t types.Type, addressable bool) bool) bool {
+       if c.obj == nil || c.obj.Type() == nil {
+               return false
+       }
+
+       objType := c.obj.Type()
+
+       if f(objType, c.addressable) {
+               return true
+       }
+
+       // If c is a func type with a single result, offer the result type.
+       if sig, ok := objType.Underlying().(*types.Signature); ok {
+               if sig.Results().Len() == 1 && f(sig.Results().At(0).Type(), false) {
+                       // Mark the candidate so we know to append "()" when formatting.
+                       c.expandFuncCall = true
+                       return true
+               }
+       }
+
+       var (
+               seenPtrTypes map[types.Type]bool
+               ptrType      = objType
+               ptrDepth     int
+       )
+
+       // Check if dereferencing c would match our type inference. We loop
+       // since c could have arbitrary levels of pointerness.
+       for {
+               ptr, ok := ptrType.Underlying().(*types.Pointer)
+               if !ok {
+                       break
+               }
+
+               ptrDepth++
+
+               // Avoid pointer type cycles.
+               if seenPtrTypes[ptrType] {
+                       break
+               }
+
+               if _, named := ptrType.(*types.Named); named {
+                       // Lazily allocate "seen" since it isn't used normally.
+                       if seenPtrTypes == nil {
+                               seenPtrTypes = make(map[types.Type]bool)
+                       }
+
+                       // Track named pointer types we have seen to detect cycles.
+                       seenPtrTypes[ptrType] = true
+               }
+
+               if f(ptr.Elem(), false) {
+                       // Mark the candidate so we know to prepend "*" when formatting.
+                       c.dereference = ptrDepth
+                       return true
+               }
+
+               ptrType = ptr.Elem()
+       }
+
+       // Check if c is addressable and a pointer to c matches our type inference.
+       if c.addressable && f(types.NewPointer(objType), false) {
+               // Mark the candidate so we know to prepend "&" when formatting.
+               c.takeAddress = true
+               return true
+       }
+
+       return false
+}
+
+// matchingCandidate reports whether cand matches our type inferences.
+// It mutates cand's score in certain cases.
+func (c *completer) matchingCandidate(cand *candidate) bool {
+       if c.completionContext.commentCompletion {
+               return false
+       }
+
+       if isTypeName(cand.obj) {
+               return c.matchingTypeName(cand)
+       } else if c.wantTypeName() {
+               // If we want a type, a non-type object never matches.
+               return false
+       }
+
+       if c.inference.candTypeMatches(cand) {
+               return true
+       }
+
+       candType := cand.obj.Type()
+       if candType == nil {
+               return false
+       }
+
+       if sig, ok := candType.Underlying().(*types.Signature); ok {
+               if c.inference.assigneesMatch(cand, sig) {
+                       // Invoke the candidate if its results are multi-assignable.
+                       cand.expandFuncCall = true
+                       return true
+               }
+       }
+
+       // Default to invoking *types.Func candidates. This is so function
+       // completions in an empty statement (or other cases with no expected type)
+       // are invoked by default.
+       cand.expandFuncCall = isFunc(cand.obj)
+
+       return false
+}
+
+// candTypeMatches reports whether cand makes a good completion
+// candidate given the candidate inference. cand's score may be
+// mutated to downrank the candidate in certain situations.
+func (ci *candidateInference) candTypeMatches(cand *candidate) bool {
+       var (
+               expTypes     = make([]types.Type, 0, 2)
+               variadicType types.Type
+       )
+       if ci.objType != nil {
+               expTypes = append(expTypes, ci.objType)
+
+               if ci.variadic {
+                       variadicType = types.NewSlice(ci.objType)
+                       expTypes = append(expTypes, variadicType)
+               }
+       }
+
+       return cand.anyCandType(func(candType types.Type, addressable bool) bool {
+               // Take into account any type modifiers on the expected type.
+               candType = ci.applyTypeModifiers(candType, addressable)
+               if candType == nil {
+                       return false
+               }
+
+               if ci.convertibleTo != nil && types.ConvertibleTo(candType, ci.convertibleTo) {
+                       return true
+               }
+
+               for _, expType := range expTypes {
+                       if isEmptyInterface(expType) {
+                               continue
+                       }
+
+                       matches, untyped := ci.typeMatches(expType, candType)
+                       if !matches {
+                               continue
+                       }
+
+                       if expType == variadicType {
+                               cand.variadic = true
+                       }
+
+                       // Lower candidate score for untyped conversions. This avoids
+                       // ranking untyped constants above candidates with an exact type
+                       // match. Don't lower score of builtin constants, e.g. "true".
+                       if untyped && !types.Identical(candType, expType) && cand.obj.Parent() != types.Universe {
+                               cand.score /= 2
+                       }
+
+                       return true
+               }
+
+               // If we don't have a specific expected type, fall back to coarser
+               // object kind checks.
+               if ci.objType == nil || isEmptyInterface(ci.objType) {
+                       // If we were able to apply type modifiers to our candidate type,
+                       // count that as a match. For example:
+                       //
+                       //   var foo chan int
+                       //   <-fo<>
+                       //
+                       // We were able to apply the "<-" type modifier to "foo", so "foo"
+                       // matches.
+                       if len(ci.modifiers) > 0 {
+                               return true
+                       }
+
+                       // If we didn't have an exact type match, check if our object kind
+                       // matches.
+                       if ci.kindMatches(candType) {
+                               if ci.objKind == kindFunc {
+                                       cand.expandFuncCall = true
+                               }
+                               return true
+                       }
+               }
+
+               return false
+       })
+}
+
+// typeMatches reports whether an object of candType makes a good
+// completion candidate given the expected type expType. It also
+// returns a second bool which is true if both types are basic types
+// of the same kind, and at least one is untyped.
+func (ci *candidateInference) typeMatches(expType, candType types.Type) (bool, bool) {
+       // Handle untyped values specially since AssignableTo gives false negatives
+       // for them (see https://golang.org/issue/32146).
+       if candBasic, ok := candType.Underlying().(*types.Basic); ok {
+               if wantBasic, ok := expType.Underlying().(*types.Basic); ok {
+                       // Make sure at least one of them is untyped.
+                       if isUntyped(candType) || isUntyped(expType) {
+                               // Check that their constant kind (bool|int|float|complex|string) matches.
+                               // This doesn't take into account the constant value, so there will be some
+                               // false positives due to integer sign and overflow.
+                               if candBasic.Info()&types.IsConstType == wantBasic.Info()&types.IsConstType {
+                                       return true, true
+                               }
+                       }
+               }
+       }
+
+       // AssignableTo covers the case where the types are equal, but also handles
+       // cases like assigning a concrete type to an interface type.
+       return types.AssignableTo(candType, expType), false
+}
+
+// kindMatches reports whether candType's kind matches our expected
+// kind (e.g. slice, map, etc.).
+func (ci *candidateInference) kindMatches(candType types.Type) bool {
+       return ci.objKind > 0 && ci.objKind&candKind(candType) > 0
+}
+
+// assigneesMatch reports whether an invocation of sig matches the
+// number and type of any assignees.
+func (ci *candidateInference) assigneesMatch(cand *candidate, sig *types.Signature) bool {
+       if len(ci.assignees) == 0 {
+               return false
+       }
+
+       // Uniresult functions are always usable and are handled by the
+       // normal, non-assignees type matching logic.
+       if sig.Results().Len() == 1 {
+               return false
+       }
+
+       var numberOfResultsCouldMatch bool
+       if ci.variadicAssignees {
+               numberOfResultsCouldMatch = sig.Results().Len() >= len(ci.assignees)-1
+       } else {
+               numberOfResultsCouldMatch = sig.Results().Len() == len(ci.assignees)
+       }
+
+       // If our signature doesn't return the right number of values, it's
+       // not a match, so downrank it. For example:
+       //
+       //  var foo func() (int, int)
+       //  a, b, c := <> // downrank "foo()" since it only returns two values
+       if !numberOfResultsCouldMatch {
+               cand.score /= 2
+               return false
+       }
+
+       // If at least one assignee has a valid type, and all valid
+       // assignees match the corresponding sig result value, the signature
+       // is a match.
+       allMatch := false
+       for i := 0; i < sig.Results().Len(); i++ {
+               var assignee types.Type
+
+               // If we are completing into variadic parameters, deslice the
+               // expected variadic type.
+               if ci.variadicAssignees && i >= len(ci.assignees)-1 {
+                       assignee = ci.assignees[len(ci.assignees)-1]
+                       if elem := deslice(assignee); elem != nil {
+                               assignee = elem
+                       }
+               } else {
+                       assignee = ci.assignees[i]
+               }
+
+               if assignee == nil {
+                       continue
+               }
+
+               allMatch, _ = ci.typeMatches(assignee, sig.Results().At(i).Type())
+               if !allMatch {
+                       break
+               }
+       }
+       return allMatch
+}
+
+func (c *completer) matchingTypeName(cand *candidate) bool {
+       if !c.wantTypeName() {
+               return false
+       }
+
+       typeMatches := func(candType types.Type) bool {
+               // Take into account any type name modifier prefixes.
+               candType = c.inference.applyTypeNameModifiers(candType)
+
+               if from := c.inference.typeName.assertableFrom; from != nil {
+                       // Don't suggest the starting type in type assertions. For example,
+                       // if "foo" is an io.Writer, don't suggest "foo.(io.Writer)".
+                       if types.Identical(from, candType) {
+                               return false
+                       }
+
+                       if intf, ok := from.Underlying().(*types.Interface); ok {
+                               if !types.AssertableTo(intf, candType) {
+                                       return false
+                               }
+                       }
+               }
+
+               if c.inference.typeName.wantComparable && !types.Comparable(candType) {
+                       return false
+               }
+
+               // Skip this type if it has already been used in another type
+               // switch case.
+               for _, seen := range c.inference.typeName.seenTypeSwitchCases {
+                       if types.Identical(candType, seen) {
+                               return false
+                       }
+               }
+
+               // We can expect a type name and have an expected type in cases like:
+               //
+               //   var foo []int
+               //   foo = []i<>
+               //
+               // Where our expected type is "[]int", and we expect a type name.
+               if c.inference.objType != nil {
+                       return types.AssignableTo(candType, c.inference.objType)
+               }
+
+               // Default to saying any type name is a match.
+               return true
+       }
+
+       t := cand.obj.Type()
+
+       if typeMatches(t) {
+               return true
+       }
+
+       if !source.IsInterface(t) && typeMatches(types.NewPointer(t)) {
+               if c.inference.typeName.compLitType {
+                       // If we are completing a composite literal type as in
+                       // "foo<>{}", to make a pointer we must prepend "&".
+                       cand.takeAddress = true
+               } else {
+                       // If we are completing a normal type name such as "foo<>", to
+                       // make a pointer we must prepend "*".
+                       cand.makePointer = true
+               }
+               return true
+       }
+
+       return false
+}
+
+var (
+       // "interface { Error() string }" (i.e. error)
+       errorIntf = types.Universe.Lookup("error").Type().Underlying().(*types.Interface)
+
+       // "interface { String() string }" (i.e. fmt.Stringer)
+       stringerIntf = types.NewInterfaceType([]*types.Func{
+               types.NewFunc(token.NoPos, nil, "String", types.NewSignature(
+                       nil,
+                       nil,
+                       types.NewTuple(types.NewParam(token.NoPos, nil, "", types.Typ[types.String])),
+                       false,
+               )),
+       }, nil).Complete()
+
+       byteType = types.Universe.Lookup("byte").Type()
+)
+
+// candKind returns the objKind of candType, if any.
+func candKind(candType types.Type) objKind {
+       var kind objKind
+
+       switch t := candType.Underlying().(type) {
+       case *types.Array:
+               kind |= kindArray
+               if t.Elem() == byteType {
+                       kind |= kindBytes
+               }
+       case *types.Slice:
+               kind |= kindSlice
+               if t.Elem() == byteType {
+                       kind |= kindBytes
+               }
+       case *types.Chan:
+               kind |= kindChan
+       case *types.Map:
+               kind |= kindMap
+       case *types.Pointer:
+               kind |= kindPtr
+
+               // Some builtins handle array pointers as arrays, so just report a pointer
+               // to an array as an array.
+               if _, isArray := t.Elem().Underlying().(*types.Array); isArray {
+                       kind |= kindArray
+               }
+       case *types.Basic:
+               switch info := t.Info(); {
+               case info&types.IsString > 0:
+                       kind |= kindString
+               case info&types.IsInteger > 0:
+                       kind |= kindInt
+               case info&types.IsFloat > 0:
+                       kind |= kindFloat
+               case info&types.IsComplex > 0:
+                       kind |= kindComplex
+               case info&types.IsBoolean > 0:
+                       kind |= kindBool
+               }
+       case *types.Signature:
+               return kindFunc
+       }
+
+       if types.Implements(candType, errorIntf) {
+               kind |= kindError
+       }
+
+       if types.Implements(candType, stringerIntf) {
+               kind |= kindStringer
+       }
+
+       return kind
+}