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 / snippet.go
1 // Copyright 2019 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 package completion
6
7 import (
8         "go/ast"
9
10         "golang.org/x/tools/internal/lsp/snippet"
11 )
12
13 // structFieldSnippets calculates the snippet for struct literal field names.
14 func (c *completer) structFieldSnippet(cand candidate, label, detail string) *snippet.Builder {
15         if !c.wantStructFieldCompletions() {
16                 return nil
17         }
18
19         // If we are in a deep completion then we can't be completing a field
20         // name (e.g. "Foo{f<>}" completing to "Foo{f.Bar}" should not generate
21         // a snippet).
22         if len(cand.path) > 0 {
23                 return nil
24         }
25
26         clInfo := c.enclosingCompositeLiteral
27
28         // If we are already in a key-value expression, we don't want a snippet.
29         if clInfo.kv != nil {
30                 return nil
31         }
32
33         snip := &snippet.Builder{}
34
35         // A plain snippet turns "Foo{Ba<>" into "Foo{Bar: <>".
36         snip.WriteText(label + ": ")
37         snip.WritePlaceholder(func(b *snippet.Builder) {
38                 // A placeholder snippet turns "Foo{Ba<>" into "Foo{Bar: <*int*>".
39                 if c.opts.placeholders {
40                         b.WriteText(detail)
41                 }
42         })
43
44         fset := c.snapshot.FileSet()
45
46         // If the cursor position is on a different line from the literal's opening brace,
47         // we are in a multiline literal.
48         if fset.Position(c.pos).Line != fset.Position(clInfo.cl.Lbrace).Line {
49                 snip.WriteText(",")
50         }
51
52         return snip
53 }
54
55 // functionCallSnippets calculates the snippet for function calls.
56 func (c *completer) functionCallSnippet(name string, params []string) *snippet.Builder {
57         // If there is no suffix then we need to reuse existing call parens
58         // "()" if present. If there is an identifier suffix then we always
59         // need to include "()" since we don't overwrite the suffix.
60         if c.surrounding != nil && c.surrounding.Suffix() == "" && len(c.path) > 1 {
61                 // If we are the left side (i.e. "Fun") part of a call expression,
62                 // we don't want a snippet since there are already parens present.
63                 switch n := c.path[1].(type) {
64                 case *ast.CallExpr:
65                         // The Lparen != Rparen check detects fudged CallExprs we
66                         // inserted when fixing the AST. In this case, we do still need
67                         // to insert the calling "()" parens.
68                         if n.Fun == c.path[0] && n.Lparen != n.Rparen {
69                                 return nil
70                         }
71                 case *ast.SelectorExpr:
72                         if len(c.path) > 2 {
73                                 if call, ok := c.path[2].(*ast.CallExpr); ok && call.Fun == c.path[1] && call.Lparen != call.Rparen {
74                                         return nil
75                                 }
76                         }
77                 }
78         }
79         snip := &snippet.Builder{}
80         snip.WriteText(name + "(")
81
82         if c.opts.placeholders {
83                 // A placeholder snippet turns "someFun<>" into "someFunc(<*i int*>, *s string*)".
84                 for i, p := range params {
85                         if i > 0 {
86                                 snip.WriteText(", ")
87                         }
88                         snip.WritePlaceholder(func(b *snippet.Builder) {
89                                 b.WriteText(p)
90                         })
91                 }
92         } else {
93                 // A plain snippet turns "someFun<>" into "someFunc(<>)".
94                 if len(params) > 0 {
95                         snip.WritePlaceholder(nil)
96                 }
97         }
98
99         snip.WriteText(")")
100
101         return snip
102 }