github.com/amarpal/go-tools@v0.0.0-20240422043104-40142f59f616/debug/debug.go (about)

     1  // Package debug contains helpers for debugging static analyses.
     2  package debug
     3  
     4  import (
     5  	"bytes"
     6  	"go/ast"
     7  	"go/format"
     8  	"go/importer"
     9  	"go/parser"
    10  	"go/token"
    11  	"go/types"
    12  )
    13  
    14  // TypeCheck parses and type-checks a single-file Go package from a string.
    15  // The package must not have any imports.
    16  func TypeCheck(src string) (*ast.File, *types.Package, *types.Info, error) {
    17  	fset := token.NewFileSet()
    18  	f, err := parser.ParseFile(fset, "foo.go", src, parser.ParseComments|parser.SkipObjectResolution)
    19  	if err != nil {
    20  		return nil, nil, nil, err
    21  	}
    22  	pkg := types.NewPackage("foo", f.Name.Name)
    23  	info := &types.Info{
    24  		Types:      map[ast.Expr]types.TypeAndValue{},
    25  		Defs:       map[*ast.Ident]types.Object{},
    26  		Uses:       map[*ast.Ident]types.Object{},
    27  		Implicits:  map[ast.Node]types.Object{},
    28  		Selections: map[*ast.SelectorExpr]*types.Selection{},
    29  		Scopes:     map[ast.Node]*types.Scope{},
    30  		InitOrder:  []*types.Initializer{},
    31  		Instances:  map[*ast.Ident]types.Instance{},
    32  	}
    33  	tcfg := &types.Config{
    34  		Importer: importer.Default(),
    35  	}
    36  	if err := types.NewChecker(tcfg, fset, pkg, info).Files([]*ast.File{f}); err != nil {
    37  		return nil, nil, nil, err
    38  	}
    39  	return f, pkg, info, nil
    40  }
    41  
    42  func FormatNode(node ast.Node) string {
    43  	var buf bytes.Buffer
    44  	fset := token.NewFileSet()
    45  	format.Node(&buf, fset, node)
    46  	return buf.String()
    47  }