Source file src/cmd/vendor/golang.org/x/tools/go/analysis/passes/testinggoroutine/util.go

     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 testinggoroutine
     6  
     7  import (
     8  	"go/ast"
     9  	"go/types"
    10  
    11  	"golang.org/x/tools/internal/typeparams"
    12  )
    13  
    14  // AST and types utilities that not specific to testinggoroutines.
    15  
    16  // localFunctionDecls returns a mapping from *types.Func to *ast.FuncDecl in files.
    17  func localFunctionDecls(info *types.Info, files []*ast.File) func(*types.Func) *ast.FuncDecl {
    18  	var fnDecls map[*types.Func]*ast.FuncDecl // computed lazily
    19  	return func(f *types.Func) *ast.FuncDecl {
    20  		if f != nil && fnDecls == nil {
    21  			fnDecls = make(map[*types.Func]*ast.FuncDecl)
    22  			for _, file := range files {
    23  				for _, decl := range file.Decls {
    24  					if fnDecl, ok := decl.(*ast.FuncDecl); ok {
    25  						if fn, ok := info.Defs[fnDecl.Name].(*types.Func); ok {
    26  							fnDecls[fn] = fnDecl
    27  						}
    28  					}
    29  				}
    30  			}
    31  		}
    32  		// TODO: set f = f.Origin() here.
    33  		return fnDecls[f]
    34  	}
    35  }
    36  
    37  // isMethodNamed returns true if f is a method defined
    38  // in package with the path pkgPath with a name in names.
    39  func isMethodNamed(f *types.Func, pkgPath string, names ...string) bool {
    40  	if f == nil {
    41  		return false
    42  	}
    43  	if f.Pkg() == nil || f.Pkg().Path() != pkgPath {
    44  		return false
    45  	}
    46  	if f.Type().(*types.Signature).Recv() == nil {
    47  		return false
    48  	}
    49  	for _, n := range names {
    50  		if f.Name() == n {
    51  			return true
    52  		}
    53  	}
    54  	return false
    55  }
    56  
    57  func funcIdent(fun ast.Expr) *ast.Ident {
    58  	switch fun := ast.Unparen(fun).(type) {
    59  	case *ast.IndexExpr, *ast.IndexListExpr:
    60  		x, _, _, _ := typeparams.UnpackIndexExpr(fun) // necessary?
    61  		id, _ := x.(*ast.Ident)
    62  		return id
    63  	case *ast.Ident:
    64  		return fun
    65  	default:
    66  		return nil
    67  	}
    68  }
    69  
    70  // funcLitInScope returns a FuncLit that id is at least initially assigned to.
    71  //
    72  // TODO: This is closely tied to id.Obj which is deprecated.
    73  func funcLitInScope(id *ast.Ident) *ast.FuncLit {
    74  	// Compare to (*ast.Object).Pos().
    75  	if id.Obj == nil {
    76  		return nil
    77  	}
    78  	var rhs ast.Expr
    79  	switch d := id.Obj.Decl.(type) {
    80  	case *ast.AssignStmt:
    81  		for i, x := range d.Lhs {
    82  			if ident, isIdent := x.(*ast.Ident); isIdent && ident.Name == id.Name && i < len(d.Rhs) {
    83  				rhs = d.Rhs[i]
    84  			}
    85  		}
    86  	case *ast.ValueSpec:
    87  		for i, n := range d.Names {
    88  			if n.Name == id.Name && i < len(d.Values) {
    89  				rhs = d.Values[i]
    90  			}
    91  		}
    92  	}
    93  	lit, _ := rhs.(*ast.FuncLit)
    94  	return lit
    95  }
    96  

View as plain text