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