mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-02 19:01:02 +08:00
v3 parser: initial work on model generation w/ templates (#2428)
* v3 parser: initial work on model generation w/ templates * v3 parser: expand models to namespaces
This commit is contained in:
parent
00c458f948
commit
da90e74268
@ -1,5 +1,45 @@
|
|||||||
package parser
|
package parser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ModelDefinitions struct {
|
||||||
|
Package string
|
||||||
|
Models map[string]*StructDef
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenerateModel(wr io.Writer, def *ModelDefinitions) error {
|
||||||
|
tmpl, err := template.New("model.ts.tmpl").ParseFiles("templates/model.ts.tmpl")
|
||||||
|
if err != nil {
|
||||||
|
println("Unable to create class template: " + err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tmpl.ExecuteTemplate(wr, "model.ts.tmpl", def)
|
||||||
|
if err != nil {
|
||||||
|
println("Problem executing template: " + err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//func GenerateClass(wr io.Writer, def *StructDef) error {
|
||||||
|
// tmpl, err := template.New("class.ts.tmpl").ParseFiles("templates/class.ts.tmpl")
|
||||||
|
// if err != nil {
|
||||||
|
// println("Unable to create class template: " + err.Error())
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// err = tmpl.ExecuteTemplate(wr, "class.ts.tmpl", def)
|
||||||
|
// if err != nil {
|
||||||
|
// println("Problem executing template: " + err.Error())
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
// return nil
|
||||||
|
//}
|
||||||
|
|
||||||
//
|
//
|
||||||
//import (
|
//import (
|
||||||
// "bytes"
|
// "bytes"
|
||||||
|
133
v3/internal/parser/models_test.go
Normal file
133
v3/internal/parser/models_test.go
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
package parser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
const expected = `
|
||||||
|
export namespace main {
|
||||||
|
|
||||||
|
export class Person {
|
||||||
|
name: string;
|
||||||
|
parent: Person;
|
||||||
|
details: anon1;
|
||||||
|
address: package.Address;
|
||||||
|
|
||||||
|
static createFrom(source: any = {}) {
|
||||||
|
return new Person(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(source: any = {}) {
|
||||||
|
if ('string' === typeof source) {
|
||||||
|
source = JSON.parse(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.name = source["name"]
|
||||||
|
this.parent = source["parent"]
|
||||||
|
this.details = source["details"]
|
||||||
|
this.address = source["address"]
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class anon1 {
|
||||||
|
age: int;
|
||||||
|
address: string;
|
||||||
|
|
||||||
|
static createFrom(source: any = {}) {
|
||||||
|
return new anon1(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(source: any = {}) {
|
||||||
|
if ('string' === typeof source) {
|
||||||
|
source = JSON.parse(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.age = source["age"]
|
||||||
|
this.address = source["address"]
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
func TestGenerateClass(t *testing.T) {
|
||||||
|
person := StructDef{
|
||||||
|
Name: "Person",
|
||||||
|
Fields: []*Field{
|
||||||
|
{
|
||||||
|
Name: "Name",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Parent",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Name: "Person",
|
||||||
|
IsStruct: true,
|
||||||
|
IsPointer: true,
|
||||||
|
Package: "main",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Details",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Name: "anon1",
|
||||||
|
IsStruct: true,
|
||||||
|
Package: "main",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Address",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Name: "Address",
|
||||||
|
IsStruct: true,
|
||||||
|
IsPointer: true,
|
||||||
|
Package: "github.com/some/other/package",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
anon1 := StructDef{
|
||||||
|
Name: "anon1",
|
||||||
|
Fields: []*Field{
|
||||||
|
{
|
||||||
|
Name: "Age",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Name: "int",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Address",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var builder strings.Builder
|
||||||
|
models := make(map[string]*StructDef)
|
||||||
|
models["Person"] = &person
|
||||||
|
models["anon1"] = &anon1
|
||||||
|
def := ModelDefinitions{
|
||||||
|
Package: "main",
|
||||||
|
Models: models,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := GenerateModel(&builder, &def)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
text := builder.String()
|
||||||
|
println("Built string")
|
||||||
|
println(text)
|
||||||
|
if diff := cmp.Diff(expected, text); diff != "" {
|
||||||
|
t.Errorf("GenerateClass() failed:\n" + diff)
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type packagePath = string
|
type packagePath = string
|
||||||
@ -49,6 +50,21 @@ type Field struct {
|
|||||||
Type *ParameterType
|
Type *ParameterType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *Field) JSName() string {
|
||||||
|
return strings.ToLower(f.Name[0:1]) + f.Name[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *Field) JSDef(pkg string) string {
|
||||||
|
name := f.JSName()
|
||||||
|
|
||||||
|
if f.Type.Package == "" || f.Type.Package == pkg {
|
||||||
|
return fmt.Sprintf("%s: %s;", name, f.Type.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := strings.Split(f.Type.Package, "/")
|
||||||
|
return fmt.Sprintf("%s: %s.%s;", name, parts[len(parts)-1], f.Type.Name)
|
||||||
|
}
|
||||||
|
|
||||||
type ParsedPackage struct {
|
type ParsedPackage struct {
|
||||||
Pkg *ast.Package
|
Pkg *ast.Package
|
||||||
Name string
|
Name string
|
||||||
|
16
v3/internal/parser/templates/class.ts.tmpl
Normal file
16
v3/internal/parser/templates/class.ts.tmpl
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
export class {{.Name}} {
|
||||||
|
{{range .Fields}}{{.}}
|
||||||
|
{{end}}
|
||||||
|
static createFrom(source: any = {}) {
|
||||||
|
return new {{.Name}}(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(source: any = {}) {
|
||||||
|
if ('string' === typeof source) {
|
||||||
|
source = JSON.parse(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
{{range .Fields}}this.{{jsName .}} = source["{{jsName .}}"]
|
||||||
|
{{end}}
|
||||||
|
}
|
||||||
|
}
|
21
v3/internal/parser/templates/model.ts.tmpl
Normal file
21
v3/internal/parser/templates/model.ts.tmpl
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{{$pkg := .Package}}
|
||||||
|
export namespace {{.Package}} {
|
||||||
|
{{range $name, $def := .Models}}
|
||||||
|
export class {{$def.Name}} {
|
||||||
|
{{range $def.Fields}}{{.JSDef $pkg}}
|
||||||
|
{{end}}
|
||||||
|
static createFrom(source: any = {}) {
|
||||||
|
return new {{$def.Name}}(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(source: any = {}) {
|
||||||
|
if ('string' === typeof source) {
|
||||||
|
source = JSON.parse(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
{{range $def.Fields}}this.{{.JSName}} = source["{{.JSName}}"]
|
||||||
|
{{end}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user