182 lines
4.2 KiB
Go
182 lines
4.2 KiB
Go
// exportable typescript generated from golang
|
|
// Copyright (C) 2022 Fabio Prada
|
|
|
|
package tsrpc
|
|
|
|
import (
|
|
"fmt"
|
|
"go/ast"
|
|
"slices"
|
|
"strings"
|
|
)
|
|
|
|
type TSSField struct {
|
|
Name string
|
|
Type string
|
|
TsType string
|
|
Json TSTagJson
|
|
Ts TSTagTs
|
|
DependOn bool
|
|
}
|
|
|
|
type TSStruct struct {
|
|
Name string
|
|
Typescript bool
|
|
Fields []TSSField
|
|
Imports []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:
|
|
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(getFieldTsInfo(ft.Value)))
|
|
case *ast.InterfaceType:
|
|
result = "unknown"
|
|
case *ast.FuncType:
|
|
fmt.Println("*ast.FuncType found, skipping...")
|
|
default:
|
|
exitOnError(fmt.Errorf("getFieldTsInfo can't evaluate type: %T %T", t, ft))
|
|
}
|
|
return result
|
|
}
|
|
|
|
func (s *TSStruct) getStruct(ts *ast.TypeSpec) {
|
|
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)
|
|
|
|
if tagTs.Type == "Debugger" {
|
|
fmt.Printf("Debugger tag found in field %s, skipping field\n", field.Names[0].String())
|
|
}
|
|
|
|
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),
|
|
}
|
|
if len(strings.Split(f.Type, ".")) == 2 && tagTs.Type == "" {
|
|
a := strings.Split(f.Type, ".")
|
|
a[1] = strings.Trim(a[1], "[]*")
|
|
a[0] = strings.Trim(a[0], "[]*")
|
|
imp := fmt.Sprintf("%s.%s", a[0], a[1])
|
|
if !slices.Contains(s.Imports, imp) {
|
|
s.Imports = append(s.Imports, imp)
|
|
}
|
|
}
|
|
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),
|
|
}
|
|
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,
|
|
}
|
|
s.Fields = append(s.Fields, f)
|
|
} else {
|
|
exitOnError(fmt.Errorf("this typescript type: %T is not evaluated", field.Type))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|