You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
3.5 KiB
134 lines
3.5 KiB
package main |
|
|
|
import ( |
|
"fmt" |
|
"strings" |
|
"unicode" |
|
|
|
"golang.org/x/text/cases" |
|
"golang.org/x/text/language" |
|
|
|
"github.com/go-kratos/kratos/cmd/protoc-gen-go-errors/v2/errors" |
|
"google.golang.org/protobuf/compiler/protogen" |
|
"google.golang.org/protobuf/proto" |
|
) |
|
|
|
const ( |
|
errorsPackage = protogen.GoImportPath("github.com/go-kratos/kratos/v2/errors") |
|
fmtPackage = protogen.GoImportPath("fmt") |
|
) |
|
|
|
var enCases = cases.Title(language.AmericanEnglish, cases.NoLower) |
|
|
|
// generateFile generates a _errors.pb.go file containing kratos errors definitions. |
|
func generateFile(gen *protogen.Plugin, file *protogen.File) *protogen.GeneratedFile { |
|
if len(file.Enums) == 0 { |
|
return nil |
|
} |
|
filename := file.GeneratedFilenamePrefix + "_errors.pb.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(fmtPackage.Ident("")) |
|
generateFileContent(gen, file, g) |
|
return g |
|
} |
|
|
|
// generateFileContent generates the kratos errors definitions, excluding the package statement. |
|
func generateFileContent(gen *protogen.Plugin, file *protogen.File, g *protogen.GeneratedFile) { |
|
if len(file.Enums) == 0 { |
|
return |
|
} |
|
|
|
g.P("// This is a compile-time assertion to ensure that this generated file") |
|
g.P("// is compatible with the kratos package it is being compiled against.") |
|
g.P("const _ = ", errorsPackage.Ident("SupportPackageIsVersion1")) |
|
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(gen *protogen.Plugin, file *protogen.File, g *protogen.GeneratedFile, enum *protogen.Enum) bool { |
|
defaultCode := proto.GetExtension(enum.Desc.Options(), errors.E_DefaultCode) |
|
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_Code) |
|
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, "") |
|
}
|
|
|