From f046c0c2ee24a6be802a9a1c3cafd7bdb5523a4d Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Sat, 31 Oct 2020 15:31:44 +1100 Subject: [PATCH] Now parsing actual code --- v2/go.mod | 1 + v2/internal/parse/parse.go | 1 - .../build/internal/backendjs/conversion.go | 47 +- .../build/internal/backendjs/methods.go | 77 ---- .../internal/backendjs/package.d.template | 8 +- .../build/internal/backendjs/package.template | 6 +- .../build/internal/backendjs/packages.go | 183 ++++---- .../build/internal/backendjs/parse.go | 403 ++++++++++++++++++ .../build/internal/backendjs/structs.go | 13 + .../build/internal/backendjs/values.go | 55 +++ 10 files changed, 624 insertions(+), 170 deletions(-) delete mode 100644 v2/pkg/commands/build/internal/backendjs/methods.go create mode 100644 v2/pkg/commands/build/internal/backendjs/parse.go create mode 100644 v2/pkg/commands/build/internal/backendjs/structs.go create mode 100644 v2/pkg/commands/build/internal/backendjs/values.go diff --git a/v2/go.mod b/v2/go.mod index e2cb3aee..81d05d4b 100644 --- a/v2/go.mod +++ b/v2/go.mod @@ -3,6 +3,7 @@ module github.com/wailsapp/wails/v2 go 1.13 require ( + github.com/davecgh/go-spew v1.1.1 github.com/fsnotify/fsnotify v1.4.9 github.com/imdario/mergo v0.3.11 github.com/leaanthony/clir v1.0.4 diff --git a/v2/internal/parse/parse.go b/v2/internal/parse/parse.go index f448c088..e9d98236 100644 --- a/v2/internal/parse/parse.go +++ b/v2/internal/parse/parse.go @@ -65,7 +65,6 @@ func ParseProject(projectPath string) (BoundStructs, error) { var wailsPkgVar = "" ast.Inspect(file, func(n ast.Node) bool { - var s string switch x := n.(type) { // Parse import declarations case *ast.ImportSpec: diff --git a/v2/pkg/commands/build/internal/backendjs/conversion.go b/v2/pkg/commands/build/internal/backendjs/conversion.go index 0214599a..bed88fbc 100644 --- a/v2/pkg/commands/build/internal/backendjs/conversion.go +++ b/v2/pkg/commands/build/internal/backendjs/conversion.go @@ -1,7 +1,5 @@ package backendjs -import "reflect" - // JSType represents a javascript type type JSType string @@ -22,22 +20,45 @@ const ( JsUnsupported = "*" ) -func goTypeToJS(input reflect.Kind) JSType { +func goTypeToJS(input string) JSType { switch input { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, - reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - return JsInt - case reflect.String: + case "string": return JsString - case reflect.Float32, reflect.Float64, reflect.Complex64: + case "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64": + return JsInt + case "float32", "float64": return JsFloat - case reflect.Bool: + case "bool": return JsBoolean - case reflect.Array, reflect.Slice: - return JsArray - case reflect.Ptr, reflect.Struct, reflect.Map, reflect.Interface: - return JsObject + // case reflect.Array, reflect.Slice: + // return JsArray + // case reflect.Ptr, reflect.Struct, reflect.Map, reflect.Interface: + // return JsObject default: + println("UNSUPPORTED: ", input) + return JsUnsupported + } +} + +func goTypeToTS(input string) string { + switch input { + case "string": + return "string" + case "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64": + return "number" + case "float32", "float64": + return "number" + case "bool": + return "boolean" + // case reflect.Array, reflect.Slice: + // return string(JsArray) + // case reflect.Ptr, reflect.Struct: + // fqt := input.Type().String() + // return strings.Split(fqt, ".")[1] + // case reflect.Map, reflect.Interface: + // return string(JsObject) + default: + println("UNSUPPORTED: ", input) return JsUnsupported } } diff --git a/v2/pkg/commands/build/internal/backendjs/methods.go b/v2/pkg/commands/build/internal/backendjs/methods.go deleted file mode 100644 index cbcf7613..00000000 --- a/v2/pkg/commands/build/internal/backendjs/methods.go +++ /dev/null @@ -1,77 +0,0 @@ -package backendjs - -import ( - "fmt" - "reflect" - "strings" -) - -// Parameter defines a parameter used by a struct method -type Parameter struct { - Name string - Type reflect.Kind - StructName string -} - -// JSType returns the Javascript equivalent of the -// parameter type -func (p *Parameter) JSType() string { - return string(goTypeToJS(p.Type)) -} - -// Method defines a struct method -type Method struct { - Name string - Inputs []*Parameter - Outputs []*Parameter - Comments []string -} - -// InputsAsJSText generates a string with the method inputs -// formatted in a way acceptable to Javascript -func (m *Method) InputsAsJSText() string { - var inputs []string - - for _, input := range m.Inputs { - inputs = append(inputs, input.Name) - } - - return strings.Join(inputs, ", ") -} - -// InputsAsTSText generates a string with the method inputs -// formatted in a way acceptable to Typescript -func (m *Method) InputsAsTSText() string { - var inputs []string - - for _, input := range m.Inputs { - inputText := fmt.Sprintf("%s: %s", input.Name, goTypeToJS(input.Type)) - inputs = append(inputs, inputText) - } - - return strings.Join(inputs, ", ") -} - -// OutputsAsTSText generates a string with the method inputs -// formatted in a way acceptable to Javascript -func (m *Method) OutputsAsTSText() string { - - if len(m.Outputs) == 0 { - return "void" - } - - var result []string - - for _, output := range m.Outputs { - jsType := goTypeToJS(output.Type) - switch jsType { - case JsArray: - result = append(result, "Array") - case JsObject: - result = append(result, "any") - default: - result = append(result, string(jsType)) - } - } - return strings.Join(result, ", ") -} diff --git a/v2/pkg/commands/build/internal/backendjs/package.d.template b/v2/pkg/commands/build/internal/backendjs/package.d.template index 492d4005..0a4db6da 100644 --- a/v2/pkg/commands/build/internal/backendjs/package.d.template +++ b/v2/pkg/commands/build/internal/backendjs/package.d.template @@ -1,9 +1,9 @@ // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL // This file is automatically generated. DO NOT EDIT -{{range .Comments}}// {{.}}{{end}} -declare module {{.Name}} { - {{range .Methods}} +declare module {{.Struct.Name}} { + {{range .Struct.Methods}} {{if .Comments }}{{range .Comments}}// {{ . }}{{end}}{{end}} - function {{.Name}}({{.InputsAsTSText}}): Promise<{{.OutputsAsTSText}}>;{{end}} + function {{.Name}}({{.InputsAsTSText}}): Promise<{{.OutputsAsTSText}}>; + {{end}} } \ No newline at end of file diff --git a/v2/pkg/commands/build/internal/backendjs/package.template b/v2/pkg/commands/build/internal/backendjs/package.template index 64ae8313..efa55e18 100644 --- a/v2/pkg/commands/build/internal/backendjs/package.template +++ b/v2/pkg/commands/build/internal/backendjs/package.template @@ -1,8 +1,7 @@ // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL // This file is automatically generated. DO NOT EDIT -{{range .Comments}}// {{.}}{{end}} -{{range .Methods}} +{{range .Struct.Methods }} /**{{if .Comments }} {{range .Comments}} * {{ . }}{{end}} *{{end}} @@ -12,6 +11,7 @@ * @returns {Promise<{{.OutputsAsTSText}}>} */ export function {{.Name}}({{.InputsAsJSText}}) { - return window.backend.{{$.Name}}.{{.Name}}({{.InputsAsJSText}}); + return window.backend.{{$.PackageName}}.{{$.Struct.Name}}.{{.Name}}({{.InputsAsJSText}}); } {{end}} + diff --git a/v2/pkg/commands/build/internal/backendjs/packages.go b/v2/pkg/commands/build/internal/backendjs/packages.go index 8f45376e..77febd94 100644 --- a/v2/pkg/commands/build/internal/backendjs/packages.go +++ b/v2/pkg/commands/build/internal/backendjs/packages.go @@ -3,8 +3,8 @@ package backendjs import ( "bytes" "io/ioutil" + "os" "path/filepath" - "reflect" "text/template" "github.com/pkg/errors" @@ -15,7 +15,7 @@ import ( type Package struct { Name string Comments []string - Methods []*Method + Structs []*ParsedStruct } func generatePackages() error { @@ -35,67 +35,83 @@ func generatePackages() error { func parsePackages() ([]*Package, error) { - // STUB! - var result []*Package + cwd, err := os.Getwd() + if err != nil { + return nil, err + } + result, err := parseProject(cwd) + if err != nil { + return nil, err + } - result = append(result, &Package{ - Name: "mypackage", - Comments: []string{"mypackage is awesome"}, - Methods: []*Method{ - { - Name: "Naked", - Comments: []string{"Naked is a method that does nothing"}, - }, - }, - }) - result = append(result, &Package{ - Name: "otherpackage", - Comments: []string{"otherpackage is awesome"}, - Methods: []*Method{ - { - Name: "OneInput", - Comments: []string{"OneInput does stuff"}, - Inputs: []*Parameter{ - { - Name: "name", - Type: reflect.String, - }, - }, - }, - { - Name: "TwoInputs", - Inputs: []*Parameter{ - { - Name: "name", - Type: reflect.String, - }, - { - Name: "age", - Type: reflect.Uint8, - }, - }, - }, - { - Name: "TwoInputsAndOutput", - Inputs: []*Parameter{ - { - Name: "name", - Type: reflect.String, - }, - { - Name: "age", - Type: reflect.Uint8, - }, - }, - Outputs: []*Parameter{ - { - Name: "result", - Type: reflect.Bool, - }, - }, - }, - }, - }) + // result = append(result, &Package{ + // Name: "mypackage", + // Comments: []string{"mypackage is awesome"}, + // Methods: []*Method{ + // { + // Name: "Naked", + // Comments: []string{"Naked is a method that does nothing"}, + // }, + // }, + // }) + // result = append(result, &Package{ + // Name: "otherpackage", + // Comments: []string{"otherpackage is awesome"}, + // Methods: []*Method{ + // { + // Name: "OneInput", + // Comments: []string{"OneInput does stuff"}, + // Inputs: []*Parameter{ + // { + // Name: "name", + // Value: String, + // }, + // }, + // }, + // { + // Name: "TwoInputs", + // Inputs: []*Parameter{ + // { + // Name: "name", + // Value: String, + // }, + // { + // Name: "age", + // Value: Uint8, + // }, + // }, + // }, + // { + // Name: "TwoInputsAndOutput", + // Inputs: []*Parameter{ + // { + // Name: "name", + // Value: String, + // }, + // { + // Name: "age", + // Value: Uint8, + // }, + // }, + // Outputs: []*Parameter{ + // { + // Name: "result", + // Value: Bool, + // }, + // }, + // }, + // { + // Name: "StructInput", + // Comments: []string{"StructInput takes a person"}, + // Inputs: []*Parameter{ + // { + // Name: "person", + // Value: NewPerson("John Thomas", 46), + // }, + // }, + // }, + // }, + // }) return result, nil } @@ -172,25 +188,48 @@ func generatePackageFiles(packages []*Package) error { // Iterate over each package for _, thisPackage := range packages { - - // Calculate target directory - packageDir, err := fs.RelativeToCwd("./frontend/backend/" + thisPackage.Name) + err := generatePackage(thisPackage, typescriptTemplate, javascriptTemplate) if err != nil { - return errors.Wrap(err, "Error calculating package path") + return err } + } - // Make the dir but ignore if it already exists - fs.Mkdir(packageDir) + return nil +} + +func generatePackage(thisPackage *Package, typescriptTemplate *template.Template, javascriptTemplate *template.Template) error { + + // Calculate target directory + packageDir, err := fs.RelativeToCwd("./frontend/backend/" + thisPackage.Name) + if err != nil { + return errors.Wrap(err, "Error calculating package path") + } + + // Make the dir but ignore if it already exists + fs.Mkdir(packageDir) + + type TemplateData struct { + PackageName string + Struct *ParsedStruct + } + + // Loop over structs + for _, strct := range thisPackage.Structs { + + var data = &TemplateData{ + PackageName: thisPackage.Name, + Struct: strct, + } // Execute javascript template var buffer bytes.Buffer - err = javascriptTemplate.Execute(&buffer, thisPackage) + err = javascriptTemplate.Execute(&buffer, data) if err != nil { return errors.Wrap(err, "Error generating code") } // Save javascript file - err = ioutil.WriteFile(filepath.Join(packageDir, "index.js"), buffer.Bytes(), 0755) + err = ioutil.WriteFile(filepath.Join(packageDir, strct.Name+".js"), buffer.Bytes(), 0755) if err != nil { return errors.Wrap(err, "Error writing backend package file") } @@ -199,13 +238,13 @@ func generatePackageFiles(packages []*Package) error { buffer.Reset() // Execute typescript template - err = typescriptTemplate.Execute(&buffer, thisPackage) + err = typescriptTemplate.Execute(&buffer, data) if err != nil { return errors.Wrap(err, "Error generating code") } // Save typescript file - err = ioutil.WriteFile(filepath.Join(packageDir, "index.d.ts"), buffer.Bytes(), 0755) + err = ioutil.WriteFile(filepath.Join(packageDir, strct.Name+".d.ts"), buffer.Bytes(), 0755) if err != nil { return errors.Wrap(err, "Error writing backend package file") } diff --git a/v2/pkg/commands/build/internal/backendjs/parse.go b/v2/pkg/commands/build/internal/backendjs/parse.go new file mode 100644 index 00000000..8735b303 --- /dev/null +++ b/v2/pkg/commands/build/internal/backendjs/parse.go @@ -0,0 +1,403 @@ +package backendjs + +import ( + "fmt" + "go/ast" + "strings" + + "github.com/leaanthony/slicer" + "github.com/pkg/errors" + "golang.org/x/tools/go/packages" +) + +type Parser struct { + wailsPkgVar string + appVarName string + + boundStructLiterals slicer.StringSlicer + boundMethods []string + boundStructPointerLiterals []string + boundVariables slicer.StringSlicer + variableFunctionDecls map[string]string + variableStructDecls map[string]string + internalMethods slicer.StringSlicer + structCache map[string]*ParsedStruct + structPointerFunctionDecls map[string]string + structFunctionDecls map[string]string +} + +type ParsedParameter struct { + Name string + Type string +} + +func (p *ParsedParameter) JSType() string { + return string(goTypeToJS(p.Type)) +} + +type ParsedMethod struct { + Struct string + Name string + Comments []string + Inputs []*ParsedParameter + Returns []*ParsedParameter +} + +// InputsAsTSText generates a string with the method inputs +// formatted in a way acceptable to Typescript +func (m *ParsedMethod) InputsAsTSText() string { + var inputs []string + + for _, input := range m.Inputs { + inputText := fmt.Sprintf("%s: %s", input.Name, goTypeToTS(input.Type)) + inputs = append(inputs, inputText) + } + + return strings.Join(inputs, ", ") +} + +// InputsAsJSText generates a string with the method inputs +// formatted in a way acceptable to Javascript +func (m *ParsedMethod) InputsAsJSText() string { + var inputs []string + + for _, input := range m.Inputs { + inputs = append(inputs, input.Name) + } + + return strings.Join(inputs, ", ") +} + +// OutputsAsTSText generates a string with the method inputs +// formatted in a way acceptable to Javascript +func (m *ParsedMethod) OutputsAsTSText() string { + + if len(m.Returns) == 0 { + return "void" + } + + var result []string + + for _, output := range m.Returns { + jsType := goTypeToJS(output.Type) + switch jsType { + case JsArray: + result = append(result, "Array") + case JsObject: + result = append(result, "any") + default: + result = append(result, string(jsType)) + } + } + return strings.Join(result, ", ") +} + +type ParsedStruct struct { + Name string + Methods []*ParsedMethod +} + +func NewParser() *Parser { + return &Parser{ + variableFunctionDecls: make(map[string]string), + variableStructDecls: make(map[string]string), + internalMethods: *slicer.String([]string{"WailsInit", "WailsShutdown"}), + structCache: make(map[string]*ParsedStruct), + structPointerFunctionDecls: make(map[string]string), + structFunctionDecls: make(map[string]string), + } +} + +func parseProject(projectPath string) ([]*Package, error) { + cfg := &packages.Config{ + Mode: packages.NeedName | + packages.NeedFiles | + packages.NeedSyntax | + packages.NeedTypes | + packages.NeedTypesInfo, + } + pkgs, err := packages.Load(cfg, projectPath) + if err != nil { + return nil, errors.Wrap(err, "Problem loading packages") + } + if packages.PrintErrors(pkgs) > 0 { + return nil, errors.Wrap(err, "Errors during parsing") + } + + var result []*Package + + // Iterate the packages + for _, pkg := range pkgs { + + p := NewParser() + + thisPackage, err := p.parsePackage(pkg) + if err != nil { + return nil, err + } + + for k := range p.structCache { + thisPackage.Structs = append(thisPackage.Structs, p.structCache[k]) + } + + result = append(result, thisPackage) + + } + + return result, nil +} + +func (p *Parser) parsePackage(pkg *packages.Package) (*Package, error) { + result := &Package{Name: pkg.Name} + + for _, file := range pkg.Syntax { + err := p.parseFile(file) + if err != nil { + return nil, err + } + } + + return result, nil +} + +func (p *Parser) parseFile(file *ast.File) error { + ast.Inspect(file, func(n ast.Node) bool { + switch x := n.(type) { + // Parse import declarations + case *ast.ImportSpec: + // Determine what wails has been imported as + if x.Path.Value == `"github.com/wailsapp/wails/v2"` { + p.wailsPkgVar = x.Name.Name + } + // Parse calls. We are looking for app.Bind() calls + case *ast.CallExpr: + f, ok := x.Fun.(*ast.SelectorExpr) + if ok { + n, ok := f.X.(*ast.Ident) + if ok { + //Check this is the Bind() call associated with the app variable + if n.Name == p.appVarName && f.Sel.Name == "Bind" { + if len(x.Args) == 1 { + ce, ok := x.Args[0].(*ast.CallExpr) + if ok { + n, ok := ce.Fun.(*ast.Ident) + if ok { + // We found a bind method using a function call + // EG: app.Bind( newMyStruct() ) + p.boundMethods = append(p.boundMethods, n.Name) + } + } else { + // We also want to check for Bind( &MyStruct{} ) + ue, ok := x.Args[0].(*ast.UnaryExpr) + if ok { + if ue.Op.String() == "&" { + cl, ok := ue.X.(*ast.CompositeLit) + if ok { + t, ok := cl.Type.(*ast.Ident) + if ok { + // We have found Bind( &MyStruct{} ) + p.boundStructPointerLiterals = append(p.boundStructPointerLiterals, t.Name) + } + } + } + } else { + // Let's check when the user binds a struct, + // rather than a struct pointer: Bind( MyStruct{} ) + // We do this to provide better hints to the user + cl, ok := x.Args[0].(*ast.CompositeLit) + if ok { + t, ok := cl.Type.(*ast.Ident) + if ok { + p.boundStructLiterals.Add(t.Name) + } + } else { + // Also check for when we bind a variable + // myVariable := &MyStruct{} + // app.Bind( myVariable ) + i, ok := x.Args[0].(*ast.Ident) + if ok { + p.boundVariables.Add(i.Name) + } + } + } + } + } + } + } + } + + // We scan assignments for a number of reasons: + // * Determine the variable containing the main application + // * Determine the type of variables that get used in Bind() + // * Determine the type of variables that get created with var := &MyStruct{} + case *ast.AssignStmt: + for _, rhs := range x.Rhs { + ce, ok := rhs.(*ast.CallExpr) + if ok { + se, ok := ce.Fun.(*ast.SelectorExpr) + if ok { + i, ok := se.X.(*ast.Ident) + if ok { + // Have we found the wails package name? + if i.Name == p.wailsPkgVar { + // Check we are calling a function to create the app + if se.Sel.Name == "CreateApp" || se.Sel.Name == "CreateAppWithOptions" { + if len(x.Lhs) == 1 { + i, ok := x.Lhs[0].(*ast.Ident) + if ok { + // Found the app variable name + p.appVarName = i.Name + } + } + } + } + } + } else { + // Check for function assignment + // a := newMyStruct() + fe, ok := ce.Fun.(*ast.Ident) + if ok { + if len(x.Lhs) == 1 { + i, ok := x.Lhs[0].(*ast.Ident) + if ok { + // Store the variable -> Function mapping + // so we can later resolve the type + p.variableFunctionDecls[i.Name] = fe.Name + } + } + } + } + } else { + // Check for literal assignment of struct + // EG: myvar := MyStruct{} + ue, ok := rhs.(*ast.UnaryExpr) + if ok { + cl, ok := ue.X.(*ast.CompositeLit) + if ok { + t, ok := cl.Type.(*ast.Ident) + if ok { + if len(x.Lhs) == 1 { + i, ok := x.Lhs[0].(*ast.Ident) + if ok { + p.variableStructDecls[i.Name] = t.Name + } + } + } + } + } + } + } + // We scan for functions to build up a list of function names + // for a number of reasons: + // * Determine which functions are struct methods that are bound + // * Determine + case *ast.FuncDecl: + if x.Recv != nil { + // This is a struct method + for _, field := range x.Recv.List { + se, ok := field.Type.(*ast.StarExpr) + if ok { + // This is a struct pointer method + i, ok := se.X.(*ast.Ident) + if ok { + // We want to ignore Internal functions + if p.internalMethods.Contains(x.Name.Name) { + continue + } + // If we haven't already found this struct, + // Create a placeholder in the cache + parsedStruct := p.structCache[i.Name] + if parsedStruct == nil { + p.structCache[i.Name] = &ParsedStruct{ + Name: i.Name, + } + parsedStruct = p.structCache[i.Name] + } + + // If this method is Public + if string(x.Name.Name[0]) == strings.ToUpper((string(x.Name.Name[0]))) { + structMethod := &ParsedMethod{ + Struct: i.Name, + Name: x.Name.Name, + } + // Check if the method has comments. + // If so, save it with the parsed method + if x.Doc != nil { + for _, comment := range x.Doc.List { + stringComment := strings.TrimPrefix(comment.Text, "//") + structMethod.Comments = append(structMethod.Comments, strings.TrimSpace(stringComment)) + } + } + + // Save the input parameters + for _, inputField := range x.Type.Params.List { + t, ok := inputField.Type.(*ast.Ident) + if !ok { + continue + } + for _, name := range inputField.Names { + structMethod.Inputs = append(structMethod.Inputs, &ParsedParameter{Name: name.Name, Type: t.Name}) + } + } + + // Save the output parameters + if x.Type.Results != nil { + + for _, outputField := range x.Type.Results.List { + t, ok := outputField.Type.(*ast.Ident) + if !ok { + continue + } + if len(outputField.Names) == 0 { + structMethod.Returns = append(structMethod.Returns, &ParsedParameter{Type: t.Name}) + } else { + for _, name := range outputField.Names { + structMethod.Returns = append(structMethod.Returns, &ParsedParameter{Name: name.Name, Type: t.Name}) + } + } + } + } + + // Append this method to the parsed struct + parsedStruct.Methods = append(parsedStruct.Methods, structMethod) + + } + } + } + } + } else { + // This is a function declaration + // We care about its name and return type + // This will allow us to resolve types later + functionName := x.Name.Name + + // Look for one that returns a single value + if x.Type != nil && x.Type.Results != nil && x.Type.Results.List != nil { + if len(x.Type.Results.List) == 1 { + // Check for *struct + t, ok := x.Type.Results.List[0].Type.(*ast.StarExpr) + if ok { + s, ok := t.X.(*ast.Ident) + if ok { + // println("*** Function", functionName, "found which returns: *"+s.Name) + p.structPointerFunctionDecls[functionName] = s.Name + } + } else { + // Check for functions that return a struct + // This is to help us provide hints if the user binds a struct + t, ok := x.Type.Results.List[0].Type.(*ast.Ident) + if ok { + // println("*** Function", functionName, "found which returns: "+t.Name) + p.structFunctionDecls[functionName] = t.Name + } + } + } + } + } + } + return true + }) + // spew.Dump(file) + + return nil +} diff --git a/v2/pkg/commands/build/internal/backendjs/structs.go b/v2/pkg/commands/build/internal/backendjs/structs.go new file mode 100644 index 00000000..82168b20 --- /dev/null +++ b/v2/pkg/commands/build/internal/backendjs/structs.go @@ -0,0 +1,13 @@ +package backendjs + +import "reflect" + +type Struct struct { + Name string + Fields []*Field +} + +type Field struct { + Name string + Type reflect.Value +} diff --git a/v2/pkg/commands/build/internal/backendjs/values.go b/v2/pkg/commands/build/internal/backendjs/values.go new file mode 100644 index 00000000..c5096bf9 --- /dev/null +++ b/v2/pkg/commands/build/internal/backendjs/values.go @@ -0,0 +1,55 @@ +package backendjs + +import "reflect" + +var BoolValue bool = true +var IntValue int = 0 +var Int8Value int8 = 0 +var Int16Value int16 = 0 +var Int32Value int32 = 0 +var Int64Value int64 = 0 +var UintValue uint = 0 +var Uint8Value uint8 = 0 +var Uint16Value uint16 = 0 +var Uint32Value uint32 = 0 +var Uint64Value uint64 = 0 +var UintptrValue uintptr = 0 +var Float32Value float32 = 0 +var Float64Value float64 = 0 +var Complex64Value complex64 = 0 +var Complex128Value complex128 = 0 +var StringValue string = "" + +type Person struct { + Name string + Age uint8 +} + +type GuestList struct { + People []*Person +} + +func NewPerson(name string, age uint8) reflect.Value { + return reflect.New(reflect.TypeOf(&Person{ + Name: name, + Age: age, + })) +} + +var Bool = reflect.New(reflect.TypeOf(BoolValue)) +var Int = reflect.New(reflect.TypeOf(IntValue)) +var Int8 = reflect.New(reflect.TypeOf(Int8Value)) +var Int16 = reflect.New(reflect.TypeOf(Int16Value)) +var Int32 = reflect.New(reflect.TypeOf(Int32Value)) +var Int64 = reflect.New(reflect.TypeOf(Int64Value)) +var Uint = reflect.New(reflect.TypeOf(UintValue)) +var Uint8 = reflect.New(reflect.TypeOf(Uint8Value)) +var Uint16 = reflect.New(reflect.TypeOf(Uint16Value)) +var Uint32 = reflect.New(reflect.TypeOf(Uint32Value)) +var Uint64 = reflect.New(reflect.TypeOf(Uint64Value)) +var Uintptr = reflect.New(reflect.TypeOf(UintptrValue)) +var Float32 = reflect.New(reflect.TypeOf(Float32Value)) +var Float64 = reflect.New(reflect.TypeOf(Float64Value)) +var Complex64 = reflect.New(reflect.TypeOf(Complex64Value)) +var Complex128 = reflect.New(reflect.TypeOf(Complex128Value)) +var String = reflect.New(reflect.TypeOf(StringValue))