5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-02 17:52:29 +08:00

fix: blank namespaces, unknown structs

This commit is contained in:
Lea Anthony 2022-04-06 19:13:10 +10:00
parent dce5fd442f
commit 43f8a1f773
2 changed files with 103 additions and 34 deletions

View File

@ -84,29 +84,34 @@ func (b *Bindings) ToJSON() (string, error) {
func (b *Bindings) WriteModels(modelsDir string) error { func (b *Bindings) WriteModels(modelsDir string) error {
models := map[string]string{} models := map[string]string{}
var seen slicer.StringSlicer var seen slicer.StringSlicer
allStructNames := b.getAllStructNames()
for packageName, structsToGenerate := range b.structsToGenerateTS { for packageName, structsToGenerate := range b.structsToGenerateTS {
thisPackageCode := "" thisPackageCode := ""
w := typescriptify.New()
w.Namespace = packageName
w.WithBackupDir("")
w.KnownStructs = allStructNames
for structName, structInterface := range structsToGenerate { for structName, structInterface := range structsToGenerate {
fqstructname := packageName + "." + structName fqstructname := packageName + "." + structName
if seen.Contains(fqstructname) { if seen.Contains(fqstructname) {
continue continue
} }
w := typescriptify.New()
w.Namespace = packageName
w.WithBackupDir("")
w.Add(structInterface) w.Add(structInterface)
str, err := w.Convert(nil)
if err != nil {
return err
}
thisPackageCode += str
seen.AddSlice(w.GetGeneratedStructs())
} }
str, err := w.Convert(nil)
if err != nil {
return err
}
thisPackageCode += str
seen.AddSlice(w.GetGeneratedStructs())
models[packageName] = thisPackageCode models[packageName] = thisPackageCode
} }
var modelsData bytes.Buffer var modelsData bytes.Buffer
for packageName, modelData := range models { for packageName, modelData := range models {
if strings.TrimSpace(modelData) == "" {
continue
}
modelsData.WriteString("export namespace " + packageName + " {\n") modelsData.WriteString("export namespace " + packageName + " {\n")
sc := bufio.NewScanner(strings.NewReader(modelData)) sc := bufio.NewScanner(strings.NewReader(modelData))
for sc.Scan() { for sc.Scan() {
@ -156,17 +161,55 @@ func (b *Bindings) AddStructToGenerateTS(packageName string, structName string,
sName := strings.Split(fqname, ".")[1] sName := strings.Split(fqname, ".")[1]
pName := getPackageName(fqname) pName := getPackageName(fqname)
a := reflect.New(field.Type) a := reflect.New(field.Type)
s := reflect.Indirect(a).Interface() if b.hasExportedJSONFields(field.Type) {
b.AddStructToGenerateTS(pName, sName, s) s := reflect.Indirect(a).Interface()
b.AddStructToGenerateTS(pName, sName, s)
}
} else if kind == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct { } else if kind == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct {
fqname := field.Type.String() fqname := field.Type.String()
sName := strings.Split(fqname, ".")[1] sName := strings.Split(fqname, ".")[1]
pName := getPackageName(fqname) pName := getPackageName(fqname)
typ := field.Type.Elem() typ := field.Type.Elem()
a := reflect.New(typ) a := reflect.New(typ)
s := reflect.Indirect(a).Interface() if b.hasExportedJSONFields(typ) {
b.AddStructToGenerateTS(pName, sName, s) s := reflect.Indirect(a).Interface()
b.AddStructToGenerateTS(pName, sName, s)
}
} }
} }
} }
func (b *Bindings) getAllStructNames() *slicer.StringSlicer {
var result slicer.StringSlicer
for packageName, structsToGenerate := range b.structsToGenerateTS {
for structName := range structsToGenerate {
result.Add(packageName + "." + structName)
}
}
return &result
}
func (b *Bindings) hasExportedJSONFields(typeOf reflect.Type) bool {
for i := 0; i < typeOf.NumField(); i++ {
jsonFieldName := ""
f := typeOf.Field(i)
jsonTag := f.Tag.Get("json")
if len(jsonTag) == 0 {
continue
}
jsonTagParts := strings.Split(jsonTag, ",")
if len(jsonTagParts) > 0 {
jsonFieldName = jsonTagParts[0]
}
for _, t := range jsonTagParts {
if t == "-" {
continue
}
}
if jsonFieldName != "" {
return true
}
}
return false
}

View File

@ -3,6 +3,7 @@ package typescriptify
import ( import (
"bufio" "bufio"
"fmt" "fmt"
"github.com/leaanthony/slicer"
"io/ioutil" "io/ioutil"
"os" "os"
"path" "path"
@ -97,7 +98,8 @@ type TypeScriptify struct {
// throwaway, used when converting // throwaway, used when converting
alreadyConverted map[string]bool alreadyConverted map[string]bool
Namespace string Namespace string
KnownStructs *slicer.StringSlicer
} }
func New() *TypeScriptify { func New() *TypeScriptify {
@ -134,7 +136,7 @@ func New() *TypeScriptify {
return result return result
} }
func deepFields(typeOf reflect.Type) []reflect.StructField { func (t *TypeScriptify) deepFields(typeOf reflect.Type) []reflect.StructField {
fields := make([]reflect.StructField, 0) fields := make([]reflect.StructField, 0)
if typeOf.Kind() == reflect.Ptr { if typeOf.Kind() == reflect.Ptr {
@ -147,16 +149,20 @@ func deepFields(typeOf reflect.Type) []reflect.StructField {
for i := 0; i < typeOf.NumField(); i++ { for i := 0; i < typeOf.NumField(); i++ {
f := typeOf.Field(i) f := typeOf.Field(i)
kind := f.Type.Kind() kind := f.Type.Kind()
isPointer := kind == reflect.Ptr && f.Type.Elem().Kind() == reflect.Struct
if f.Anonymous && kind == reflect.Struct { if f.Anonymous && kind == reflect.Struct {
//fmt.Println(v.Interface()) //fmt.Println(v.Interface())
fields = append(fields, deepFields(f.Type)...) fields = append(fields, t.deepFields(f.Type)...)
} else if f.Anonymous && kind == reflect.Ptr && f.Type.Elem().Kind() == reflect.Struct { } else if f.Anonymous && isPointer {
//fmt.Println(v.Interface()) //fmt.Println(v.Interface())
fields = append(fields, deepFields(f.Type.Elem())...) fields = append(fields, t.deepFields(f.Type.Elem())...)
} else { } else {
fields = append(fields, f) // Check we have a json tag
jsonTag := t.getJSONFieldName(f, isPointer)
if jsonTag != "" {
fields = append(fields, f)
}
} }
} }
@ -348,7 +354,6 @@ func (t *TypeScriptify) Convert(customCode map[string]string) (string, error) {
result += "\n" + strings.Trim(typeScriptCode, " "+t.Indent+"\r\n") result += "\n" + strings.Trim(typeScriptCode, " "+t.Indent+"\r\n")
} }
fmt.Printf("t.structTypes: %+v\n", t.structTypes)
for _, strctTyp := range t.structTypes { for _, strctTyp := range t.structTypes {
typeScriptCode, err := t.convertType(depth, strctTyp.Type, customCode) typeScriptCode, err := t.convertType(depth, strctTyp.Type, customCode)
if err != nil { if err != nil {
@ -561,6 +566,10 @@ func (t *TypeScriptify) convertType(depth int, typeOf reflect.Type, customCode m
if _, found := t.alreadyConverted[typeOf.String()]; found { // Already converted if _, found := t.alreadyConverted[typeOf.String()]; found { // Already converted
return "", nil return "", nil
} }
fields := t.deepFields(typeOf)
if len(fields) == 0 {
return "", nil
}
t.logf(depth, "Converting type %s", typeOf.String()) t.logf(depth, "Converting type %s", typeOf.String())
if strings.ContainsRune(typeOf.String(), '.') { if strings.ContainsRune(typeOf.String(), '.') {
namespace := strings.Split(typeOf.String(), ".")[0] namespace := strings.Split(typeOf.String(), ".")[0]
@ -589,7 +598,6 @@ func (t *TypeScriptify) convertType(depth int, typeOf reflect.Type, customCode m
namespace: t.Namespace, namespace: t.Namespace,
} }
fields := deepFields(typeOf)
for _, field := range fields { for _, field := range fields {
isPtr := field.Type.Kind() == reflect.Ptr isPtr := field.Type.Kind() == reflect.Ptr
if isPtr { if isPtr {
@ -620,7 +628,10 @@ func (t *TypeScriptify) convertType(depth int, typeOf reflect.Type, customCode m
if typeScriptChunk != "" { if typeScriptChunk != "" {
result = typeScriptChunk + "\n" + result result = typeScriptChunk + "\n" + result
} }
builder.AddStructField(jsonFieldName, field) isKnownType := t.KnownStructs.Contains(getStructFQN(field.Type.String()))
println("KnownStructs:", t.KnownStructs.Join("\t"))
println(getStructFQN(field.Type.String()))
builder.AddStructField(jsonFieldName, field, !isKnownType)
} else if field.Type.Kind() == reflect.Map { } else if field.Type.Kind() == reflect.Map {
t.logf(depth, "- map field %s.%s", typeOf.Name(), field.Name) t.logf(depth, "- map field %s.%s", typeOf.Name(), field.Name)
// Also convert map key types if needed // Also convert map key types if needed
@ -756,11 +767,11 @@ func (t *typeScriptClassBuilder) AddSimpleArrayField(fieldName string, field ref
if len(fieldName) > 0 { if len(fieldName) > 0 {
strippedFieldName := strings.ReplaceAll(fieldName, "?", "") strippedFieldName := strings.ReplaceAll(fieldName, "?", "")
if len(opts.TSType) > 0 { if len(opts.TSType) > 0 {
t.addField(fieldName, opts.TSType) t.addField(fieldName, opts.TSType, false)
t.addInitializerFieldLine(strippedFieldName, fmt.Sprintf("source[\"%s\"]", strippedFieldName)) t.addInitializerFieldLine(strippedFieldName, fmt.Sprintf("source[\"%s\"]", strippedFieldName))
return nil return nil
} else if len(typeScriptType) > 0 { } else if len(typeScriptType) > 0 {
t.addField(fieldName, fmt.Sprint(typeScriptType, strings.Repeat("[]", arrayDepth))) t.addField(fieldName, fmt.Sprint(typeScriptType, strings.Repeat("[]", arrayDepth)), false)
t.addInitializerFieldLine(strippedFieldName, fmt.Sprintf("source[\"%s\"]", strippedFieldName)) t.addInitializerFieldLine(strippedFieldName, fmt.Sprintf("source[\"%s\"]", strippedFieldName))
return nil return nil
} }
@ -779,7 +790,7 @@ func (t *typeScriptClassBuilder) AddSimpleField(fieldName string, field reflect.
if len(typeScriptType) > 0 && len(fieldName) > 0 { if len(typeScriptType) > 0 && len(fieldName) > 0 {
strippedFieldName := strings.ReplaceAll(fieldName, "?", "") strippedFieldName := strings.ReplaceAll(fieldName, "?", "")
t.addField(fieldName, typeScriptType) t.addField(fieldName, typeScriptType, false)
if opts.TSTransform == "" { if opts.TSTransform == "" {
t.addInitializerFieldLine(strippedFieldName, fmt.Sprintf("source[\"%s\"]", strippedFieldName)) t.addInitializerFieldLine(strippedFieldName, fmt.Sprintf("source[\"%s\"]", strippedFieldName))
} else { } else {
@ -795,26 +806,31 @@ func (t *typeScriptClassBuilder) AddSimpleField(fieldName string, field reflect.
func (t *typeScriptClassBuilder) AddEnumField(fieldName string, field reflect.StructField) { func (t *typeScriptClassBuilder) AddEnumField(fieldName string, field reflect.StructField) {
fieldType := field.Type.Name() fieldType := field.Type.Name()
t.addField(fieldName, t.prefix+fieldType+t.suffix) t.addField(fieldName, t.prefix+fieldType+t.suffix, false)
strippedFieldName := strings.ReplaceAll(fieldName, "?", "") strippedFieldName := strings.ReplaceAll(fieldName, "?", "")
t.addInitializerFieldLine(strippedFieldName, fmt.Sprintf("source[\"%s\"]", strippedFieldName)) t.addInitializerFieldLine(strippedFieldName, fmt.Sprintf("source[\"%s\"]", strippedFieldName))
} }
func (t *typeScriptClassBuilder) AddStructField(fieldName string, field reflect.StructField) { func (t *typeScriptClassBuilder) AddStructField(fieldName string, field reflect.StructField, isAnyType bool) {
strippedFieldName := strings.ReplaceAll(fieldName, "?", "") strippedFieldName := strings.ReplaceAll(fieldName, "?", "")
namespace := strings.Split(field.Type.String(), ".")[0] namespace := strings.Split(field.Type.String(), ".")[0]
fqname := field.Type.Name() fqname := "any"
classname := "null"
fqname = field.Type.Name()
if namespace != t.namespace { if namespace != t.namespace {
fqname = field.Type.String() fqname = field.Type.String()
} }
t.addField(fieldName, fqname) if !isAnyType {
t.addInitializerFieldLine(strippedFieldName, fmt.Sprintf("this.convertValues(source[\"%s\"], %s)", strippedFieldName, fqname)) classname = fqname
}
t.addField(fieldName, fqname, isAnyType)
t.addInitializerFieldLine(strippedFieldName, fmt.Sprintf("this.convertValues(source[\"%s\"], %s)", strippedFieldName, classname))
} }
func (t *typeScriptClassBuilder) AddArrayOfStructsField(fieldName string, field reflect.StructField, arrayDepth int) { func (t *typeScriptClassBuilder) AddArrayOfStructsField(fieldName string, field reflect.StructField, arrayDepth int) {
fieldType := field.Type.Elem().Name() fieldType := field.Type.Elem().Name()
strippedFieldName := strings.ReplaceAll(fieldName, "?", "") strippedFieldName := strings.ReplaceAll(fieldName, "?", "")
t.addField(fieldName, fmt.Sprint(t.prefix+fieldType+t.suffix, strings.Repeat("[]", arrayDepth))) t.addField(fieldName, fmt.Sprint(t.prefix+fieldType+t.suffix, strings.Repeat("[]", arrayDepth)), false)
t.addInitializerFieldLine(strippedFieldName, fmt.Sprintf("this.convertValues(source[\"%s\"], %s)", strippedFieldName, t.prefix+fieldType+t.suffix)) t.addInitializerFieldLine(strippedFieldName, fmt.Sprintf("this.convertValues(source[\"%s\"], %s)", strippedFieldName, t.prefix+fieldType+t.suffix))
} }
@ -823,8 +839,12 @@ func (t *typeScriptClassBuilder) addInitializerFieldLine(fld, initializer string
t.constructorBody = append(t.constructorBody, fmt.Sprint(t.indent, t.indent, "this.", fld, " = ", initializer, ";")) t.constructorBody = append(t.constructorBody, fmt.Sprint(t.indent, t.indent, "this.", fld, " = ", initializer, ";"))
} }
func (t *typeScriptClassBuilder) addField(fld, fldType string) { func (t *typeScriptClassBuilder) addField(fld, fldType string, isAnyType bool) {
t.fields = append(t.fields, fmt.Sprint(t.indent, fld, ": ", fldType, ";")) if isAnyType {
t.fields = append(t.fields, fmt.Sprint(t.indent, "// Go type: ", fldType, "\n", t.indent, fld, ": any;"))
} else {
t.fields = append(t.fields, fmt.Sprint(t.indent, fld, ": ", fldType, ";"))
}
} }
func indentLines(str string, i int) string { func indentLines(str string, i int) string {
@ -834,3 +854,9 @@ func indentLines(str string, i int) string {
} }
return strings.Join(lines, "\n") return strings.Join(lines, "\n")
} }
func getStructFQN(in string) string {
result := strings.ReplaceAll(in, "[]", "")
result = strings.ReplaceAll(result, "*", "")
return result
}