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