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 / util.go
1 // Copyright 2020 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         "go/token"
10         "go/types"
11
12         "golang.org/x/tools/internal/lsp/source"
13 )
14
15 // exprAtPos returns the index of the expression containing pos.
16 func exprAtPos(pos token.Pos, args []ast.Expr) int {
17         for i, expr := range args {
18                 if expr.Pos() <= pos && pos <= expr.End() {
19                         return i
20                 }
21         }
22         return len(args)
23 }
24
25 // eachField invokes fn for each field that can be selected from a
26 // value of type T.
27 func eachField(T types.Type, fn func(*types.Var)) {
28         // TODO(adonovan): this algorithm doesn't exclude ambiguous
29         // selections that match more than one field/method.
30         // types.NewSelectionSet should do that for us.
31
32         // for termination on recursive types
33         var seen map[*types.Struct]bool
34
35         var visit func(T types.Type)
36         visit = func(T types.Type) {
37                 if T, ok := source.Deref(T).Underlying().(*types.Struct); ok {
38                         if seen[T] {
39                                 return
40                         }
41
42                         for i := 0; i < T.NumFields(); i++ {
43                                 f := T.Field(i)
44                                 fn(f)
45                                 if f.Anonymous() {
46                                         if seen == nil {
47                                                 // Lazily create "seen" since it is only needed for
48                                                 // embedded structs.
49                                                 seen = make(map[*types.Struct]bool)
50                                         }
51                                         seen[T] = true
52                                         visit(f.Type())
53                                 }
54                         }
55                 }
56         }
57         visit(T)
58 }
59
60 // typeIsValid reports whether typ doesn't contain any Invalid types.
61 func typeIsValid(typ types.Type) bool {
62         // Check named types separately, because we don't want
63         // to call Underlying() on them to avoid problems with recursive types.
64         if _, ok := typ.(*types.Named); ok {
65                 return true
66         }
67
68         switch typ := typ.Underlying().(type) {
69         case *types.Basic:
70                 return typ.Kind() != types.Invalid
71         case *types.Array:
72                 return typeIsValid(typ.Elem())
73         case *types.Slice:
74                 return typeIsValid(typ.Elem())
75         case *types.Pointer:
76                 return typeIsValid(typ.Elem())
77         case *types.Map:
78                 return typeIsValid(typ.Key()) && typeIsValid(typ.Elem())
79         case *types.Chan:
80                 return typeIsValid(typ.Elem())
81         case *types.Signature:
82                 return typeIsValid(typ.Params()) && typeIsValid(typ.Results())
83         case *types.Tuple:
84                 for i := 0; i < typ.Len(); i++ {
85                         if !typeIsValid(typ.At(i).Type()) {
86                                 return false
87                         }
88                 }
89                 return true
90         case *types.Struct, *types.Interface:
91                 // Don't bother checking structs, interfaces for validity.
92                 return true
93         default:
94                 return false
95         }
96 }
97
98 // resolveInvalid traverses the node of the AST that defines the scope
99 // containing the declaration of obj, and attempts to find a user-friendly
100 // name for its invalid type. The resulting Object and its Type are fake.
101 func resolveInvalid(fset *token.FileSet, obj types.Object, node ast.Node, info *types.Info) types.Object {
102         var resultExpr ast.Expr
103         ast.Inspect(node, func(node ast.Node) bool {
104                 switch n := node.(type) {
105                 case *ast.ValueSpec:
106                         for _, name := range n.Names {
107                                 if info.Defs[name] == obj {
108                                         resultExpr = n.Type
109                                 }
110                         }
111                         return false
112                 case *ast.Field: // This case handles parameters and results of a FuncDecl or FuncLit.
113                         for _, name := range n.Names {
114                                 if info.Defs[name] == obj {
115                                         resultExpr = n.Type
116                                 }
117                         }
118                         return false
119                 default:
120                         return true
121                 }
122         })
123         // Construct a fake type for the object and return a fake object with this type.
124         typename := source.FormatNode(fset, resultExpr)
125         typ := types.NewNamed(types.NewTypeName(token.NoPos, obj.Pkg(), typename, nil), types.Typ[types.Invalid], nil)
126         return types.NewVar(obj.Pos(), obj.Pkg(), obj.Name(), typ)
127 }
128
129 func isPointer(T types.Type) bool {
130         _, ok := T.(*types.Pointer)
131         return ok
132 }
133
134 func isVar(obj types.Object) bool {
135         _, ok := obj.(*types.Var)
136         return ok
137 }
138
139 func isTypeName(obj types.Object) bool {
140         _, ok := obj.(*types.TypeName)
141         return ok
142 }
143
144 func isFunc(obj types.Object) bool {
145         _, ok := obj.(*types.Func)
146         return ok
147 }
148
149 func isEmptyInterface(T types.Type) bool {
150         intf, _ := T.(*types.Interface)
151         return intf != nil && intf.NumMethods() == 0
152 }
153
154 func isUntyped(T types.Type) bool {
155         if basic, ok := T.(*types.Basic); ok {
156                 return basic.Info()&types.IsUntyped > 0
157         }
158         return false
159 }
160
161 func isPkgName(obj types.Object) bool {
162         _, ok := obj.(*types.PkgName)
163         return ok
164 }
165
166 func isASTFile(n ast.Node) bool {
167         _, ok := n.(*ast.File)
168         return ok
169 }
170
171 func deslice(T types.Type) types.Type {
172         if slice, ok := T.Underlying().(*types.Slice); ok {
173                 return slice.Elem()
174         }
175         return nil
176 }
177
178 // isSelector returns the enclosing *ast.SelectorExpr when pos is in the
179 // selector.
180 func enclosingSelector(path []ast.Node, pos token.Pos) *ast.SelectorExpr {
181         if len(path) == 0 {
182                 return nil
183         }
184
185         if sel, ok := path[0].(*ast.SelectorExpr); ok {
186                 return sel
187         }
188
189         if _, ok := path[0].(*ast.Ident); ok && len(path) > 1 {
190                 if sel, ok := path[1].(*ast.SelectorExpr); ok && pos >= sel.Sel.Pos() {
191                         return sel
192                 }
193         }
194
195         return nil
196 }
197
198 func enclosingValueSpec(path []ast.Node) *ast.ValueSpec {
199         for _, n := range path {
200                 if vs, ok := n.(*ast.ValueSpec); ok {
201                         return vs
202                 }
203         }
204
205         return nil
206 }
207
208 // exprObj returns the types.Object associated with the *ast.Ident or
209 // *ast.SelectorExpr e.
210 func exprObj(info *types.Info, e ast.Expr) types.Object {
211         var ident *ast.Ident
212         switch expr := e.(type) {
213         case *ast.Ident:
214                 ident = expr
215         case *ast.SelectorExpr:
216                 ident = expr.Sel
217         default:
218                 return nil
219         }
220
221         return info.ObjectOf(ident)
222 }
223
224 // typeConversion returns the type being converted to if call is a type
225 // conversion expression.
226 func typeConversion(call *ast.CallExpr, info *types.Info) types.Type {
227         // Type conversion (e.g. "float64(foo)").
228         if fun, _ := exprObj(info, call.Fun).(*types.TypeName); fun != nil {
229                 return fun.Type()
230         }
231
232         return nil
233 }
234
235 // fieldsAccessible returns whether s has at least one field accessible by p.
236 func fieldsAccessible(s *types.Struct, p *types.Package) bool {
237         for i := 0; i < s.NumFields(); i++ {
238                 f := s.Field(i)
239                 if f.Exported() || f.Pkg() == p {
240                         return true
241                 }
242         }
243         return false
244 }
245
246 // prevStmt returns the statement that precedes the statement containing pos.
247 // For example:
248 //
249 //     foo := 1
250 //     bar(1 + 2<>)
251 //
252 // If "<>" is pos, prevStmt returns "foo := 1"
253 func prevStmt(pos token.Pos, path []ast.Node) ast.Stmt {
254         var blockLines []ast.Stmt
255         for i := 0; i < len(path) && blockLines == nil; i++ {
256                 switch n := path[i].(type) {
257                 case *ast.BlockStmt:
258                         blockLines = n.List
259                 case *ast.CommClause:
260                         blockLines = n.Body
261                 case *ast.CaseClause:
262                         blockLines = n.Body
263                 }
264         }
265
266         for i := len(blockLines) - 1; i >= 0; i-- {
267                 if blockLines[i].End() < pos {
268                         return blockLines[i]
269                 }
270         }
271
272         return nil
273 }
274
275 // formatZeroValue produces Go code representing the zero value of T. It
276 // returns the empty string if T is invalid.
277 func formatZeroValue(T types.Type, qf types.Qualifier) string {
278         switch u := T.Underlying().(type) {
279         case *types.Basic:
280                 switch {
281                 case u.Info()&types.IsNumeric > 0:
282                         return "0"
283                 case u.Info()&types.IsString > 0:
284                         return `""`
285                 case u.Info()&types.IsBoolean > 0:
286                         return "false"
287                 default:
288                         return ""
289                 }
290         case *types.Pointer, *types.Interface, *types.Chan, *types.Map, *types.Slice, *types.Signature:
291                 return "nil"
292         default:
293                 return types.TypeString(T, qf) + "{}"
294         }
295 }