golang.org/x/tools/gopls@v0.15.3/internal/util/astutil/util.go (about) 1 // Copyright 2023 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 astutil 6 7 import ( 8 "go/ast" 9 "go/token" 10 11 "golang.org/x/tools/internal/typeparams" 12 ) 13 14 // UnpackRecv unpacks a receiver type expression, reporting whether it is a 15 // pointer recever, along with the type name identifier and any receiver type 16 // parameter identifiers. 17 // 18 // Copied (with modifications) from go/types. 19 func UnpackRecv(rtyp ast.Expr) (ptr bool, rname *ast.Ident, tparams []*ast.Ident) { 20 L: // unpack receiver type 21 // This accepts invalid receivers such as ***T and does not 22 // work for other invalid receivers, but we don't care. The 23 // validity of receiver expressions is checked elsewhere. 24 for { 25 switch t := rtyp.(type) { 26 case *ast.ParenExpr: 27 rtyp = t.X 28 case *ast.StarExpr: 29 ptr = true 30 rtyp = t.X 31 default: 32 break L 33 } 34 } 35 36 // unpack type parameters, if any 37 switch rtyp.(type) { 38 case *ast.IndexExpr, *ast.IndexListExpr: 39 var indices []ast.Expr 40 rtyp, _, indices, _ = typeparams.UnpackIndexExpr(rtyp) 41 for _, arg := range indices { 42 var par *ast.Ident 43 switch arg := arg.(type) { 44 case *ast.Ident: 45 par = arg 46 default: 47 // ignore errors 48 } 49 if par == nil { 50 par = &ast.Ident{NamePos: arg.Pos(), Name: "_"} 51 } 52 tparams = append(tparams, par) 53 } 54 } 55 56 // unpack receiver name 57 if name, _ := rtyp.(*ast.Ident); name != nil { 58 rname = name 59 } 60 61 return 62 } 63 64 // NodeContains returns true if a node encloses a given position pos. 65 // 66 // Precondition: n must not be nil. 67 func NodeContains(n ast.Node, pos token.Pos) bool { 68 return n.Pos() <= pos && pos <= n.End() 69 }