gitee.com/wgliang/goreporter@v0.0.0-20180902115603-df1b20f7c5d0/linters/simpler/ssa/ssautil/load.go (about) 1 // Copyright 2015 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 // +build go1.5 6 7 package ssautil 8 9 // This file defines utility functions for constructing programs in SSA form. 10 11 import ( 12 "go/ast" 13 "go/token" 14 "go/types" 15 16 "github.com/360EntSecGroup-Skylar/goreporter/linters/simpler/ssa" 17 "golang.org/x/tools/go/loader" 18 ) 19 20 // CreateProgram returns a new program in SSA form, given a program 21 // loaded from source. An SSA package is created for each transitively 22 // error-free package of lprog. 23 // 24 // Code for bodies of functions is not built until Build is called 25 // on the result. 26 // 27 // mode controls diagnostics and checking during SSA construction. 28 // 29 func CreateProgram(lprog *loader.Program, mode ssa.BuilderMode) *ssa.Program { 30 prog := ssa.NewProgram(lprog.Fset, mode) 31 32 for _, info := range lprog.AllPackages { 33 if info.TransitivelyErrorFree { 34 prog.CreatePackage(info.Pkg, info.Files, &info.Info, info.Importable) 35 } 36 } 37 38 return prog 39 } 40 41 // BuildPackage builds an SSA program with IR for a single package. 42 // 43 // It populates pkg by type-checking the specified file ASTs. All 44 // dependencies are loaded using the importer specified by tc, which 45 // typically loads compiler export data; SSA code cannot be built for 46 // those packages. BuildPackage then constructs an ssa.Program with all 47 // dependency packages created, and builds and returns the SSA package 48 // corresponding to pkg. 49 // 50 // The caller must have set pkg.Path() to the import path. 51 // 52 // The operation fails if there were any type-checking or import errors. 53 // 54 // See ../ssa/example_test.go for an example. 55 // 56 func BuildPackage(tc *types.Config, fset *token.FileSet, pkg *types.Package, files []*ast.File, mode ssa.BuilderMode) (*ssa.Package, *types.Info, error) { 57 if fset == nil { 58 panic("no token.FileSet") 59 } 60 if pkg.Path() == "" { 61 panic("package has no import path") 62 } 63 64 info := &types.Info{ 65 Types: make(map[ast.Expr]types.TypeAndValue), 66 Defs: make(map[*ast.Ident]types.Object), 67 Uses: make(map[*ast.Ident]types.Object), 68 Implicits: make(map[ast.Node]types.Object), 69 Scopes: make(map[ast.Node]*types.Scope), 70 Selections: make(map[*ast.SelectorExpr]*types.Selection), 71 } 72 if err := types.NewChecker(tc, fset, pkg, info).Files(files); err != nil { 73 return nil, nil, err 74 } 75 76 prog := ssa.NewProgram(fset, mode) 77 78 // Create SSA packages for all imports. 79 // Order is not significant. 80 created := make(map[*types.Package]bool) 81 var createAll func(pkgs []*types.Package) 82 createAll = func(pkgs []*types.Package) { 83 for _, p := range pkgs { 84 if !created[p] { 85 created[p] = true 86 prog.CreatePackage(p, nil, nil, true) 87 createAll(p.Imports()) 88 } 89 } 90 } 91 createAll(pkg.Imports()) 92 93 // Create and build the primary package. 94 ssapkg := prog.CreatePackage(pkg, files, info, false) 95 ssapkg.Build() 96 return ssapkg, info, nil 97 }