예제 #1
0
파일: mkstdlib.go 프로젝트: tcard/sgo
func main() {
	var buf bytes.Buffer
	outf := func(format string, args ...interface{}) {
		fmt.Fprintf(&buf, format, args...)
	}
	outf("// AUTO-GENERATED BY mkstdlib.go\n\n")
	outf("package imports\n")
	outf("var stdlib = map[string]string{\n")
	f := io.MultiReader(
		mustOpen(api("go1.txt")),
		mustOpen(api("go1.1.txt")),
		mustOpen(api("go1.2.txt")),
		mustOpen(api("go1.3.txt")),
		mustOpen(api("go1.4.txt")),
		mustOpen(api("go1.5.txt")),
	)
	sc := bufio.NewScanner(f)
	fullImport := map[string]string{} // "zip.NewReader" => "archive/zip"
	ambiguous := map[string]bool{}
	var keys []string
	for sc.Scan() {
		l := sc.Text()
		has := func(v string) bool { return strings.Contains(l, v) }
		if has("struct, ") || has("interface, ") || has(", method (") {
			continue
		}
		if m := sym.FindStringSubmatch(l); m != nil {
			full := m[1]
			key := path.Base(full) + "." + m[2]
			if exist, ok := fullImport[key]; ok {
				if exist != full {
					ambiguous[key] = true
				}
			} else {
				fullImport[key] = full
				keys = append(keys, key)
			}
		}
	}
	if err := sc.Err(); err != nil {
		log.Fatal(err)
	}
	sort.Strings(keys)
	for _, key := range keys {
		if ambiguous[key] {
			outf("\t// %q is ambiguous\n", key)
		} else {
			outf("\t%q: %q,\n", key, fullImport[key])
		}
	}
	outf("}\n")
	fmtbuf, err := format.Source(buf.Bytes())
	if err != nil {
		log.Fatal(err)
	}
	os.Stdout.Write(fmtbuf)
}
예제 #2
0
파일: main.go 프로젝트: tcard/sgo
func handleMsg(msg msgType) {
	c := msg.c
	if c == nil {
		log.Println("c shouldn't be nil")
		return
	}
	switch msg.Type {
	case "format":
		resp := &msgType{
			Type: "format",
		}
		func() {
			defer func() {
				if r := recover(); r != nil {
					value := fmt.Sprintln(r)
					stack := make([]byte, 99999)
					runtime.Stack(stack, false)
					value += string(stack)
					resp.Value = value
				}
			}()
			formatted, err := format.Source([]byte(msg.Value.(string)))
			if err == nil {
				resp.Value = string(formatted)
			}
		}()
		c.WriteJSON(resp)
	case "translate":
		resp := &msgType{
			Type: "translate",
		}
		func() {
			defer func() {
				if r := recover(); r != nil {
					value := fmt.Sprintln(r)
					stack := make([]byte, 99999)
					runtime.Stack(stack, false)
					value += string(stack)
					resp.Value = value
				}
			}()
			w := &bytes.Buffer{}
			errs := sgo.TranslateFile(func() (io.Writer, error) { return w, nil }, strings.NewReader(msg.Value.(string)), "name")
			if errs != nil {
				var errMsgs []string
				for _, err := range errs {
					if errs, ok := err.(scanner.ErrorList); ok {
						for _, err := range errs {
							errMsgs = append(errMsgs, err.Error())
						}
					} else {
						errMsgs = append(errMsgs, err.Error())
					}
				}
				resp.Value = strings.Join(errMsgs, "\n")
			} else {
				resp.Value = w.String()
			}
		}()
		c.WriteJSON(resp)
	case "execute":
		resp := &msgType{
			Type: "execute",
		}
		body := url.Values{}
		body.Add("version", "2")
		var errs []error
		w := &bytes.Buffer{}
		func() {
			defer func() {
				if r := recover(); r != nil {
					value := fmt.Sprintln(r)
					stack := make([]byte, 99999)
					runtime.Stack(stack, false)
					value += string(stack)
					errs = append(errs, errors.New(value))
				}
			}()

			errs = sgo.TranslateFile(func() (io.Writer, error) { return w, nil }, strings.NewReader(msg.Value.(string)), "name")
		}()
		if errs != nil {
			var errMsgs []string
			for _, err := range errs {
				if errs, ok := err.(scanner.ErrorList); ok {
					for _, err := range errs {
						errMsgs = append(errMsgs, err.Error())
					}
				} else {
					errMsgs = append(errMsgs, err.Error())
				}
			}
			resp.Value = strings.Join(errMsgs, "\n")
		} else {
			body.Add("body", w.String())
			postResp, err := http.PostForm("https://play.golang.org/compile", body)
			if err != nil {
				resp.Value = err.Error()
			} else {
				var v interface{}
				err := json.NewDecoder(postResp.Body).Decode(&v)
				postResp.Body.Close()
				if err != nil {
					resp.Value = err.Error()
				} else {
					resp.Value = v
				}
			}
		}
		c.WriteJSON(resp)
	}
}
예제 #3
0
파일: imports.go 프로젝트: tcard/sgo
// Process formats and adjusts imports for the provided file.
// If opt is nil the defaults are used.
//
// Note that filename's directory influences which imports can be chosen,
// so it is important that filename be accurate.
// To process data ``as if'' it were in filename, pass the data as a non-nil src.
func Process(filename string, src []byte, opt *Options) ([]byte, error) {
	if opt == nil {
		opt = &Options{Comments: true, TabIndent: true, TabWidth: 8}
	}

	fileSet := token.NewFileSet()
	file, adjust, err := parse(fileSet, filename, src, opt)
	if err != nil {
		return nil, err
	}

	if !opt.FormatOnly {
		_, err = fixImports(fileSet, file, filename)
		if err != nil {
			return nil, err
		}
	}

	sortImports(fileSet, file)
	imps := astutil.Imports(fileSet, file)

	var spacesBefore []string // import paths we need spaces before
	for _, impSection := range imps {
		// Within each block of contiguous imports, see if any
		// import lines are in different group numbers. If so,
		// we'll need to put a space between them so it's
		// compatible with gofmt.
		lastGroup := -1
		for _, importSpec := range impSection {
			importPath, _ := strconv.Unquote(importSpec.Path.Value)
			groupNum := importGroup(importPath)
			if groupNum != lastGroup && lastGroup != -1 {
				spacesBefore = append(spacesBefore, importPath)
			}
			lastGroup = groupNum
		}

	}

	printerMode := printer.UseSpaces
	if opt.TabIndent {
		printerMode |= printer.TabIndent
	}
	printConfig := &printer.Config{Mode: printerMode, Tabwidth: opt.TabWidth}

	var buf bytes.Buffer
	err = printConfig.Fprint(&buf, fileSet, file)
	if err != nil {
		return nil, err
	}
	out := buf.Bytes()
	if adjust != nil {
		out = adjust(src, out)
	}
	if len(spacesBefore) > 0 {
		out = addImportSpaces(bytes.NewReader(out), spacesBefore)
	}

	out, err = format.Source(out)
	if err != nil {
		return nil, err
	}
	return out, nil
}
예제 #4
0
파일: mkindex.go 프로젝트: tcard/sgo
func main() {
	// Don't use GOPATH.
	ctx := build.Default
	ctx.GOPATH = ""

	// Populate pkgIndex global from GOROOT.
	for _, path := range ctx.SrcDirs() {
		f, err := os.Open(path)
		if err != nil {
			log.Print(err)
			continue
		}
		children, err := f.Readdir(-1)
		f.Close()
		if err != nil {
			log.Print(err)
			continue
		}
		for _, child := range children {
			if child.IsDir() {
				loadPkg(path, child.Name())
			}
		}
	}
	// Populate exports global.
	for _, ps := range pkgIndex {
		for _, p := range ps {
			e := loadExports(p.dir)
			if e != nil {
				exports[p.dir] = e
			}
		}
	}

	// Construct source file.
	var buf bytes.Buffer
	fmt.Fprint(&buf, pkgIndexHead)
	fmt.Fprintf(&buf, "var pkgIndexMaster = %#v\n", pkgIndex)
	fmt.Fprintf(&buf, "var exportsMaster = %#v\n", exports)
	src := buf.Bytes()

	// Replace main.pkg type name with pkg.
	src = bytes.Replace(src, []byte("main.pkg"), []byte("pkg"), -1)
	// Replace actual GOROOT with "/go".
	src = bytes.Replace(src, []byte(ctx.GOROOT), []byte("/go"), -1)
	// Add some line wrapping.
	src = bytes.Replace(src, []byte("}, "), []byte("},\n"), -1)
	src = bytes.Replace(src, []byte("true, "), []byte("true,\n"), -1)

	var err error
	src, err = format.Source(src)
	if err != nil {
		log.Fatal(err)
	}

	// Write out source file.
	err = ioutil.WriteFile("pkgindex.go", src, 0644)
	if err != nil {
		log.Fatal(err)
	}
}