Esempio n. 1
0
// TODO replace with encoding/gob when reflection is ready
func ReadArchive(packages map[string]*types.Package, filename, id string, data io.Reader) ([]byte, *types.Package, error) {
	r := bufio.NewReader(data)

	code, err := readUntilSeparator(r)
	if err != nil {
		return nil, nil, err
	}
	importList, err := readUntilSeparator(r)
	if err != nil {
		return nil, nil, err
	}

	pkg, err := gcimporter.ImportData(packages, filename, id, r)
	if err != nil {
		return nil, nil, err
	}

	var imports []*types.Package
	for _, path := range strings.Split(string(importList), "\n") {
		if path == "" {
			continue
		}
		impPkg, found := packages[path]
		if !found {
			impPkg = types.NewPackage(path, "", types.NewScope(nil))
			packages[path] = impPkg
		}
		imports = append(imports, impPkg)
	}
	pkg.SetImports(imports)

	return code, pkg, nil
}
Esempio n. 2
0
func (p *importer) pkg() *types.Package {
	// if the package was seen before, i is its index (>= 0)
	i := p.int()
	if i >= 0 {
		return p.pkgList[i]
	}

	// otherwise, i is the package tag (< 0)
	if i != packageTag {
		panic(fmt.Sprintf("unexpected package tag %d", i))
	}

	// read package data
	name := p.string()
	path := p.string()

	// if the package was imported before, use that one; otherwise create a new one
	pkg := p.imports[path]
	if pkg == nil {
		pkg = types.NewPackage(path, name, types.NewScope(nil))
		p.imports[path] = pkg
	}
	p.pkgList = append(p.pkgList, pkg)

	return pkg
}
// getPkg returns the package for a given id. If the package is
// not found but we have a package name, create the package and
// add it to the p.imports map.
//
func (p *parser) getPkg(id, name string) *types.Package {
	// package unsafe is not in the imports map - handle explicitly
	if id == "unsafe" {
		return types.Unsafe
	}
	pkg := p.imports[id]
	if pkg == nil && name != "" {
		pkg = types.NewPackage(id, name, types.NewScope(nil))
		p.imports[id] = pkg
	}
	return pkg
}
Esempio n. 4
0
func tool() error {
	flag.Parse()

	cmd := flag.Arg(0)
	switch cmd {
	case "build":
		buildFlags := flag.NewFlagSet("build", flag.ContinueOnError)
		var pkgObj string
		buildFlags.StringVar(&pkgObj, "o", "", "")
		buildFlags.Parse(flag.Args()[1:])

		if buildFlags.NArg() == 0 {
			wd, err := os.Getwd()
			if err != nil {
				return err
			}
			buildContext := &build.Context{
				GOROOT:   build.Default.GOROOT,
				GOPATH:   build.Default.GOPATH,
				GOOS:     build.Default.GOOS,
				GOARCH:   "js",
				Compiler: "gc",
			}
			buildPkg, err := buildContext.ImportDir(wd, 0)
			if err != nil {
				return err
			}
			pkg := &Package{Package: buildPkg}
			pkg.ImportPath = wd
			if err := buildPackage(pkg); err != nil {
				return err
			}
			if pkgObj == "" {
				pkgObj = path.Base(wd) + ".js"
			}
			if err := writeCommandPackage(pkg, pkgObj); err != nil {
				return err
			}
			return nil
		}

		if strings.HasSuffix(buildFlags.Arg(0), ".go") {
			for _, arg := range buildFlags.Args() {
				if !strings.HasSuffix(arg, ".go") {
					return fmt.Errorf("named files must be .go files")
				}
			}
			if pkgObj == "" {
				basename := path.Base(buildFlags.Arg(0))
				pkgObj = basename[:len(basename)-3] + ".js"
			}
			if err := buildFiles(buildFlags.Args(), pkgObj); err != nil {
				return err
			}
			return nil
		}

		for _, pkgPath := range buildFlags.Args() {
			buildPkg, err := buildImport(pkgPath, 0)
			if err != nil {
				return err
			}
			pkg := &Package{Package: buildPkg}
			if err := buildPackage(pkg); err != nil {
				return err
			}
			if pkgObj == "" {
				pkgObj = path.Base(buildFlags.Arg(0)) + ".js"
			}
			if err := writeCommandPackage(pkg, pkgObj); err != nil {
				return err
			}
		}
		return nil

	case "install":
		installFlags := flag.NewFlagSet("install", flag.ContinueOnError)
		installFlags.Parse(flag.Args()[1:])

		installMode = true
		for _, pkgPath := range installFlags.Args() {
			buildPkg, err := buildImport(pkgPath, 0)
			if err != nil {
				return err
			}
			pkg := &Package{Package: buildPkg}
			if pkg.IsCommand() {
				pkg.PkgObj = pkg.BinDir + "/" + path.Base(pkg.ImportPath) + ".js"
			}
			if err := buildPackage(pkg); err != nil {
				return err
			}
			if err := writeCommandPackage(pkg, pkg.PkgObj); err != nil {
				return err
			}
		}
		return nil

	case "run":
		lastSourceArg := 1
		for {
			if !strings.HasSuffix(flag.Arg(lastSourceArg), ".go") {
				break
			}
			lastSourceArg += 1
		}
		if lastSourceArg == 1 {
			return fmt.Errorf("gopherjs run: no go files listed")
		}

		tempfile, err := ioutil.TempFile("", path.Base(flag.Arg(1))+".")
		if err != nil {
			return err
		}
		defer func() {
			tempfile.Close()
			os.Remove(tempfile.Name())
		}()

		if err := buildFiles(flag.Args()[1:lastSourceArg], tempfile.Name()); err != nil {
			return err
		}
		if err := runNode(tempfile.Name(), flag.Args()[lastSourceArg:], ""); err != nil {
			return err
		}
		return nil

	case "test":
		testFlags := flag.NewFlagSet("test", flag.ContinueOnError)
		short := testFlags.Bool("short", false, "")
		verbose := testFlags.Bool("v", false, "")
		testFlags.Parse(flag.Args()[1:])

		mainPkg := &Package{Package: &build.Package{
			ImportPath: "main",
		}}
		packages["main"] = mainPkg
		mainPkgTypes := types.NewPackage("main", "main", types.NewScope(nil))
		testingPkgTypes, _ := typesConfig.Import(typesConfig.Packages, "testing")
		mainPkgTypes.SetImports([]*types.Package{testingPkgTypes})
		typesConfig.Packages["main"] = mainPkgTypes
		mainPkg.JavaScriptCode = []byte("Go$pkg.main = function() {\nGo$packages[\"flag\"].Parse();\n")

		for _, pkgPath := range testFlags.Args() {
			buildPkg, err := buildImport(pkgPath, 0)
			if err != nil {
				return err
			}

			pkg := &Package{Package: buildPkg}
			pkg.GoFiles = append(pkg.GoFiles, pkg.TestGoFiles...)
			if err := buildPackage(pkg); err != nil {
				return err
			}

			testPkg := &Package{Package: &build.Package{
				ImportPath: pkg.ImportPath + "_test",
				Dir:        pkg.Dir,
				GoFiles:    pkg.XTestGoFiles,
			}}
			if err := buildPackage(testPkg); err != nil {
				return err
			}

			pkgTypes := typesConfig.Packages[pkg.ImportPath]
			testPkgTypes := typesConfig.Packages[testPkg.ImportPath]
			var names []string
			var tests []string
			for _, name := range pkgTypes.Scope().Names() {
				if strings.HasPrefix(name, "Test") {
					names = append(names, name)
					tests = append(tests, fmt.Sprintf(`Go$packages["%s"].%s`, pkg.ImportPath, name))
				}
			}
			for _, name := range testPkgTypes.Scope().Names() {
				if strings.HasPrefix(name, "Test") {
					names = append(names, name)
					tests = append(tests, fmt.Sprintf(`Go$packages["%s"].%s`, testPkg.ImportPath, name))
				}
			}
			mainPkg.JavaScriptCode = append(mainPkg.JavaScriptCode, []byte(fmt.Sprintf(`Go$packages["testing"].RunTests2("%s", "%s", ["%s"], [%s]);`+"\n", pkg.ImportPath, pkg.Dir, strings.Join(names, `", "`), strings.Join(tests, ", ")))...)
			mainPkgTypes.SetImports(append(mainPkgTypes.Imports(), pkgTypes, testPkgTypes))
		}
		mainPkg.JavaScriptCode = append(mainPkg.JavaScriptCode, []byte("}; Go$pkg.init = function() {};")...)

		tempfile, err := ioutil.TempFile("", "test.")
		if err != nil {
			return err
		}
		defer func() {
			tempfile.Close()
			os.Remove(tempfile.Name())
		}()

		if err := writeCommandPackage(mainPkg, tempfile.Name()); err != nil {
			return err
		}

		var args []string
		if *short {
			args = append(args, "-test.short")
		}
		if *verbose {
			args = append(args, "-test.v")
		}
		return runNode(tempfile.Name(), args, "")

	case "tool":
		tool := flag.Arg(1)
		toolFlags := flag.NewFlagSet("tool", flag.ContinueOnError)
		toolFlags.Bool("e", false, "")
		toolFlags.Bool("l", false, "")
		toolFlags.Bool("m", false, "")
		toolFlags.String("o", "", "")
		toolFlags.String("D", "", "")
		toolFlags.String("I", "", "")
		toolFlags.Parse(flag.Args()[2:])

		if len(tool) == 2 {
			switch tool[1] {
			case 'g':
				basename := path.Base(toolFlags.Arg(0))
				if err := buildFiles([]string{toolFlags.Arg(0)}, basename[:len(basename)-3]+".js"); err != nil {
					return err
				}
				return nil
			}
		}
		return fmt.Errorf("Tool not supported: " + tool)

	case "help", "":
		os.Stderr.WriteString(`GopherJS is a tool for compiling Go source code to JavaScript.

Usage:

    gopherjs command [arguments]

The commands are:

    build       compile packages and dependencies
    install     compile and install packages and dependencies
    run         compile and run Go program

`)
		return nil

	default:
		return fmt.Errorf("gopherjs: unknown subcommand \"%s\"\nRun 'gopherjs help' for usage.", cmd)

	}
}