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 }