Ejemplo n.º 1
0
Archivo: importer.go Proyecto: pcc/llgo
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
}
Ejemplo n.º 2
0
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)
}
Ejemplo n.º 3
0
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
}