Giant blob of minor changes
[dotfiles/.git] / .config / coc / extensions / coc-go-data / tools / pkg / mod / golang.org / x / tools@v0.0.0-20201028153306-37f0764111ff / internal / lsp / source / signature_help.go
diff --git a/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201028153306-37f0764111ff/internal/lsp/source/signature_help.go b/.config/coc/extensions/coc-go-data/tools/pkg/mod/golang.org/x/tools@v0.0.0-20201028153306-37f0764111ff/internal/lsp/source/signature_help.go
new file mode 100644 (file)
index 0000000..b49880d
--- /dev/null
@@ -0,0 +1,173 @@
+// 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 source
+
+import (
+       "context"
+       "go/ast"
+       "go/doc"
+       "go/token"
+       "go/types"
+
+       "golang.org/x/tools/go/ast/astutil"
+       "golang.org/x/tools/internal/event"
+       "golang.org/x/tools/internal/lsp/protocol"
+       errors "golang.org/x/xerrors"
+)
+
+func SignatureHelp(ctx context.Context, snapshot Snapshot, fh FileHandle, pos protocol.Position) (*protocol.SignatureInformation, int, error) {
+       ctx, done := event.Start(ctx, "source.SignatureHelp")
+       defer done()
+
+       pkg, pgf, err := GetParsedFile(ctx, snapshot, fh, NarrowestPackage)
+       if err != nil {
+               return nil, 0, errors.Errorf("getting file for SignatureHelp: %w", err)
+       }
+       spn, err := pgf.Mapper.PointSpan(pos)
+       if err != nil {
+               return nil, 0, err
+       }
+       rng, err := spn.Range(pgf.Mapper.Converter)
+       if err != nil {
+               return nil, 0, err
+       }
+       // Find a call expression surrounding the query position.
+       var callExpr *ast.CallExpr
+       path, _ := astutil.PathEnclosingInterval(pgf.File, rng.Start, rng.Start)
+       if path == nil {
+               return nil, 0, errors.Errorf("cannot find node enclosing position")
+       }
+FindCall:
+       for _, node := range path {
+               switch node := node.(type) {
+               case *ast.CallExpr:
+                       if rng.Start >= node.Lparen && rng.Start <= node.Rparen {
+                               callExpr = node
+                               break FindCall
+                       }
+               case *ast.FuncLit, *ast.FuncType:
+                       // The user is within an anonymous function,
+                       // which may be the parameter to the *ast.CallExpr.
+                       // Don't show signature help in this case.
+                       return nil, 0, errors.Errorf("no signature help within a function declaration")
+               }
+       }
+       if callExpr == nil || callExpr.Fun == nil {
+               return nil, 0, errors.Errorf("cannot find an enclosing function")
+       }
+
+       qf := Qualifier(pgf.File, pkg.GetTypes(), pkg.GetTypesInfo())
+
+       // Get the object representing the function, if available.
+       // There is no object in certain cases such as calling a function returned by
+       // a function (e.g. "foo()()").
+       var obj types.Object
+       switch t := callExpr.Fun.(type) {
+       case *ast.Ident:
+               obj = pkg.GetTypesInfo().ObjectOf(t)
+       case *ast.SelectorExpr:
+               obj = pkg.GetTypesInfo().ObjectOf(t.Sel)
+       }
+
+       // Handle builtin functions separately.
+       if obj, ok := obj.(*types.Builtin); ok {
+               return builtinSignature(ctx, snapshot, callExpr, obj.Name(), rng.Start)
+       }
+
+       // Get the type information for the function being called.
+       sigType := pkg.GetTypesInfo().TypeOf(callExpr.Fun)
+       if sigType == nil {
+               return nil, 0, errors.Errorf("cannot get type for Fun %[1]T (%[1]v)", callExpr.Fun)
+       }
+
+       sig, _ := sigType.Underlying().(*types.Signature)
+       if sig == nil {
+               return nil, 0, errors.Errorf("cannot find signature for Fun %[1]T (%[1]v)", callExpr.Fun)
+       }
+
+       activeParam := activeParameter(callExpr, sig.Params().Len(), sig.Variadic(), rng.Start)
+
+       var (
+               name    string
+               comment *ast.CommentGroup
+       )
+       if obj != nil {
+               node, err := objToDecl(ctx, snapshot, pkg, obj)
+               if err != nil {
+                       return nil, 0, err
+               }
+               rng, err := objToMappedRange(snapshot, pkg, obj)
+               if err != nil {
+                       return nil, 0, err
+               }
+               decl := Declaration{
+                       obj:  obj,
+                       node: node,
+               }
+               decl.MappedRange = append(decl.MappedRange, rng)
+               d, err := HoverInfo(ctx, pkg, decl.obj, decl.node)
+               if err != nil {
+                       return nil, 0, err
+               }
+               name = obj.Name()
+               comment = d.comment
+       } else {
+               name = "func"
+       }
+       s := NewSignature(ctx, snapshot, pkg, sig, comment, qf)
+       paramInfo := make([]protocol.ParameterInformation, 0, len(s.params))
+       for _, p := range s.params {
+               paramInfo = append(paramInfo, protocol.ParameterInformation{Label: p})
+       }
+       return &protocol.SignatureInformation{
+               Label:         name + s.Format(),
+               Documentation: doc.Synopsis(s.doc),
+               Parameters:    paramInfo,
+       }, activeParam, nil
+}
+
+func builtinSignature(ctx context.Context, snapshot Snapshot, callExpr *ast.CallExpr, name string, pos token.Pos) (*protocol.SignatureInformation, int, error) {
+       sig, err := NewBuiltinSignature(ctx, snapshot, name)
+       if err != nil {
+               return nil, 0, err
+       }
+       paramInfo := make([]protocol.ParameterInformation, 0, len(sig.params))
+       for _, p := range sig.params {
+               paramInfo = append(paramInfo, protocol.ParameterInformation{Label: p})
+       }
+       activeParam := activeParameter(callExpr, len(sig.params), sig.variadic, pos)
+       return &protocol.SignatureInformation{
+               Label:         sig.name + sig.Format(),
+               Documentation: doc.Synopsis(sig.doc),
+               Parameters:    paramInfo,
+       }, activeParam, nil
+
+}
+
+func activeParameter(callExpr *ast.CallExpr, numParams int, variadic bool, pos token.Pos) (activeParam int) {
+       if len(callExpr.Args) == 0 {
+               return 0
+       }
+       // First, check if the position is even in the range of the arguments.
+       start, end := callExpr.Lparen, callExpr.Rparen
+       if !(start <= pos && pos <= end) {
+               return 0
+       }
+       for _, expr := range callExpr.Args {
+               if start == token.NoPos {
+                       start = expr.Pos()
+               }
+               end = expr.End()
+               if start <= pos && pos <= end {
+                       break
+               }
+               // Don't advance the active parameter for the last parameter of a variadic function.
+               if !variadic || activeParam < numParams-1 {
+                       activeParam++
+               }
+               start = expr.Pos() + 1 // to account for commas
+       }
+       return activeParam
+}