-
Notifications
You must be signed in to change notification settings - Fork 102
/
format.go
124 lines (110 loc) · 3.07 KB
/
format.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
package main
import (
"fmt"
"io/fs"
"os"
"path/filepath"
"regexp"
"strings"
)
func main() {
switch {
case len(os.Args) == 1 || len(os.Args) > 2:
displayUsage()
case len(os.Args) == 2 && os.Args[1] == "run":
formatFiles()
case len(os.Args) == 2 && os.Args[1] == "test":
runTests()
default:
fmt.Printf("Error: unknown argument: %s", os.Args[1])
os.Exit(1)
}
}
func displayUsage() {
fmt.Println(`
This tool makes all instance variables have the name "self".
See https://github.com/git-town/git-town/issues/2589 for details.
Usage: format <command>
Available commands:
run Formats the source code files
test Verifies that this tool works
`[1:])
}
// shouldIgnorePath indicates whether the file with the given path should be ignored (not formatted).
func shouldIgnorePath(path string) bool {
return strings.HasPrefix(path, "vendor/")
}
func formatFiles() {
err := filepath.WalkDir(".", func(path string, dirEntry fs.DirEntry, err error) error {
if err != nil || dirEntry.IsDir() || !isGoFile(path) || shouldIgnorePath(path) {
return err
}
fmt.Print(".")
content, err := os.ReadFile(path)
if err != nil {
return err
}
newContent := formatFileContent(string(content))
return os.WriteFile(path, []byte(newContent), dirEntry.Type().Perm())
})
fmt.Println()
if err != nil {
fmt.Printf("ERROR: %s\n", err)
os.Exit(1)
}
}
func formatFileContent(content string) string {
lines := strings.Split(content, "\n")
for l, line := range lines {
lines[l] = formatLine(line)
}
return strings.Join(lines, "\n")
}
func formatLine(line string) string {
if !strings.HasPrefix(line, "func (") {
return line
}
instanceRE := regexp.MustCompile(`func \((\w+) (\*?\w+\).*)$`)
matches := instanceRE.FindStringSubmatch(line)
if len(matches) < 2 {
return line
}
return strings.Replace(line, "("+matches[1], "(self", 1)
}
func isGoFile(path string) bool {
if strings.HasSuffix(path, "_test.go") {
return false
}
return strings.HasSuffix(path, ".go")
}
/************************************************************************************
* TESTS
*/
func runTests() {
testFormatLine()
fmt.Println()
}
func testFormatLine() {
tests := map[string]string{
"func (bcs *BackendCommands) CommentOutSquashCommitMessage(prefix string) error {": "func (self *BackendCommands) CommentOutSquashCommitMessage(prefix string) error {",
"func (c *Counter) Count() int {": "func (self *Counter) Count() int {",
" if err != nil {": " if err != nil {",
}
for give, want := range tests {
have := formatLine(give)
assertEqual(want, have, "testFormatLine")
}
}
func assertEqual[T comparable](want, have T, testName string) {
fmt.Print(".")
if have != want {
fmt.Printf("\nTEST FAILURE in %q\n", testName)
fmt.Println("\n\nWANT")
fmt.Println("--------------------------------------------------------")
fmt.Println(want)
fmt.Println("\n\nHAVE")
fmt.Println("--------------------------------------------------------")
fmt.Println(have)
os.Exit(1)
}
}