unpack.go (1489B)
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 10 "honnef.co/go/tools/internal/xtools-internal/typeparams" 11 ) 12 13 // UnpackRecv unpacks a receiver type expression, reporting whether it is a 14 // pointer receiver, along with the type name identifier and any receiver type 15 // parameter identifiers. 16 // 17 // Copied (with modifications) from go/types. 18 func UnpackRecv(rtyp ast.Expr) (ptr bool, rname *ast.Ident, tparams []*ast.Ident) { 19 L: // unpack receiver type 20 // This accepts invalid receivers such as ***T and does not 21 // work for other invalid receivers, but we don't care. The 22 // validity of receiver expressions is checked elsewhere. 23 for { 24 switch t := rtyp.(type) { 25 case *ast.ParenExpr: 26 rtyp = t.X 27 case *ast.StarExpr: 28 ptr = true 29 rtyp = t.X 30 default: 31 break L 32 } 33 } 34 35 // unpack type parameters, if any 36 switch rtyp.(type) { 37 case *ast.IndexExpr, *ast.IndexListExpr: 38 var indices []ast.Expr 39 rtyp, _, indices, _ = typeparams.UnpackIndexExpr(rtyp) 40 for _, arg := range indices { 41 var par *ast.Ident 42 switch arg := arg.(type) { 43 case *ast.Ident: 44 par = arg 45 default: 46 // ignore errors 47 } 48 if par == nil { 49 par = &ast.Ident{NamePos: arg.Pos(), Name: "_"} 50 } 51 tparams = append(tparams, par) 52 } 53 } 54 55 // unpack receiver name 56 if name, _ := rtyp.(*ast.Ident); name != nil { 57 rname = name 58 } 59 60 return 61 }