go-quasar-partial-ssr/backend/pkg/ts-rpc/tsStruct.go

188 lines
4.4 KiB
Go

// exportable typescript generated from golang
// Copyright (C) 2022 Fabio Prada
package tsrpc
import (
"fmt"
"go/ast"
)
type TSSField struct {
Name string
Type string
TsType string
Json TSTagJson
Ts TSTagTs
DependOn bool
SourceInfo string
}
type TSStruct struct {
Name string
Typescript bool
Fields []TSSField
SourceInfo string
}
func IsNativeType(t string) bool {
switch t {
case "uint8", "uint16", "uint32", "uint64", "uint",
"int8", "int16", "int32", "int64", "int",
"float32", "float64":
return true
case "bool":
return true
case "string":
return true
}
return false
}
func toBeImported(t ast.Expr) bool {
switch ft := t.(type) {
case *ast.Ident:
return !IsNativeType(ft.Name)
case *ast.SelectorExpr:
return true
}
return false
}
func typeToTypescript(k string) string {
switch k {
case "uint8", "uint16", "uint32", "uint64", "uint",
"int8", "int16", "int32", "int64", "int",
"float32", "float64":
return "number"
case "bool":
return "boolean"
case "string":
return "string"
}
return k
}
func getFieldInfo(t ast.Expr) string {
result := ""
switch ft := t.(type) {
case *ast.Ident:
result = ft.Name
case *ast.SelectorExpr:
result = fmt.Sprintf("%s.%s", ft.X, ft.Sel)
case *ast.ArrayType:
result = fmt.Sprintf("[]%s", getFieldInfo(ft.Elt))
case *ast.StarExpr:
result = fmt.Sprintf("*%s", (ft.X))
case *ast.MapType:
result = fmt.Sprintf("map[%s]%s", ft.Key, getFieldInfo(ft.Value))
case *ast.InterfaceType:
result = "interface{}"
default:
f := fmt.Sprintf("this go type: %T is not evaluated", ft)
fmt.Println(f)
//exitOnError(fmt.Errorf("this go type: %T is not evaluated", ft))
}
return result
}
func getFieldTsInfo(t ast.Expr) string {
result := ""
switch ft := t.(type) {
case *ast.Ident:
result = typeToTypescript(ft.Name)
case *ast.SelectorExpr:
result = typeToTypescript(fmt.Sprintf("%s.%s", ft.X, ft.Sel))
case *ast.ArrayType:
result = fmt.Sprintf("%s[]", typeToTypescript(getFieldTsInfo(ft.Elt)))
case *ast.StarExpr:
result = fmt.Sprintf("Nullable<%s>", typeToTypescript(getFieldTsInfo(ft.X)))
case *ast.MapType:
result = fmt.Sprintf("Record<%s , %s>", typeToTypescript(fmt.Sprintf("%s", ft.Key)), typeToTypescript(("ft.Value")))
case *ast.InterfaceType:
result = "unknown"
case *ast.FuncType:
fmt.Println("*ast.FuncType found, skipping...")
default:
//f := fmt.Sprintf("getFieldTsInfo can't evaluate type: %T %T", t, ft)
//fmt.Println(f)
exitOnError(fmt.Errorf("getFieldTsInfo can't evaluate type: %T %T", t, ft))
}
return result
}
func getSourceInfo(pos int, src []TSSourceFile) string {
for _, v := range src {
for _, l := range v.Lines {
if pos >= l.Pos && pos <= l.End {
return fmt.Sprintf("%s Line: %d", v.Name, l.Line)
}
}
}
return ""
}
func (s *TSStruct) getStruct(ts *ast.TypeSpec, src []TSSourceFile) {
if st, ok := ts.Type.(*ast.StructType); ok {
for _, field := range st.Fields.List {
tag := ""
if field.Tag != nil {
tag = field.Tag.Value
}
tagJson := TSTagJson{}
tagJson.parse(tag)
tagTs := TSTagTs{}
tagTs.parse(tag)
tsType := ""
if len(field.Names) > 0 {
tsType = getFieldTsInfo(field.Type)
var f = TSSField{
Name: field.Names[0].String(),
Json: tagJson,
Ts: tagTs,
Type: getFieldInfo(field.Type),
TsType: tsType,
DependOn: toBeImported(field.Type),
SourceInfo: getSourceInfo(int(field.Type.Pos()), src),
}
s.Fields = append(s.Fields, f)
} else {
if se, ok := field.Type.(*ast.SelectorExpr); ok {
var f = TSSField{
Name: fmt.Sprintf("%s.%s", se.X, se.Sel),
Json: tagJson,
Ts: tagTs,
Type: getFieldInfo(field.Type),
TsType: tsType,
DependOn: toBeImported(field.Type),
SourceInfo: getSourceInfo(int(field.Type.Pos()), src),
}
s.Fields = append(s.Fields, f)
} else {
if se, ok := field.Type.(*ast.Ident); ok {
var f = TSSField{
Name: se.Name,
Json: tagJson,
Ts: tagTs,
Type: se.Name,
TsType: tsType,
DependOn: false,
SourceInfo: getSourceInfo(int(field.Type.Pos()), src),
}
s.Fields = append(s.Fields, f)
fmt.Println(f)
} else {
exitOnError(fmt.Errorf("this typescript type: %T is not evaluated", field.Type))
}
}
}
}
}
}