Skip to content

Instantly share code, notes, and snippets.

@tmthrgd
Last active January 6, 2019 04:54
Show Gist options
  • Save tmthrgd/917b25210ebe45e3df75d0f5bbfb6dac to your computer and use it in GitHub Desktop.
Save tmthrgd/917b25210ebe45e3df75d0f5bbfb6dac to your computer and use it in GitHub Desktop.
A small tool to sort all the funcs and global map keys in a golang source file.
// +build ignore
package main
import (
"bytes"
"fmt"
"go/parser"
"go/token"
"io/ioutil"
"log"
"os"
"sort"
"github.com/dave/dst"
"github.com/dave/dst/decorator"
)
func main() {
var file string
for _, arg := range os.Args[1:] {
if arg != "--" {
file = arg
break
}
}
if file == "" {
fmt.Fprintf(os.Stderr, "usage %s <file>\n", os.Args[0])
os.Exit(1)
}
fset := token.NewFileSet()
f, err := decorator.ParseFile(fset, file, nil, parser.ParseComments)
must(err)
for i := 0; i < len(f.Decls); i++ {
if !isFuncDecl(f.Decls[i]) {
continue
}
j := i
for j < len(f.Decls) && isFuncDecl(f.Decls[j]) {
j++
}
funcs := f.Decls[i:j]
sort.Slice(funcs, func(i, j int) bool {
return funcs[i].(*dst.FuncDecl).Name.Name <
funcs[j].(*dst.FuncDecl).Name.Name
})
i = j
}
for _, d := range f.Decls {
g, ok := d.(*dst.GenDecl)
if !ok || g.Tok != token.VAR {
continue
}
for _, s := range g.Specs {
v, ok := s.(*dst.ValueSpec)
if !ok {
continue
}
for _, vv := range v.Values {
c, ok := vv.(*dst.CompositeLit)
if !ok {
continue
}
_, ok = c.Type.(*dst.MapType)
if !ok {
continue
}
sort.Slice(c.Elts, func(i, j int) bool {
return c.Elts[i].(*dst.KeyValueExpr).Key.(*dst.Ident).Name <
c.Elts[j].(*dst.KeyValueExpr).Key.(*dst.Ident).Name
})
}
}
}
var buf bytes.Buffer
must(decorator.Fprint(&buf, f))
must(ioutil.WriteFile(file, buf.Bytes(), 0644))
}
func isFuncDecl(d dst.Decl) bool {
_, ok := d.(*dst.FuncDecl)
return ok
}
func must(err error) {
if err != nil {
log.Fatal(err)
}
}
// +build ignore
package main
import (
"bytes"
"fmt"
"go/parser"
"go/token"
"io/ioutil"
"log"
"os"
"sort"
"github.com/dave/dst"
"github.com/dave/dst/decorator"
)
func main() {
var file string
for _, arg := range os.Args[1:] {
if arg != "--" {
file = arg
break
}
}
if file == "" {
fmt.Fprintf(os.Stderr, "usage %s <file>\n", os.Args[0])
os.Exit(1)
}
fset := token.NewFileSet()
f, err := decorator.ParseFile(fset, file, nil, parser.ParseComments)
must(err)
for i := 0; i < len(f.Decls); i++ {
if !isFuncDecl(f.Decls[i]) {
continue
}
j := i
for j < len(f.Decls) && isFuncDecl(f.Decls[j]) {
j++
}
funcs := f.Decls[i:j]
sort.Slice(funcs, func(i, j int) bool {
mi, mj := methodName(funcs[i]), methodName(funcs[j])
if mi != mj {
return mi < mj
}
fi, fj := funcName(funcs[i]), funcName(funcs[j])
if fi == "parse" && fj != "parse" {
return false
}
if fi != "parse" && fj == "parse" {
return true
}
return fi < fj
})
i = j
}
var buf bytes.Buffer
must(decorator.Fprint(&buf, f))
must(ioutil.WriteFile(file, buf.Bytes(), 0644))
}
func isFuncDecl(d dst.Decl) bool {
_, ok := d.(*dst.FuncDecl)
return ok
}
func methodName(d dst.Decl) string {
return d.(*dst.FuncDecl).Recv.List[0].Type.(*dst.StarExpr).X.(*dst.Ident).Name
}
func funcName(d dst.Decl) string {
return d.(*dst.FuncDecl).Name.Name
}
func must(err error) {
if err != nil {
log.Fatal(err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment