func (imp *Importer) Import(imports map[string]*types.Package, path string) (pkg *types.Package, err error) { // myimports is different from imports. Imports can contain // dummy packages not loaded by us, while myimports will // be "pure". if pkg, ok := imp.myimports[path]; ok { if pkg == nil { return nil, fmt.Errorf("Previous attempt at loading package failed") } return pkg, nil } var data []byte pkgfile := packageExportsFile(imp.context, path) if path == "unsafe" { // Importing these packages have issues // // unsafe: // If this is actually imported, go.types will panic due to invalid type conversions. // This because it is a built in package (http://tip.golang.org/doc/spec#Package_unsafe) // and thus shouldn't be treated as a normal package anyway. } else { data, _ = ioutil.ReadFile(pkgfile) } if data != nil { // Need to load dependencies first for _, match := range importsRe.FindAllStringSubmatch(string(data), -1) { if _, ok := imp.myimports[match[1]]; !ok { _, err := imp.Import(imports, match[1]) if err != nil { return nil, err } } } pkg, err = gcimporter.ImportData(imports, pkgfile, path, bufio.NewReader(bytes.NewBuffer(data))) if err == nil { tracef("Loaded import data from: %s", pkgfile) } } if pkg == nil || err != nil { if data != nil { return nil, fmt.Errorf("Failed to load package %s: %v", path, err) } // Package has not been compiled yet, so fall back to // the standard GcImport. tracef("Falling back to gc import data for: %s", path) pkg, err = gcimporter.Import(imports, path) } imp.myimports[path] = pkg imports[path] = pkg return pkg, err }
func (imp *Importer) Import(imports map[string]*types.Package, path string) (pkg *types.Package, err error) { exportsPath := packageExportsFile(imp.context, path) data, err := ioutil.ReadFile(exportsPath) if err != nil { // Package has not been compiled yet, so // fall back to the standard GcImport. tracef("Falling back to gc import data for: %s", path) return gcimporter.Import(imports, path) } tracef("Loading import data for %q from %q", path, exportsPath) return importer.ImportData(imports, data) }
func (w *PkgWalker) Import(parentDir string, name string, conf *PkgConfig) (pkg *types.Package, err error) { defer func() { err := recover() if err != nil && typeVerbose { log.Println(err) } }() if strings.HasPrefix(name, ".") && parentDir != "" { name = filepath.Join(parentDir, name) } pkg = w.imported[name] if pkg != nil { if pkg == &w.importing { return nil, fmt.Errorf("cycle importing package %q", name) } return pkg, nil } if typeVerbose { log.Println("parser pkg", name) } var bp *build.Package if filepath.IsAbs(name) { bp, err = w.context.ImportDir(name, 0) } else { bp, err = w.context.Import(name, "", 0) } checkName := name if bp.ImportPath == "." { checkName = bp.Name } else { checkName = bp.ImportPath } if err != nil { return nil, err //if _, nogo := err.(*build.NoGoError); nogo { // return //} //return //log.Fatalf("pkg %q, dir %q: ScanDir: %v", name, info.Dir, err) } filenames := append(append([]string{}, bp.GoFiles...), bp.CgoFiles...) filenames = append(filenames, bp.TestGoFiles...) if name == "runtime" { n := fmt.Sprintf("zgoos_%s.go", w.context.GOOS) if !contains(filenames, n) { filenames = append(filenames, n) } n = fmt.Sprintf("zgoarch_%s.go", w.context.GOARCH) if !contains(filenames, n) { filenames = append(filenames, n) } } parserFiles := func(filenames []string, cursor *FileCursor) (files []*ast.File) { for _, file := range filenames { var f *ast.File if cursor != nil && cursor.fileName == file { f, err = w.parseFile(bp.Dir, file, cursor.src) cursor.pos = token.Pos(w.fset.File(f.Pos()).Base()) + token.Pos(cursor.cursorPos) cursor.fileDir = bp.Dir } else { f, err = w.parseFile(bp.Dir, file, nil) } if err != nil && typeVerbose { log.Printf("error parsing package %s: %s\n", name, err) } files = append(files, f) } return } files := parserFiles(filenames, conf.Cursor) xfiles := parserFiles(bp.XTestGoFiles, conf.Cursor) typesConf := types.Config{ IgnoreFuncBodies: conf.IgnoreFuncBodies, FakeImportC: true, Packages: w.gcimporter, Import: func(imports map[string]*types.Package, name string) (pkg *types.Package, err error) { if pkg != nil { return pkg, nil } if conf.AllowBinary && w.isBinaryPkg(name) { pkg = w.gcimporter[name] if pkg != nil && pkg.Complete() { return } pkg, err = gcimporter.Import(imports, name) if pkg != nil && pkg.Complete() { w.gcimporter[name] = pkg return } } return w.Import(bp.Dir, name, &PkgConfig{IgnoreFuncBodies: true, AllowBinary: true}) }, Error: func(err error) { if typeVerbose { log.Println(err) } }, } if pkg == nil { pkg, err = typesConf.Check(checkName, w.fset, files, conf.Info) } w.imported[name] = pkg if len(xfiles) > 0 { xpkg, _ := typesConf.Check(checkName+"_test", w.fset, xfiles, conf.Info) w.imported[checkName+"_test"] = xpkg } return }