func (imp *importer) newPackageInfo(path string) *PackageInfo { pkg := types.NewPackage(path, "") info := &PackageInfo{ Pkg: pkg, Info: types.Info{ Types: make(map[ast.Expr]types.TypeAndValue), Defs: make(map[*ast.Ident]types.Object), Uses: make(map[*ast.Ident]types.Object), Implicits: make(map[ast.Node]types.Object), Scopes: make(map[ast.Node]*types.Scope), Selections: make(map[*ast.SelectorExpr]*types.Selection), }, errorFunc: imp.conf.TypeChecker.Error, } // Copy the types.Config so we can vary it across PackageInfos. tc := imp.conf.TypeChecker tc.IgnoreFuncBodies = false if f := imp.conf.TypeCheckFuncBodies; f != nil { tc.IgnoreFuncBodies = !f(path) } tc.Import = func(_ map[string]*types.Package, to string) (*types.Package, error) { return imp.doImport(info, to) } tc.Error = info.appendError // appendError wraps the user's Error function info.checker = types.NewChecker(&tc, imp.conf.fset(), pkg, &info.Info) imp.progMu.Lock() imp.prog.AllPackages[pkg] = info imp.progMu.Unlock() return info }
"reflect" "unsafe" "github.com/stripe/safesql/Godeps/_workspace/src/golang.org/x/tools/go/ssa" "github.com/stripe/safesql/Godeps/_workspace/src/golang.org/x/tools/go/types" ) type opaqueType struct { types.Type name string } func (t *opaqueType) String() string { return t.name } // A bogus "reflect" type-checker package. Shared across interpreters. var reflectTypesPackage = types.NewPackage("reflect", "reflect") // rtype is the concrete type the interpreter uses to implement the // reflect.Type interface. // // type rtype <opaque> var rtypeType = makeNamedType("rtype", &opaqueType{nil, "rtype"}) // error is an (interpreted) named type whose underlying type is string. // The interpreter uses it for all implementations of the built-in error // interface that it creates. // We put it in the "reflect" package for expedience. // // type error string var errorType = makeNamedType("error", &opaqueType{nil, "error"})
// CreateTestMainPackage creates and returns a synthetic "main" // package that runs all the tests of the supplied packages, similar // to the one that would be created by the 'go test' tool. // // It returns nil if the program contains no tests. // func (prog *Program) CreateTestMainPackage(pkgs ...*Package) *Package { pkgs, tests, benchmarks, examples := FindTests(pkgs) if len(pkgs) == 0 { return nil } testmain := &Package{ Prog: prog, Members: make(map[string]Member), values: make(map[types.Object]Value), Pkg: types.NewPackage("test$main", "main"), } // Build package's init function. init := &Function{ name: "init", Signature: new(types.Signature), Synthetic: "package initializer", Pkg: testmain, Prog: prog, } init.startBody() if testMainStartBodyHook != nil { testMainStartBodyHook(init) } // Initialize packages to test. var pkgpaths []string for _, pkg := range pkgs { var v Call v.Call.Value = pkg.init v.setType(types.NewTuple()) init.emit(&v) pkgpaths = append(pkgpaths, pkg.Pkg.Path()) } sort.Strings(pkgpaths) init.emit(new(Return)) init.finishBody() testmain.init = init testmain.Pkg.MarkComplete() testmain.Members[init.name] = init // For debugging convenience, define an unexported const // that enumerates the packages. packagesConst := types.NewConst(token.NoPos, testmain.Pkg, "packages", tString, exact.MakeString(strings.Join(pkgpaths, " "))) memberFromObject(testmain, packagesConst, nil) // Create main *types.Func and *ssa.Function mainFunc := types.NewFunc(token.NoPos, testmain.Pkg, "main", new(types.Signature)) memberFromObject(testmain, mainFunc, nil) main := testmain.Func("main") main.Synthetic = "test main function" main.startBody() if testMainStartBodyHook != nil { testMainStartBodyHook(main) } if testingPkg := prog.ImportedPackage("testing"); testingPkg != nil { testingMain := testingPkg.Func("Main") testingMainParams := testingMain.Signature.Params() // The generated code is as if compiled from this: // // func main() { // match := func(_, _ string) (bool, error) { return true, nil } // tests := []testing.InternalTest{{"TestFoo", TestFoo}, ...} // benchmarks := []testing.InternalBenchmark{...} // examples := []testing.InternalExample{...} // testing.Main(match, tests, benchmarks, examples) // } matcher := &Function{ name: "matcher", Signature: testingMainParams.At(0).Type().(*types.Signature), Synthetic: "test matcher predicate", parent: main, Pkg: testmain, Prog: prog, } main.AnonFuncs = append(main.AnonFuncs, matcher) matcher.startBody() matcher.emit(&Return{Results: []Value{vTrue, nilConst(types.Universe.Lookup("error").Type())}}) matcher.finishBody() // Emit call: testing.Main(matcher, tests, benchmarks, examples). var c Call c.Call.Value = testingMain c.Call.Args = []Value{ matcher, testMainSlice(main, tests, testingMainParams.At(1).Type()), testMainSlice(main, benchmarks, testingMainParams.At(2).Type()), testMainSlice(main, examples, testingMainParams.At(3).Type()), } emitTailCall(main, &c) } else { // The program does not import "testing", but FindTests // returned non-nil, which must mean there were Examples // but no Tests or Benchmarks. // We'll simply call them from testmain.main; this will // ensure they don't panic, but will not check any // "Output:" comments. for _, eg := range examples { var c Call c.Call.Value = eg c.setType(types.NewTuple()) main.emit(&c) } main.emit(&Return{}) main.currentBlock = nil } main.finishBody() testmain.Members["main"] = main if prog.mode&PrintPackages != 0 { printMu.Lock() testmain.WriteTo(os.Stdout) printMu.Unlock() } if prog.mode&SanityCheckFunctions != 0 { sanityCheckPackage(testmain) } prog.packages[testmain.Pkg] = testmain return testmain }