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  }