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

Fix issue with anonymous structures (#2186)

Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
This commit is contained in:
Vadim Shchepotev 2022-12-20 03:54:11 -08:00 committed by GitHub
parent 04e92a813b
commit e2f1429c67
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 150 additions and 10 deletions

View File

@ -0,0 +1,65 @@
package binding_test
type StructWithAnonymousSubMultiLevelStruct struct {
Name string `json:"name"`
Meta struct {
Age int `json:"age"`
More struct {
Info string `json:"info"`
MoreInMore struct {
Demo string `json:"demo"`
} `json:"more_in_more"`
} `json:"more"`
} `json:"meta"`
}
func (s StructWithAnonymousSubMultiLevelStruct) Get() StructWithAnonymousSubMultiLevelStruct {
return s
}
var AnonymousSubStructMultiLevelTest = BindingTest{
name: "StructWithAnonymousSubMultiLevelStruct",
structs: []interface{}{
&StructWithAnonymousSubMultiLevelStruct{},
},
exemptions: nil,
shouldError: false,
want: `
export namespace binding_test {
export class StructWithAnonymousSubMultiLevelStruct {
name: string;
// Go type: struct { Age int "json:\"age\""; More struct { Info string "json:\"info\""; MoreInMore struct { Demo string "json:\"demo\"" } "json:\"more_in_more\"" } "json:\"more\"" }
meta: any;
static createFrom(source: any = {}) {
return new StructWithAnonymousSubMultiLevelStruct(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.name = source["name"];
this.meta = this.convertValues(source["meta"], Object);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
}
`,
}

View File

@ -0,0 +1,59 @@
package binding_test
type StructWithAnonymousSubStruct struct {
Name string `json:"name"`
Meta struct {
Age int `json:"age"`
} `json:"meta"`
}
func (s StructWithAnonymousSubStruct) Get() StructWithAnonymousSubStruct {
return s
}
var AnonymousSubStructTest = BindingTest{
name: "StructWithAnonymousSubStruct",
structs: []interface{}{
&StructWithAnonymousSubStruct{},
},
exemptions: nil,
shouldError: false,
want: `
export namespace binding_test {
export class StructWithAnonymousSubStruct {
name: string;
// Go type: struct { Age int "json:\"age\"" }
meta: any;
static createFrom(source: any = {}) {
return new StructWithAnonymousSubStruct(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.name = source["name"];
this.meta = this.convertValues(source["meta"], Object);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {
return a;
}
if (a.slice) {
return (a as any[]).map(elem => this.convertValues(elem, classs));
} else if ("object" === typeof a) {
if (asMap) {
for (const key of Object.keys(a)) {
a[key] = new classs(a[key]);
}
return a;
}
return new classs(a);
}
return a;
}
}
}
`,
}

View File

@ -27,7 +27,7 @@ export namespace binding_test {
}
constructor(source: any = {}) {
if ('string' === typeof source) source = JSON.parse(source);
this.empty = this.convertValues(source["empty"], null);
this.empty = this.convertValues(source["empty"], Object);
}
convertValues(a: any, classs: any, asMap: boolean = false): any {
if (!a) {

View File

@ -37,6 +37,8 @@ func TestBindings_GenerateModels(t *testing.T) {
MultistructTest,
EmptyStructTest,
GeneratedJsEntityTest,
AnonymousSubStructTest,
AnonymousSubStructMultiLevelTest,
}
testLogger := &logger.Logger{}

View File

@ -641,13 +641,19 @@ func (t *TypeScriptify) convertType(depth int, typeOf reflect.Type, customCode m
err = builder.AddSimpleField(jsonFieldName, field, fldOpts)
} else if field.Type.Kind() == reflect.Struct { // Struct:
t.logf(depth, "- struct %s.%s (%s)", typeOf.Name(), field.Name, field.Type.String())
typeScriptChunk, err := t.convertType(depth+1, field.Type, customCode)
if err != nil {
return "", err
}
if typeScriptChunk != "" {
result = typeScriptChunk + "\n" + result
// Anonymous structures is ignored
// It is possible to generate them but hard to generate correct name
if field.Type.Name() != "" {
typeScriptChunk, err := t.convertType(depth+1, field.Type, customCode)
if err != nil {
return "", err
}
if typeScriptChunk != "" {
result = typeScriptChunk + "\n" + result
}
}
isKnownType := t.KnownStructs.Contains(getStructFQN(field.Type.String()))
println("KnownStructs:", t.KnownStructs.Join("\t"))
println(getStructFQN(field.Type.String()))
@ -833,16 +839,24 @@ func (t *typeScriptClassBuilder) AddEnumField(fieldName string, field reflect.St
func (t *typeScriptClassBuilder) AddStructField(fieldName string, field reflect.StructField, isAnyType bool) {
strippedFieldName := strings.ReplaceAll(fieldName, "?", "")
namespace := strings.Split(field.Type.String(), ".")[0]
fqname := "any"
fqname := field.Type.Name()
classname := "null"
fqname = field.Type.Name()
namespace := strings.Split(field.Type.String(), ".")[0]
if namespace != t.namespace {
fqname = field.Type.String()
}
if !isAnyType {
classname = fqname
}
// Anonymous struct
if field.Type.Name() == "" {
classname = "Object"
}
t.addField(fieldName, fqname, isAnyType)
t.addInitializerFieldLine(strippedFieldName, fmt.Sprintf("this.convertValues(source[\"%s\"], %s)", strippedFieldName, classname))
}