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:
parent
04e92a813b
commit
e2f1429c67
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
`,
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
`,
|
||||
}
|
@ -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) {
|
||||
|
@ -37,6 +37,8 @@ func TestBindings_GenerateModels(t *testing.T) {
|
||||
MultistructTest,
|
||||
EmptyStructTest,
|
||||
GeneratedJsEntityTest,
|
||||
AnonymousSubStructTest,
|
||||
AnonymousSubStructMultiLevelTest,
|
||||
}
|
||||
|
||||
testLogger := &logger.Logger{}
|
||||
|
@ -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))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user