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) }
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) } }
// 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 }
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) } }