mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-03 03:40:12 +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 = {}) {
|
constructor(source: any = {}) {
|
||||||
if ('string' === typeof source) source = JSON.parse(source);
|
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 {
|
convertValues(a: any, classs: any, asMap: boolean = false): any {
|
||||||
if (!a) {
|
if (!a) {
|
||||||
|
@ -37,6 +37,8 @@ func TestBindings_GenerateModels(t *testing.T) {
|
|||||||
MultistructTest,
|
MultistructTest,
|
||||||
EmptyStructTest,
|
EmptyStructTest,
|
||||||
GeneratedJsEntityTest,
|
GeneratedJsEntityTest,
|
||||||
|
AnonymousSubStructTest,
|
||||||
|
AnonymousSubStructMultiLevelTest,
|
||||||
}
|
}
|
||||||
|
|
||||||
testLogger := &logger.Logger{}
|
testLogger := &logger.Logger{}
|
||||||
|
@ -641,6 +641,10 @@ func (t *TypeScriptify) convertType(depth int, typeOf reflect.Type, customCode m
|
|||||||
err = builder.AddSimpleField(jsonFieldName, field, fldOpts)
|
err = builder.AddSimpleField(jsonFieldName, field, fldOpts)
|
||||||
} else if field.Type.Kind() == reflect.Struct { // Struct:
|
} else if field.Type.Kind() == reflect.Struct { // Struct:
|
||||||
t.logf(depth, "- struct %s.%s (%s)", typeOf.Name(), field.Name, field.Type.String())
|
t.logf(depth, "- struct %s.%s (%s)", typeOf.Name(), field.Name, field.Type.String())
|
||||||
|
|
||||||
|
// 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)
|
typeScriptChunk, err := t.convertType(depth+1, field.Type, customCode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@ -648,6 +652,8 @@ func (t *TypeScriptify) convertType(depth int, typeOf reflect.Type, customCode m
|
|||||||
if typeScriptChunk != "" {
|
if typeScriptChunk != "" {
|
||||||
result = typeScriptChunk + "\n" + result
|
result = typeScriptChunk + "\n" + result
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
isKnownType := t.KnownStructs.Contains(getStructFQN(field.Type.String()))
|
isKnownType := t.KnownStructs.Contains(getStructFQN(field.Type.String()))
|
||||||
println("KnownStructs:", t.KnownStructs.Join("\t"))
|
println("KnownStructs:", t.KnownStructs.Join("\t"))
|
||||||
println(getStructFQN(field.Type.String()))
|
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) {
|
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]
|
fqname := field.Type.Name()
|
||||||
fqname := "any"
|
|
||||||
classname := "null"
|
classname := "null"
|
||||||
fqname = field.Type.Name()
|
|
||||||
|
namespace := strings.Split(field.Type.String(), ".")[0]
|
||||||
|
|
||||||
if namespace != t.namespace {
|
if namespace != t.namespace {
|
||||||
fqname = field.Type.String()
|
fqname = field.Type.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
if !isAnyType {
|
if !isAnyType {
|
||||||
classname = fqname
|
classname = fqname
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Anonymous struct
|
||||||
|
if field.Type.Name() == "" {
|
||||||
|
classname = "Object"
|
||||||
|
}
|
||||||
|
|
||||||
t.addField(fieldName, fqname, isAnyType)
|
t.addField(fieldName, fqname, isAnyType)
|
||||||
t.addInitializerFieldLine(strippedFieldName, fmt.Sprintf("this.convertValues(source[\"%s\"], %s)", strippedFieldName, classname))
|
t.addInitializerFieldLine(strippedFieldName, fmt.Sprintf("this.convertValues(source[\"%s\"], %s)", strippedFieldName, classname))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user