refactor: 入口移至 cmd/fun,go install 后命令名为 fun

This commit is contained in:
2026-09-19 12:16:22 +08:00
parent e29767362a
commit 49ca7f098a
20 changed files with 1 additions and 1 deletions
+194
View File
@@ -0,0 +1,194 @@
package main
// Go 渲染器:fun v1.3.7 gen_go.go 的等价移植,输入从 reflect.Type 换成元数据类型树
import "strings"
type renderGo struct{}
// typeName 等价旧 typeToTemplateType:指针 → "*" 前缀,切片 → "[]",其余用原始类型名
func (renderGo) typeName(t *MetaType) string {
prefix := ""
if t.Optional {
prefix = "*"
}
if t.Kind == "slice" {
return prefix + "[]" + renderGo{}.typeName(t.Elem)
}
return prefix + t.Name
}
func (r renderGo) genService(svc MetaService, serviceContext *genServiceType, files fileSet) {
for _, gm := range svc.Methods {
var returnValueText string
var dtoText string
var argsText string
var genericTypeText string
// () error:无数据返回,客户端类型为 Void
if gm.Void {
genericTypeText = "Void"
returnValueText = "Result[Void]"
if gm.DTO != nil {
v := r.typeName(gm.DTO)
if !strings.Contains(v, "[]") && strings.Contains(v, "[") {
dtoText += "dto " + getGenericTypeName(v) + parseGenericTypeParams(v)
} else {
dtoText += "dto " + v
}
argsText += ",dto"
r.genStruct(gm.DTO, files)
}
serviceContext.GenMethodTypeList = append(serviceContext.GenMethodTypeList, &genMethodType{
MethodName: gm.Name,
ReturnValueText: returnValueText,
DtoText: dtoText,
ArgsText: argsText,
GenericTypeText: genericTypeText,
})
continue
}
if gm.IsStream {
serviceContext.IsIncludeStream = true
if gm.Returns == nil {
genericTypeText = "any"
returnValueText = "Void"
} else {
t := r.typeName(gm.Returns)
if !strings.Contains(t, "[]") && strings.Contains(t, "[") {
genericTypeText = getGenericTypeName(t) + parseGenericTypeParams(t)
} else {
genericTypeText = t
}
returnValueText = genericTypeText
r.genReturnTypes(gm.Returns, files)
}
} else {
t := r.typeName(gm.Returns)
if !strings.Contains(t, "[]") && strings.Contains(t, "[") {
returnValueText = getGenericTypeName(t) + parseGenericTypeParams(t)
} else {
returnValueText = t
}
genericTypeText = returnValueText
r.genReturnTypes(gm.Returns, files)
returnValueText = "Result[" + returnValueText + "]"
}
if gm.DTO != nil {
v := r.typeName(gm.DTO)
if !strings.Contains(v, "[]") && strings.Contains(v, "[") {
dtoText += "dto " + getGenericTypeName(v) + parseGenericTypeParams(v)
} else {
dtoText += "dto " + v
}
argsText += ",dto"
r.genStruct(gm.DTO, files)
}
serviceContext.GenMethodTypeList = append(serviceContext.GenMethodTypeList, &genMethodType{
MethodName: gm.Name,
ReturnValueText: returnValueText,
DtoText: dtoText,
ArgsText: argsText,
GenericTypeText: genericTypeText,
IsStream: gm.IsStream,
})
}
renderCode(templateGo{}.genServiceTemplate(), camelToSnake(svc.Name), serviceContext, "go", files)
}
// genReturnTypes 递归生成返回类型涉及的 struct/enum 定义
func (r renderGo) genReturnTypes(returnType *MetaType, files fileSet) {
if returnType.Kind == "struct" {
r.genStruct(returnType, files)
}
if returnType.Kind == "slice" && returnType.Elem.Kind == "struct" {
r.genStruct(returnType.Elem, files)
}
if returnType.Kind == "enum" {
r.getEnum(returnType, files)
}
}
func (r renderGo) renderAll(meta *FunMeta, files fileSet) {
genContext := genType{GenServiceList: []*genServiceType{}}
for _, svc := range meta.Services {
serviceContext := &genServiceType{
ServiceName: svc.Name,
GenMethodTypeList: []*genMethodType{},
}
genContext.GenServiceList = append(genContext.GenServiceList, serviceContext)
r.genService(svc, serviceContext, files)
}
renderCode(templateGo{}.genDefaultServiceTemplate(), "fun", genContext, "go", files)
}
func (r renderGo) genStruct(t *MetaType, files fileSet) *genImportType {
var structTemplate genClassType
if strings.Contains(t.Name, "[]") == false && strings.Contains(t.Name, "[") {
structTemplate = genClassType{
Name: getGenericTypeName(t.Name) + parseGenericTypeParams(t.Name),
}
} else {
structTemplate = genClassType{
Name: t.Name,
}
}
for _, field := range t.Fields {
fieldType := field.Type
jsType := r.typeName(fieldType)
tag := "`json:\"" + firstLetterToLower(field.Name) + "\"`"
if !strings.Contains(jsType, "[]") && strings.Contains(jsType, "[") {
structTemplate.GenClassFieldType = append(structTemplate.GenClassFieldType, &genClassFieldType{
Name: field.Name,
Type: getGenericTypeName(jsType) + parseGenericTypeParams(jsType),
Tag: tag,
})
} else {
structTemplate.GenClassFieldType = append(structTemplate.GenClassFieldType, &genClassFieldType{
Name: field.Name,
Type: jsType,
Tag: tag,
})
}
if fieldType.Kind == "struct" {
r.genStruct(fieldType, files)
}
if fieldType.Kind == "slice" && fieldType.Elem.Kind == "struct" {
r.genStruct(fieldType.Elem, files)
}
if fieldType.Kind == "enum" {
r.getEnum(fieldType, files)
}
}
renderCode(
templateGo{}.genStructTemplate(),
camelToSnake(structTemplate.Name),
structTemplate,
"go",
files,
)
return &genImportType{}
}
func (r renderGo) getEnum(t *MetaType, files fileSet) *genImportType {
var enumTemplate genEnumType
enumTemplate.Names = t.Names
enumTemplate.DisplayNames = t.DisplayNames
enumTemplate.Name = t.Name
renderCode(
templateGo{}.genEnumTemplate(),
camelToSnake(t.Name),
enumTemplate,
"go",
files,
)
return &genImportType{}
}