forked from Memoria-X/protoc-gen-go-errors
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patherrors.go
More file actions
132 lines (118 loc) · 3.25 KB
/
errors.go
File metadata and controls
132 lines (118 loc) · 3.25 KB
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
125
126
127
128
129
130
131
132
package main
import (
"fmt"
"github.com/memoria-x/protoc-gen-go-errors/errors"
"strings"
"unicode"
"golang.org/x/text/cases"
"golang.org/x/text/language"
"google.golang.org/protobuf/compiler/protogen"
"google.golang.org/protobuf/proto"
)
const (
errorsPackage = protogen.GoImportPath("github.com/memoria-x/protoc-gen-go-errors/errors")
officialErrorsPackage = protogen.GoImportPath("errors")
)
var enCases = cases.Title(language.AmericanEnglish, cases.NoLower)
func generateFile(gen *protogen.Plugin, file *protogen.File) *protogen.GeneratedFile {
if len(file.Enums) == 0 {
return nil
}
filename := file.GeneratedFilenamePrefix + ".pb.errors.go"
g := gen.NewGeneratedFile(filename, file.GoImportPath)
g.P("// Code generated by protoc-gen-go-errors. DO NOT EDIT.")
g.P()
g.P("package ", file.GoPackageName)
g.P()
g.QualifiedGoIdent(errorsPackage.Ident(""))
g.QualifiedGoIdent(officialErrorsPackage.Ident(""))
generateFileContent(gen, file, g)
return g
}
func generateFileContent(gen *protogen.Plugin, file *protogen.File, g *protogen.GeneratedFile) {
if len(file.Enums) == 0 {
return
}
g.P()
g.P(executeCommon())
g.P()
index := 0
for _, enum := range file.Enums {
if !genErrorsReason(gen, file, g, enum) {
index++
}
}
// If all enums do not contain 'errors.code', the current file is skipped
if index == 0 {
g.Skip()
}
}
func genErrorsReason(_ *protogen.Plugin, _ *protogen.File, g *protogen.GeneratedFile, enum *protogen.Enum) bool {
defaultCode := proto.GetExtension(enum.Desc.Options(), errors.E_DefaultHttpCode)
code := 0
if ok := defaultCode.(int32); ok != 0 {
code = int(ok)
}
if code > 600 || code < 0 {
panic(fmt.Sprintf("Enum '%s' range must be greater than 0 and less than or equal to 600", string(enum.Desc.Name())))
}
var ew errorWrapper
for _, v := range enum.Values {
enumCode := code
eCode := proto.GetExtension(v.Desc.Options(), errors.E_HttpCode)
if ok := eCode.(int32); ok != 0 {
enumCode = int(ok)
}
// If the current enumeration does not contain 'errors.code'
// or the code value exceeds the range, the current enum will be skipped
if enumCode > 600 || enumCode < 0 {
panic(fmt.Sprintf("Enum '%s' range must be greater than 0 and less than or equal to 600", string(v.Desc.Name())))
}
if enumCode == 0 {
continue
}
comment := v.Comments.Leading.String()
if comment == "" {
comment = v.Comments.Trailing.String()
}
err := &errorInfo{
Name: string(enum.Desc.Name()),
Value: string(v.Desc.Name()),
CamelValue: case2Camel(string(v.Desc.Name())),
HTTPCode: enumCode,
Comment: comment,
HasComment: len(comment) > 0,
}
ew.Errors = append(ew.Errors, err)
}
if len(ew.Errors) == 0 {
return true
}
g.P(ew.execute())
return false
}
func case2Camel(name string) string {
if !strings.Contains(name, "_") {
if name == strings.ToUpper(name) {
name = strings.ToLower(name)
}
return enCases.String(name)
}
strs := strings.Split(name, "_")
words := make([]string, 0, len(strs))
for _, w := range strs {
hasLower := false
for _, r := range w {
if unicode.IsLower(r) {
hasLower = true
break
}
}
if !hasLower {
w = strings.ToLower(w)
}
w = enCases.String(w)
words = append(words, w)
}
return strings.Join(words, "")
}