honnef.co/go/tools@v0.5.0-0.dev.0.20240520180541-dcae280a5e87/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  	"sync"
    13  )
    14  
    15  // TypeCheck parses and type-checks a single-file Go package from a string.
    16  // The package must not have any imports.
    17  func TypeCheck(src string) (*ast.File, *types.Package, *types.Info, error) {
    18  	fset := token.NewFileSet()
    19  	f, err := parser.ParseFile(fset, "foo.go", src, parser.ParseComments|parser.SkipObjectResolution)
    20  	if err != nil {
    21  		return nil, nil, nil, err
    22  	}
    23  	pkg := types.NewPackage("foo", f.Name.Name)
    24  	info := &types.Info{
    25  		Types:      map[ast.Expr]types.TypeAndValue{},
    26  		Defs:       map[*ast.Ident]types.Object{},
    27  		Uses:       map[*ast.Ident]types.Object{},
    28  		Implicits:  map[ast.Node]types.Object{},
    29  		Selections: map[*ast.SelectorExpr]*types.Selection{},
    30  		Scopes:     map[ast.Node]*types.Scope{},
    31  		InitOrder:  []*types.Initializer{},
    32  		Instances:  map[*ast.Ident]types.Instance{},
    33  	}
    34  	tcfg := &types.Config{
    35  		Importer: importer.Default(),
    36  	}
    37  	if err := types.NewChecker(tcfg, fset, pkg, info).Files([]*ast.File{f}); err != nil {
    38  		return nil, nil, nil, err
    39  	}
    40  	return f, pkg, info, nil
    41  }
    42  
    43  func FormatNode(node ast.Node) string {
    44  	var buf bytes.Buffer
    45  	fset := token.NewFileSet()
    46  	format.Node(&buf, fset, node)
    47  	return buf.String()
    48  }
    49  
    50  var aliasesDefaultOnce sync.Once
    51  var gotypesaliasDefault bool
    52  
    53  func AliasesEnabled() bool {
    54  	// Dynamically check if Aliases will be produced from go/types.
    55  	aliasesDefaultOnce.Do(func() {
    56  		fset := token.NewFileSet()
    57  		f, _ := parser.ParseFile(fset, "a.go", "package p; type A = int", 0)
    58  		pkg, _ := new(types.Config).Check("p", fset, []*ast.File{f}, nil)
    59  		_, gotypesaliasDefault = pkg.Scope().Lookup("A").Type().(*types.Alias)
    60  	})
    61  	return gotypesaliasDefault
    62  }