.gitignore added
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.1.0 / internal / lsp / source / completion / format.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.0/internal/lsp/source/completion/format.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.1.0/internal/lsp/source/completion/format.go
new file mode 100644 (file)
index 0000000..bf47a1d
--- /dev/null
@@ -0,0 +1,295 @@
+// Copyright 2019 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
+
+import (
+       "context"
+       "fmt"
+       "go/types"
+       "strings"
+
+       "golang.org/x/tools/internal/event"
+       "golang.org/x/tools/internal/imports"
+       "golang.org/x/tools/internal/lsp/debug/tag"
+       "golang.org/x/tools/internal/lsp/protocol"
+       "golang.org/x/tools/internal/lsp/snippet"
+       "golang.org/x/tools/internal/lsp/source"
+       "golang.org/x/tools/internal/span"
+       errors "golang.org/x/xerrors"
+)
+
+// item formats a candidate to a CompletionItem.
+func (c *completer) item(ctx context.Context, cand candidate) (CompletionItem, error) {
+       obj := cand.obj
+
+       // if the object isn't a valid match against the surrounding, return early.
+       matchScore := c.matcher.Score(cand.name)
+       if matchScore <= 0 {
+               return CompletionItem{}, errors.New("not a surrounding match")
+       }
+       cand.score *= float64(matchScore)
+
+       // Ignore deep candidates that wont be in the MaxDeepCompletions anyway.
+       if len(cand.path) != 0 && !c.deepState.isHighScore(cand.score) {
+               return CompletionItem{}, errors.New("not a high scoring candidate")
+       }
+
+       // Handle builtin types separately.
+       if obj.Parent() == types.Universe {
+               return c.formatBuiltin(ctx, cand)
+       }
+
+       var (
+               label         = cand.name
+               detail        = types.TypeString(obj.Type(), c.qf)
+               insert        = label
+               kind          = protocol.TextCompletion
+               snip          *snippet.Builder
+               protocolEdits []protocol.TextEdit
+       )
+       if obj.Type() == nil {
+               detail = ""
+       }
+
+       // expandFuncCall mutates the completion label, detail, and snippet
+       // to that of an invocation of sig.
+       expandFuncCall := func(sig *types.Signature) {
+               s := source.NewSignature(ctx, c.snapshot, c.pkg, sig, nil, c.qf)
+               snip = c.functionCallSnippet(label, s.Params())
+               detail = "func" + s.Format()
+       }
+
+       switch obj := obj.(type) {
+       case *types.TypeName:
+               detail, kind = source.FormatType(obj.Type(), c.qf)
+       case *types.Const:
+               kind = protocol.ConstantCompletion
+       case *types.Var:
+               if _, ok := obj.Type().(*types.Struct); ok {
+                       detail = "struct{...}" // for anonymous structs
+               } else if obj.IsField() {
+                       detail = source.FormatVarType(ctx, c.snapshot, c.pkg, obj, c.qf)
+               }
+               if obj.IsField() {
+                       kind = protocol.FieldCompletion
+                       snip = c.structFieldSnippet(cand, label, detail)
+               } else {
+                       kind = protocol.VariableCompletion
+               }
+               if obj.Type() == nil {
+                       break
+               }
+
+               if sig, ok := obj.Type().Underlying().(*types.Signature); ok && cand.expandFuncCall {
+                       expandFuncCall(sig)
+               }
+       case *types.Func:
+               sig, ok := obj.Type().Underlying().(*types.Signature)
+               if !ok {
+                       break
+               }
+               kind = protocol.FunctionCompletion
+               if sig != nil && sig.Recv() != nil {
+                       kind = protocol.MethodCompletion
+               }
+
+               if cand.expandFuncCall {
+                       expandFuncCall(sig)
+               }
+       case *types.PkgName:
+               kind = protocol.ModuleCompletion
+               detail = fmt.Sprintf("%q", obj.Imported().Path())
+       case *types.Label:
+               kind = protocol.ConstantCompletion
+               detail = "label"
+       }
+
+       // If this candidate needs an additional import statement,
+       // add the additional text edits needed.
+       if cand.imp != nil {
+               addlEdits, err := c.importEdits(cand.imp)
+               if err != nil {
+                       return CompletionItem{}, err
+               }
+
+               protocolEdits = append(protocolEdits, addlEdits...)
+               if kind != protocol.ModuleCompletion {
+                       if detail != "" {
+                               detail += " "
+                       }
+                       detail += fmt.Sprintf("(from %q)", cand.imp.importPath)
+               }
+       }
+
+       var prefix, suffix string
+
+       // Prepend "&" or "*" operator as appropriate.
+       if cand.takeAddress {
+               prefix = "&"
+       } else if cand.makePointer {
+               prefix = "*"
+       } else if cand.dereference > 0 {
+               prefix = strings.Repeat("*", cand.dereference)
+       }
+
+       // Include "*" and "&" prefixes in the label.
+       label = prefix + label
+
+       if cand.convertTo != nil {
+               typeName := types.TypeString(cand.convertTo, c.qf)
+
+               switch cand.convertTo.(type) {
+               // We need extra parens when casting to these types. For example,
+               // we need "(*int)(foo)", not "*int(foo)".
+               case *types.Pointer, *types.Signature:
+                       typeName = "(" + typeName + ")"
+               }
+
+               prefix = typeName + "(" + prefix
+               suffix = ")"
+       }
+
+       // Add variadic "..." if we are filling in a variadic param.
+       if cand.variadic {
+               suffix += "..."
+       }
+
+       if prefix != "" {
+               // If we are in a selector, add an edit to place prefix before selector.
+               if sel := enclosingSelector(c.path, c.pos); sel != nil {
+                       edits, err := prependEdit(c.snapshot.FileSet(), c.mapper, sel, prefix)
+                       if err != nil {
+                               return CompletionItem{}, err
+                       }
+                       protocolEdits = append(protocolEdits, edits...)
+               } else {
+                       // If there is no selector, just stick the prefix at the start.
+                       insert = prefix + insert
+                       if snip != nil {
+                               snip.PrependText(prefix)
+                       }
+               }
+       }
+
+       if suffix != "" {
+               insert += suffix
+               if snip != nil {
+                       snip.WriteText(suffix)
+               }
+       }
+
+       detail = strings.TrimPrefix(detail, "untyped ")
+       // override computed detail with provided detail, if something is provided.
+       if cand.detail != "" {
+               detail = cand.detail
+       }
+       item := CompletionItem{
+               Label:               label,
+               InsertText:          insert,
+               AdditionalTextEdits: protocolEdits,
+               Detail:              detail,
+               Kind:                kind,
+               Score:               cand.score,
+               Depth:               len(cand.path),
+               snippet:             snip,
+               obj:                 obj,
+       }
+       // If the user doesn't want documentation for completion items.
+       if !c.opts.documentation {
+               return item, nil
+       }
+       pos := c.snapshot.FileSet().Position(obj.Pos())
+
+       // We ignore errors here, because some types, like "unsafe" or "error",
+       // may not have valid positions that we can use to get documentation.
+       if !pos.IsValid() {
+               return item, nil
+       }
+       uri := span.URIFromPath(pos.Filename)
+
+       // Find the source file of the candidate, starting from a package
+       // that should have it in its dependencies.
+       searchPkg := c.pkg
+       if cand.imp != nil && cand.imp.pkg != nil {
+               searchPkg = cand.imp.pkg
+       }
+
+       pgf, pkg, err := source.FindPosInPackage(c.snapshot, searchPkg, obj.Pos())
+       if err != nil {
+               return item, nil
+       }
+
+       posToDecl, err := c.snapshot.PosToDecl(ctx, pgf)
+       if err != nil {
+               return CompletionItem{}, err
+       }
+       decl := posToDecl[obj.Pos()]
+       if decl == nil {
+               return item, nil
+       }
+
+       hover, err := source.HoverInfo(ctx, pkg, obj, decl)
+       if err != nil {
+               event.Error(ctx, "failed to find Hover", err, tag.URI.Of(uri))
+               return item, nil
+       }
+       item.Documentation = hover.Synopsis
+       if c.opts.fullDocumentation {
+               item.Documentation = hover.FullDocumentation
+       }
+
+       return item, nil
+}
+
+// importEdits produces the text edits necessary to add the given import to the current file.
+func (c *completer) importEdits(imp *importInfo) ([]protocol.TextEdit, error) {
+       if imp == nil {
+               return nil, nil
+       }
+
+       pgf, err := c.pkg.File(span.URIFromPath(c.filename))
+       if err != nil {
+               return nil, err
+       }
+
+       return source.ComputeOneImportFixEdits(c.snapshot, pgf, &imports.ImportFix{
+               StmtInfo: imports.ImportInfo{
+                       ImportPath: imp.importPath,
+                       Name:       imp.name,
+               },
+               // IdentName is unused on this path and is difficult to get.
+               FixType: imports.AddImport,
+       })
+}
+
+func (c *completer) formatBuiltin(ctx context.Context, cand candidate) (CompletionItem, error) {
+       obj := cand.obj
+       item := CompletionItem{
+               Label:      obj.Name(),
+               InsertText: obj.Name(),
+               Score:      cand.score,
+       }
+       switch obj.(type) {
+       case *types.Const:
+               item.Kind = protocol.ConstantCompletion
+       case *types.Builtin:
+               item.Kind = protocol.FunctionCompletion
+               sig, err := source.NewBuiltinSignature(ctx, c.snapshot, obj.Name())
+               if err != nil {
+                       return CompletionItem{}, err
+               }
+               item.Detail = "func" + sig.Format()
+               item.snippet = c.functionCallSnippet(obj.Name(), sig.Params())
+       case *types.TypeName:
+               if types.IsInterface(obj.Type()) {
+                       item.Kind = protocol.InterfaceCompletion
+               } else {
+                       item.Kind = protocol.ClassCompletion
+               }
+       case *types.Nil:
+               item.Kind = protocol.VariableCompletion
+       }
+       return item, nil
+}