Last active
October 1, 2017 16:14
-
-
Save starius/7a9a3f8fe1fff4f1e4e933baa0b34f69 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bytes" | |
"flag" | |
"fmt" | |
"go/ast" | |
"go/parser" | |
"go/token" | |
"io/ioutil" | |
"log" | |
"os" | |
"path/filepath" | |
"sort" | |
"strings" | |
) | |
var ( | |
root = flag.String("root", "", "Go source files root dir") | |
) | |
func inspectSource(path string, kind ast.ObjKind) bool { | |
source, err := ioutil.ReadFile(path) | |
if err != nil { | |
log.Fatalf("Failed to read %q: %v.", path, err) | |
} | |
lines := bytes.Split(source, []byte("\n")) | |
inIotaGroup := make(map[int]struct{}) | |
inside := false | |
for l, line := range lines { | |
if bytes.Contains(line, []byte("iota")) { | |
inside = true | |
} | |
if bytes.Equal(line, []byte(")")) { | |
inside = false | |
} | |
if inside { | |
inIotaGroup[l+1] = struct{}{} | |
} | |
} | |
fset := token.NewFileSet() | |
f, err := parser.ParseFile(fset, path, source, 0) | |
if err != nil { | |
log.Fatalf("Failed to parse %q: %v.", path, err) | |
} | |
var objects []*ast.Object | |
for _, obj := range f.Scope.Objects { | |
if obj.Kind == kind { | |
objects = append(objects, obj) | |
} | |
} | |
sort.Slice(objects, func(i, j int) bool { | |
return objects[i].Pos() < objects[j].Pos() | |
}) | |
ok := true | |
for i, c := range objects { | |
if i == 0 { | |
continue | |
} | |
b := objects[i-1] | |
if strings.ToLower(b.Name) <= strings.ToLower(c.Name) { | |
continue | |
} | |
bLine := fset.Position(b.Pos()).Line | |
cLine := fset.Position(c.Pos()).Line | |
// Skip reporting if they belong to different groups. | |
differentGroups := false | |
for l := bLine - 1; l < cLine-1; l++ { | |
if bytes.Equal(lines[l], []byte(")")) { | |
differentGroups = true | |
} | |
} | |
if _, has := inIotaGroup[bLine]; has || differentGroups { | |
continue | |
} | |
fmt.Printf("%s: %s (line %d) and %s (line %d) are not ordered.\n", path, b.Name, bLine, c.Name, cLine) | |
ok = false | |
} | |
return ok | |
} | |
func main() { | |
flag.Parse() | |
if *root == "" { | |
log.Fatal("Specify -root") | |
} | |
ok := true | |
filepath.Walk(*root, func(path string, info os.FileInfo, err error) error { | |
if err == nil && !info.IsDir() && strings.HasSuffix(path, ".go") && !strings.HasSuffix(path, "_test.go") && !strings.Contains(path, "vendor/") { | |
if !inspectSource(path, ast.Con) || !inspectSource(path, ast.Var) { | |
ok = false | |
} | |
} | |
return nil | |
}) | |
if !ok { | |
os.Exit(1) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment