Skip to content

Commit cc6cc3e

Browse files
committed
initial commit
0 parents  commit cc6cc3e

File tree

12 files changed

+646
-0
lines changed

12 files changed

+646
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.DS_Store
2+
.vscode

_testproj/go.mod

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module testproj
2+
3+
go 1.22.2
4+
5+
require grr v0.0.0
6+
7+
replace grr => ../

_testproj/main.go

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"grr/grr"
6+
"os"
7+
)
8+
9+
func main() {
10+
num, err := ReturnSomethingOrError()
11+
12+
if err != nil {
13+
grr.Errorf("MyError: this is your number: %v", num).
14+
AddError(err)
15+
}
16+
17+
fmt.Println("Number: ")
18+
19+
}
20+
21+
func ReturnSomethingOrError() (int, error) {
22+
file, err := os.Open("filename")
23+
24+
if err != nil {
25+
return 0, err
26+
}
27+
28+
defer file.Close()
29+
30+
return 1, nil
31+
}

cmd/main.go

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
7+
"github.com/whiskaway/grr/gen"
8+
)
9+
10+
func main() {
11+
// Read the filename from command line arguments
12+
if !isProperLength(os.Args) {
13+
println("Usage: go run main.go <folder.go>")
14+
os.Exit(1)
15+
}
16+
filename := getFilename(os.Args)
17+
18+
fmt.Printf("Finding and replacing grr.Errorf calls in %s/...\n", filename)
19+
20+
// Find and replace grr.Errorf calls in the file
21+
gen.FindAndReplaceErrorsInDir(filename)
22+
}
23+
24+
func isProperLength(args []string) bool {
25+
// check if either file is passed like ./grr <file> or ./grr -- <file>
26+
27+
if args[1] == "--" && len(args) == 3 {
28+
return true
29+
}
30+
31+
if len(os.Args) == 2 {
32+
return true
33+
}
34+
35+
return false
36+
}
37+
38+
func getFilename(args []string) string {
39+
if args[1] == "--" {
40+
return args[2]
41+
}
42+
return args[1]
43+
}

gen/errorFunc.tmpl

+90
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
{{$varlen := len .Vars}}
2+
3+
type {{ .ErrName }} struct {
4+
err error
5+
op string
6+
traits map[grr.Trait]string
7+
8+
{{- range .Vars }}
9+
{{ .Literal }} {{ .Type }}
10+
{{- end }}
11+
}
12+
13+
var _ grr.Error = &{{ .ErrName }}{}
14+
15+
func (e *{{ .ErrName }}) Error() string {
16+
return fmt.Sprintf("{{ .Message }}", {{ range $i, $pair := .Vars }}e.{{ $pair.Literal }}{{ if notlast $i $varlen}}, {{ end }}{{ end }})
17+
}
18+
19+
func (e *{{ .ErrName }}) Unwrap() error {
20+
return e.err
21+
}
22+
23+
func (e *{{ .ErrName }}) AsGrr(err grr.Error) (Error, bool) {
24+
E := reflect.TypeOf(err)
25+
26+
var last error = e.err
27+
28+
for {
29+
if last == nil {
30+
return nil, false
31+
}
32+
33+
if _, ok := last.(Error); !ok {
34+
return nil, false
35+
}
36+
37+
if reflect.TypeOf(last).ConvertibleTo(E) {
38+
return reflect.ValueOf(last).Convert(E).Interface().(Error), true
39+
}
40+
41+
last = last.(Error).Unwrap()
42+
}
43+
}
44+
45+
46+
func (e *{{ .ErrName }}) IsGrr(err grr.Error) bool {
47+
_, ok := e.AsGrr(err)
48+
return ok
49+
}
50+
51+
func (e *{{ .ErrName }}) AddTrait(trait string, value string) grr.Error {
52+
e.traits[trait] = value
53+
return e
54+
}
55+
56+
func (e *{{ .ErrName }}) GetTrait(key grr.Trait) (string, bool) {
57+
trait, ok := e.traits[key]
58+
return trait, ok
59+
}
60+
61+
func (e *{{ .ErrName }}) GetTraits() map[grr.Trait]string {
62+
traits := make(map[grr.Trait]string)
63+
for k, v := range e.traits {
64+
traits[k] = v
65+
}
66+
return traits
67+
}
68+
69+
70+
func (e *{{ .ErrName }}) AddOp(op string) grr.Error {
71+
e.op = op
72+
return e
73+
}
74+
75+
func (e *{{ .ErrName }}) GetOp() (string, bool) {
76+
return e.op, e.op != ""
77+
}
78+
79+
func (e *{{ .ErrName }}) AddError(err error) grr.Error {
80+
e.err = err
81+
return e
82+
}
83+
84+
func New{{ .ErrName }}({{ range $i, $pair := .Vars }}{{ $pair.Literal }} {{ $pair.Type }}{{ if notlast $i $varlen}}, {{ end }}{{ end }}) grr.Error {
85+
return &{{ .ErrName }}{
86+
{{- range .Vars }}
87+
{{ .Literal }}: {{ .Literal }},
88+
{{- end }}
89+
}
90+
}

gen/gen.go

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package gen
2+
3+
import (
4+
_ "embed"
5+
"strings"
6+
7+
"text/template"
8+
9+
"github.com/whiskaway/grr/grr"
10+
)
11+
12+
//go:embed errorFunc.tmpl
13+
var tmpl string
14+
15+
var fns = template.FuncMap{
16+
"notlast": func(index int, len int) bool {
17+
return index+1 != len
18+
},
19+
}
20+
21+
var tmplGet = template.Must(template.New("").Funcs(fns).Parse(tmpl))
22+
23+
type FnArg struct {
24+
Literal string
25+
Type string
26+
}
27+
28+
type TemplateData struct {
29+
ErrName string
30+
Vars []FnArg
31+
Message string
32+
}
33+
34+
var TrIsInternal = grr.NewTrait("IsInternal")
35+
36+
func GenerateErrorFunction(errMsg string, args ...FnArg) (string, error) {
37+
op := "Generate"
38+
39+
if len(errMsg) == 0 || errMsg == "\"\"" {
40+
return "", grr.Errorf("NoErrorMessage: error message not found").
41+
AddOp(op)
42+
}
43+
44+
if errMsg[0] == '"' {
45+
errMsg = errMsg[1:]
46+
}
47+
48+
if errMsg[len(errMsg)-1] == '"' {
49+
errMsg = errMsg[:len(errMsg)-1]
50+
}
51+
52+
// extract the new error name from message: "FileNotFound: a file with name %s was not found" => "FileNotFound"
53+
split := strings.Split(errMsg, ":")
54+
55+
// extract the error name from the message
56+
errName := strings.TrimSpace(split[0])
57+
58+
if errName == "" {
59+
return "", grr.Errorf("NoErrorName: error name not found in error message")
60+
}
61+
62+
// extract the error message from the message
63+
errMsg = strings.TrimSpace(strings.Join(split[1:], ""))
64+
65+
var buf strings.Builder
66+
67+
err := tmplGet.Execute(&buf, TemplateData{
68+
ErrName: errName,
69+
Vars: args,
70+
Message: errMsg,
71+
})
72+
73+
if err != nil {
74+
return "", grr.Errorf("FailedToExecuteTemplate: something went wrong while generating").
75+
AddError(err).
76+
AddTrait(TrIsInternal, "true").
77+
AddOp(op)
78+
}
79+
80+
return buf.String(), nil
81+
}

0 commit comments

Comments
 (0)