github.com/jd-ly/tools@v0.5.7/internal/lsp/source/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 "github.com/jd-ly/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 } 296 297 // isBasicKind returns whether t is a basic type of kind k. 298 func isBasicKind(t types.Type, k types.BasicInfo) bool { 299 b, _ := t.Underlying().(*types.Basic) 300 return b != nil && b.Info()&k > 0 301 }