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

View as plain text