// CreatePackages creates SSA Packages for all error-free packages // loaded by the specified Importer. // // If all packages were error-free, it is safe to call // prog.BuildAll(), and nil is returned. Otherwise an error is // returned. // func (prog *Program) CreatePackages(imp *importer.Importer) error { var errpkgs []string for _, info := range imp.AllPackages() { if info.Err != nil { errpkgs = append(errpkgs, info.Pkg.Path()) } else { prog.CreatePackage(info) } } if errpkgs != nil { return fmt.Errorf("couldn't create these SSA packages due to type errors: %s", strings.Join(errpkgs, ", ")) } return nil }
func newOracle(imp *importer.Importer, args []string, ptalog io.Writer, needs int, reflection bool) (*Oracle, error) { o := &Oracle{fset: imp.Fset} // Load/parse/type-check program from args. initialPkgInfos, args, err := imp.LoadInitialPackages(args) if err != nil { return nil, err // I/O or parser error } if len(args) > 0 { return nil, fmt.Errorf("surplus arguments: %q", args) } // Retain type info for all ASTs in the program. if needs&needRetainTypeInfo != 0 { m := make(map[*types.Package]*importer.PackageInfo) for _, p := range imp.AllPackages() { m[p.Pkg] = p } o.typeInfo = m } // Create SSA package for the initial packages and their dependencies. if needs&needSSA != 0 { prog := ssa.NewProgram(o.fset, 0) // Create SSA packages. if err := prog.CreatePackages(imp); err != nil { return nil, err } // For each initial package (specified on the command line), // if it has a main function, analyze that, // otherwise analyze its tests, if any. var testPkgs, mains []*ssa.Package for _, info := range initialPkgInfos { initialPkg := prog.Package(info.Pkg) // Add package to the pointer analysis scope. if initialPkg.Func("main") != nil { mains = append(mains, initialPkg) } else { testPkgs = append(testPkgs, initialPkg) } } if testPkgs != nil { if p := prog.CreateTestMainPackage(testPkgs...); p != nil { mains = append(mains, p) } } if mains == nil { return nil, fmt.Errorf("analysis scope has no main and no tests") } o.ptaConfig.Log = ptalog o.ptaConfig.Reflection = reflection o.ptaConfig.Mains = mains if needs&needSSADebug != 0 { for _, pkg := range prog.AllPackages() { pkg.SetDebugMode(true) } } o.prog = prog } return o, nil }
func newOracle(imp *importer.Importer, args []string, ptalog io.Writer, needs int, reflection bool) (*Oracle, error) { o := &Oracle{ prog: ssa.NewProgram(imp.Fset, 0), timers: make(map[string]time.Duration), } o.config.Log = ptalog o.config.Reflection = reflection // Load/parse/type-check program from args. start := time.Now() initialPkgInfos, args, err := imp.LoadInitialPackages(args) if err != nil { return nil, err // I/O or parser error } if len(args) > 0 { return nil, fmt.Errorf("surplus arguments: %q", args) } o.timers["load/parse/type"] = time.Since(start) // Retain type info for all ASTs in the program. if needs&needAllTypeInfo != 0 { m := make(map[*types.Package]*importer.PackageInfo) for _, p := range imp.AllPackages() { m[p.Pkg] = p } o.typeInfo = m } // Create SSA package for the initial package and its dependencies. if needs&needSSA != 0 { start = time.Now() // Create SSA packages. if err := o.prog.CreatePackages(imp); err != nil { return nil, err } // Initial packages (specified on command line) for _, info := range initialPkgInfos { initialPkg := o.prog.Package(info.Pkg) // Add package to the pointer analysis scope. if initialPkg.Func("main") == nil { // TODO(adonovan): to simulate 'go test' more faithfully, we // should build a single synthetic testmain package, // not synthetic main functions to many packages. if initialPkg.CreateTestMainFunction() == nil { return nil, fmt.Errorf("analysis scope has no main() entry points") } } o.config.Mains = append(o.config.Mains, initialPkg) } if needs&needSSADebug != 0 { for _, pkg := range o.prog.AllPackages() { pkg.SetDebugMode(true) } } o.timers["SSA-create"] = time.Since(start) } return o, nil }