mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-19 10:29:29 +08:00
Support bindings, model & enum generation
This commit is contained in:
parent
43c4966873
commit
4b04c10f14
@ -1,15 +1,10 @@
|
|||||||
package commands
|
package commands
|
||||||
|
|
||||||
import "github.com/wailsapp/wails/v3/internal/parser"
|
import (
|
||||||
|
"github.com/wailsapp/wails/v3/internal/flags"
|
||||||
|
"github.com/wailsapp/wails/v3/internal/parser"
|
||||||
|
)
|
||||||
|
|
||||||
type GenerateBindingsOptions struct {
|
func GenerateBindings(options *flags.GenerateBindingsOptions) error {
|
||||||
Silent bool `name:"silent" description:"Silent mode"`
|
return parser.GenerateBindingsAndModels(options)
|
||||||
ModelsFilename string `name:"m" description:"The filename for the models file" default:"models.ts"`
|
|
||||||
BindingsFilename string `name:"b" description:"The filename for the bindings file" default:"bindings_<package>.js"`
|
|
||||||
ProjectDirectory string `name:"p" description:"The project directory" default:"."`
|
|
||||||
OutputDirectory string `name:"d" description:"The output directory" default:"."`
|
|
||||||
}
|
|
||||||
|
|
||||||
func GenerateBindings(options *GenerateBindingsOptions) error {
|
|
||||||
return parser.GenerateBindingsAndModels(options.ProjectDirectory, options.OutputDirectory)
|
|
||||||
}
|
}
|
||||||
|
11
v3/internal/flags/bindings.go
Normal file
11
v3/internal/flags/bindings.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package flags
|
||||||
|
|
||||||
|
type GenerateBindingsOptions struct {
|
||||||
|
Silent bool `name:"silent" description:"Silent mode"`
|
||||||
|
ModelsFilename string `name:"m" description:"The filename for the models file" default:"models.ts"`
|
||||||
|
TSPrefix string `description:"The prefix for the typescript names" default:""`
|
||||||
|
TSSuffix string `description:"The postfix for the typescript names" default:""`
|
||||||
|
UseInterfaces bool `name:"i" description:"Use interfaces instead of classes"`
|
||||||
|
ProjectDirectory string `name:"p" description:"The project directory" default:"."`
|
||||||
|
OutputDirectory string `name:"d" description:"The output directory" default:"frontend/bindings"`
|
||||||
|
}
|
@ -58,6 +58,9 @@ This package contains the static analyser used for parsing Wails projects so tha
|
|||||||
- [ ] Maps
|
- [ ] Maps
|
||||||
- [x] Structs
|
- [x] Structs
|
||||||
- [ ] Generation of bindings
|
- [ ] Generation of bindings
|
||||||
|
- [ ] Classes
|
||||||
|
- [ ] Interfaces
|
||||||
|
- [ ] Enums
|
||||||
|
|
||||||
## Limitations
|
## Limitations
|
||||||
|
|
||||||
|
@ -19,12 +19,18 @@ const bindingTemplate = `
|
|||||||
/**
|
/**
|
||||||
* {{structName}}.{{methodName}}
|
* {{structName}}.{{methodName}}
|
||||||
*Comments
|
*Comments
|
||||||
* @param name {string}
|
* @param names {string}
|
||||||
* @returns {Promise<string>}
|
* @returns {Promise<string>}
|
||||||
**/
|
**/
|
||||||
{{methodName}}: function({{inputs}}) { return wails.CallByID({{ID}}, ...Array.prototype.slice.call(arguments, 0)); },
|
{{methodName}}: function({{inputs}}) { return wails.CallByID({{ID}}, ...Array.prototype.slice.call(arguments, 0)); },
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const enumTemplate = `
|
||||||
|
export enum {{.EnumName}} {
|
||||||
|
{{.EnumValues}}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
var reservedWords = []string{
|
var reservedWords = []string{
|
||||||
"abstract",
|
"abstract",
|
||||||
"arguments",
|
"arguments",
|
||||||
@ -119,18 +125,19 @@ func GenerateBinding(structName string, method *BoundMethod) (string, []string,
|
|||||||
pkgName := getPackageName(input)
|
pkgName := getPackageName(input)
|
||||||
if pkgName != "" {
|
if pkgName != "" {
|
||||||
models = append(models, pkgName)
|
models = append(models, pkgName)
|
||||||
if input.Type.IsStruct {
|
}
|
||||||
|
if input.Type.IsStruct || input.Type.IsEnum {
|
||||||
nsStruct := input.NamespacedStructType()
|
nsStruct := input.NamespacedStructType()
|
||||||
namespacedStructs = append(namespacedStructs, nsStruct)
|
namespacedStructs = append(namespacedStructs, nsStruct)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
params += " * @param " + inputName + " {" + input.JSType() + "}\n"
|
params += " * @param " + inputName + " {" + input.JSType() + "}\n"
|
||||||
}
|
}
|
||||||
params = strings.TrimSuffix(params, "\n")
|
params = strings.TrimSuffix(params, "\n")
|
||||||
if len(params) == 0 {
|
if len(params) == 0 {
|
||||||
params = " *"
|
params = " *"
|
||||||
}
|
}
|
||||||
result = strings.ReplaceAll(result, " * @param name {string}", params)
|
result = strings.ReplaceAll(result, "* @param names {string}", params)
|
||||||
var inputs string
|
var inputs string
|
||||||
for _, input := range method.Inputs {
|
for _, input := range method.Inputs {
|
||||||
pkgName := getPackageName(input)
|
pkgName := getPackageName(input)
|
||||||
@ -232,19 +239,8 @@ func GenerateBindings(bindings map[string]map[string][]*BoundMethod) map[string]
|
|||||||
packageBindings := bindings[packageName]
|
packageBindings := bindings[packageName]
|
||||||
structNames := lo.Keys(packageBindings)
|
structNames := lo.Keys(packageBindings)
|
||||||
sort.Strings(structNames)
|
sort.Strings(structNames)
|
||||||
result[normalisedPackageNames[packageName]] += `
|
|
||||||
window.go = window.go || {};
|
|
||||||
`
|
|
||||||
// Iterate over the sorted struct keys
|
|
||||||
result[normalisedPackageNames[packageName]] += "window.go." + normalisedPackageNames[packageName] + " = {\n"
|
|
||||||
for _, structName := range structNames {
|
for _, structName := range structNames {
|
||||||
/**
|
result[normalisedPackageNames[packageName]] += "export const " + structName + " = {\n"
|
||||||
* The GreetService provides methods to greet a person.
|
|
||||||
*/
|
|
||||||
//result[normalisedPackageNames[packageName]] += " /**\n"
|
|
||||||
//result[normalisedPackageNames[packageName]] += " {{structcomments}}\n"
|
|
||||||
//result[normalisedPackageNames[packageName]] += " */\n"
|
|
||||||
result[normalisedPackageNames[packageName]] += " " + structName + ": {\n"
|
|
||||||
methods := packageBindings[structName]
|
methods := packageBindings[structName]
|
||||||
sort.Slice(methods, func(i, j int) bool {
|
sort.Slice(methods, func(i, j int) bool {
|
||||||
return methods[i].Name < methods[j].Name
|
return methods[i].Name < methods[j].Name
|
||||||
@ -255,9 +251,8 @@ window.go = window.go || {};
|
|||||||
allModels = append(allModels, models...)
|
allModels = append(allModels, models...)
|
||||||
result[normalisedPackageNames[packageName]] += thisBinding
|
result[normalisedPackageNames[packageName]] += thisBinding
|
||||||
}
|
}
|
||||||
result[normalisedPackageNames[packageName]] += " },\n"
|
result[normalisedPackageNames[packageName]] += "};\n\n"
|
||||||
}
|
}
|
||||||
result[normalisedPackageNames[packageName]] += "};\n"
|
|
||||||
|
|
||||||
if len(allNamespacedStructs) > 0 {
|
if len(allNamespacedStructs) > 0 {
|
||||||
typedefs := "/**\n"
|
typedefs := "/**\n"
|
||||||
|
@ -27,6 +27,12 @@ func TestGenerateBindings(t *testing.T) {
|
|||||||
dir string
|
dir string
|
||||||
want map[string]string
|
want map[string]string
|
||||||
}{
|
}{
|
||||||
|
{
|
||||||
|
"testdata/enum",
|
||||||
|
map[string]string{
|
||||||
|
"main": getFile("testdata/enum/bindings_main.js"),
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"testdata/function_single",
|
"testdata/function_single",
|
||||||
map[string]string{
|
map[string]string{
|
||||||
|
@ -3,6 +3,7 @@ package parser
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"embed"
|
"embed"
|
||||||
|
"github.com/wailsapp/wails/v3/internal/flags"
|
||||||
"io"
|
"io"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
@ -15,16 +16,27 @@ var templates embed.FS
|
|||||||
type ModelDefinitions struct {
|
type ModelDefinitions struct {
|
||||||
Package string
|
Package string
|
||||||
Models map[string]*StructDef
|
Models map[string]*StructDef
|
||||||
|
Enums map[string]*TypeDef
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateModel(wr io.Writer, def *ModelDefinitions) error {
|
func GenerateModel(wr io.Writer, def *ModelDefinitions, options *flags.GenerateBindingsOptions) error {
|
||||||
tmpl, err := template.New("model.ts.tmpl").ParseFS(templates, "templates/model.ts.tmpl")
|
templateName := "model.ts.tmpl"
|
||||||
|
if options.UseInterfaces {
|
||||||
|
templateName = "interfaces.ts.tmpl"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix up TS names
|
||||||
|
for _, model := range def.Models {
|
||||||
|
model.Name = options.TSPrefix + model.Name + options.TSSuffix
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpl, err := template.New(templateName).ParseFS(templates, "templates/"+templateName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
println("Unable to create class template: " + err.Error())
|
println("Unable to create class template: " + err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = tmpl.ExecuteTemplate(wr, "model.ts.tmpl", def)
|
err = tmpl.ExecuteTemplate(wr, templateName, def)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
println("Problem executing template: " + err.Error())
|
println("Problem executing template: " + err.Error())
|
||||||
return err
|
return err
|
||||||
@ -42,7 +54,7 @@ func pkgAlias(fullPkg string) string {
|
|||||||
return pkgParts[len(pkgParts)-1]
|
return pkgParts[len(pkgParts)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateModels(models map[packagePath]map[structName]*StructDef) (string, error) {
|
func GenerateModels(models map[packagePath]map[structName]*StructDef, enums map[packagePath]map[string]*TypeDef, options *flags.GenerateBindingsOptions) (string, error) {
|
||||||
if models == nil {
|
if models == nil {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
@ -53,7 +65,7 @@ func GenerateModels(models map[packagePath]map[structName]*StructDef) (string, e
|
|||||||
// sort pkgs by alias (e.g. services) instead of full pkg name (e.g. github.com/wailsapp/wails/somedir/services)
|
// sort pkgs by alias (e.g. services) instead of full pkg name (e.g. github.com/wailsapp/wails/somedir/services)
|
||||||
// and then sort resulting list by the alias
|
// and then sort resulting list by the alias
|
||||||
var keys []string
|
var keys []string
|
||||||
for pkg, _ := range models {
|
for pkg := range models {
|
||||||
keys = append(keys, pkg)
|
keys = append(keys, pkg)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,120 +77,11 @@ func GenerateModels(models map[packagePath]map[structName]*StructDef) (string, e
|
|||||||
err := GenerateModel(&buffer, &ModelDefinitions{
|
err := GenerateModel(&buffer, &ModelDefinitions{
|
||||||
Package: pkgAlias(pkg),
|
Package: pkgAlias(pkg),
|
||||||
Models: models[pkg],
|
Models: models[pkg],
|
||||||
})
|
Enums: enums[pkg],
|
||||||
|
}, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return buffer.String(), nil
|
return buffer.String(), 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 (
|
|
||||||
// "bytes"
|
|
||||||
// "fmt"
|
|
||||||
// "go/ast"
|
|
||||||
// "go/types"
|
|
||||||
// "sort"
|
|
||||||
// "strings"
|
|
||||||
// "unicode"
|
|
||||||
//)
|
|
||||||
//
|
|
||||||
//func GenerateModels(context *Context) ([]byte, error) {
|
|
||||||
// var buf bytes.Buffer
|
|
||||||
// var pkgs []Package
|
|
||||||
// specs := context.GetBoundStructs()
|
|
||||||
// for pkg, pkgSpecs := range specs {
|
|
||||||
// pkgs = append(pkgs, Package{Name: pkg, Specs: pkgSpecs})
|
|
||||||
// }
|
|
||||||
// knownStructs := newAllModels(specs)
|
|
||||||
// sort.Slice(pkgs, func(i, j int) bool { return pkgs[i].Name < pkgs[j].Name })
|
|
||||||
// for _, pkg := range pkgs {
|
|
||||||
// if _, err := fmt.Fprintf(&buf, "namespace %s {\n", pkg.Name); err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
// sort.Slice(pkg.Specs, func(i, j int) bool { return pkg.Specs[i].Name.Name < pkg.Specs[j].Name.Name })
|
|
||||||
// for _, spec := range pkg.Specs {
|
|
||||||
// if structType, ok := spec.Type.(*ast.StructType); ok {
|
|
||||||
// if _, err := fmt.Fprintf(&buf, " class %s {\n", spec.Name.Name); err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// for _, field := range structType.Fields.List {
|
|
||||||
//
|
|
||||||
// // Ignore field names that have a lower case first letter
|
|
||||||
// if !unicode.IsUpper(rune(field.Names[0].Name[0])) {
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // Get the Go type of the field
|
|
||||||
// goType := types.ExprString(field.Type)
|
|
||||||
// // Check if the type is an array
|
|
||||||
// if arrayType, ok := field.Type.(*ast.ArrayType); ok {
|
|
||||||
// // Get the element type of the array
|
|
||||||
// elementType := types.ExprString(arrayType.Elt)
|
|
||||||
// // Look up the corresponding TypeScript type
|
|
||||||
// tsType, ok := goToTS[elementType]
|
|
||||||
// if !ok {
|
|
||||||
// // strip off the * prefix if it is there
|
|
||||||
// if strings.HasPrefix(elementType, "*") {
|
|
||||||
// elementType = elementType[1:]
|
|
||||||
// }
|
|
||||||
// if knownStructs.exists(elementType) {
|
|
||||||
// tsType = elementType
|
|
||||||
// } else {
|
|
||||||
// tsType = "any"
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// // Output the field as an array of the corresponding TypeScript type
|
|
||||||
// if _, err := fmt.Fprintf(&buf, " %s: %s[];\n", field.Names[0].Name, tsType); err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// // strip off the * prefix if it is there
|
|
||||||
// if strings.HasPrefix(goType, "*") {
|
|
||||||
// goType = goType[1:]
|
|
||||||
// }
|
|
||||||
// // Look up the corresponding TypeScript type
|
|
||||||
// tsType, ok := goToTS[goType]
|
|
||||||
// if !ok {
|
|
||||||
// if knownStructs.exists(goType) {
|
|
||||||
// tsType = goType
|
|
||||||
// } else {
|
|
||||||
// tsType = "any"
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// // Output the field as the corresponding TypeScript type
|
|
||||||
// if _, err := fmt.Fprintf(&buf, " %s: %s;\n", field.Names[0].Name, tsType); err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if _, err := fmt.Fprintf(&buf, " }\n"); err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if _, err := fmt.Fprintf(&buf, "}\n\n"); err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return buf.Bytes(), nil
|
|
||||||
//}
|
|
||||||
|
@ -2,6 +2,7 @@ package parser
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
|
"github.com/wailsapp/wails/v3/internal/flags"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
@ -15,40 +16,39 @@ func TestGenerateModels(t *testing.T) {
|
|||||||
want string
|
want string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
"testdata/function_single",
|
dir: "testdata/function_single",
|
||||||
"",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"testdata/function_from_imported_package",
|
dir: "testdata/function_from_imported_package",
|
||||||
getFile("testdata/function_from_imported_package/models.ts"),
|
want: getFile("testdata/function_from_imported_package/models.ts"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"testdata/variable_single",
|
dir: "testdata/variable_single",
|
||||||
"",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"testdata/variable_single_from_function",
|
dir: "testdata/variable_single_from_function",
|
||||||
"",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"testdata/variable_single_from_other_function",
|
dir: "testdata/variable_single_from_other_function",
|
||||||
getFile("testdata/variable_single_from_other_function/models.ts"),
|
want: getFile("testdata/variable_single_from_other_function/models.ts"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"testdata/struct_literal_single",
|
dir: "testdata/struct_literal_single",
|
||||||
getFile("testdata/struct_literal_single/models.ts"),
|
want: getFile("testdata/struct_literal_single/models.ts"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"testdata/struct_literal_multiple",
|
dir: "testdata/struct_literal_multiple",
|
||||||
"",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"testdata/struct_literal_multiple_other",
|
dir: "testdata/struct_literal_multiple_other",
|
||||||
getFile("testdata/struct_literal_multiple_other/models.ts"),
|
want: getFile("testdata/struct_literal_multiple_other/models.ts"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"testdata/struct_literal_multiple_files",
|
dir: "testdata/struct_literal_multiple_files",
|
||||||
"",
|
},
|
||||||
|
{
|
||||||
|
dir: "testdata/enum",
|
||||||
|
want: getFile("testdata/enum/models.ts"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
@ -60,7 +60,7 @@ func TestGenerateModels(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate Models
|
// Generate Models
|
||||||
got, err := GenerateModels(project.Models)
|
got, err := GenerateModels(project.Models, project.Types, &flags.GenerateBindingsOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("GenerateModels() error = %v", err)
|
t.Fatalf("GenerateModels() error = %v", err)
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package parser
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/wailsapp/wails/v3/internal/flags"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/build"
|
"go/build"
|
||||||
"go/parser"
|
"go/parser"
|
||||||
@ -12,6 +13,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/samber/lo"
|
"github.com/samber/lo"
|
||||||
"github.com/wailsapp/wails/v3/internal/hash"
|
"github.com/wailsapp/wails/v3/internal/hash"
|
||||||
@ -26,16 +28,39 @@ type StructDef struct {
|
|||||||
Fields []*Field
|
Fields []*Field
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *StructDef) DefaultValueList() string {
|
||||||
|
var allFields []string
|
||||||
|
for _, field := range s.Fields {
|
||||||
|
thisFieldWithDefaultValue := fmt.Sprintf("%s = %s", field.JSName(), field.DefaultValue())
|
||||||
|
allFields = append(allFields, thisFieldWithDefaultValue)
|
||||||
|
}
|
||||||
|
return strings.Join(allFields, ", ")
|
||||||
|
}
|
||||||
|
|
||||||
type ParameterType struct {
|
type ParameterType struct {
|
||||||
Name string
|
Name string
|
||||||
IsStruct bool
|
IsStruct bool
|
||||||
IsSlice bool
|
IsSlice bool
|
||||||
IsPointer bool
|
IsPointer bool
|
||||||
|
IsEnum bool
|
||||||
MapKey *ParameterType
|
MapKey *ParameterType
|
||||||
MapValue *ParameterType
|
MapValue *ParameterType
|
||||||
Package string
|
Package string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type EnumDef struct {
|
||||||
|
Name string
|
||||||
|
Filename string
|
||||||
|
DocComments []string
|
||||||
|
Values []*EnumValue
|
||||||
|
}
|
||||||
|
|
||||||
|
type EnumValue struct {
|
||||||
|
Name string
|
||||||
|
Value string
|
||||||
|
DocComments []string
|
||||||
|
}
|
||||||
|
|
||||||
type Parameter struct {
|
type Parameter struct {
|
||||||
Name string
|
Name string
|
||||||
Type *ParameterType
|
Type *ParameterType
|
||||||
@ -73,7 +98,7 @@ func (p *Parameter) JSType() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if the type is a struct, we need to add the package name
|
// if the type is a struct, we need to add the package name
|
||||||
if p.Type.IsStruct {
|
if p.Type.IsStruct || p.Type.IsEnum {
|
||||||
typeName = p.NamespacedStructType()
|
typeName = p.NamespacedStructType()
|
||||||
typeName = strings.ReplaceAll(typeName, ".", "")
|
typeName = strings.ReplaceAll(typeName, ".", "")
|
||||||
}
|
}
|
||||||
@ -117,7 +142,7 @@ func (f *Field) JSName() string {
|
|||||||
// via assignment for simple types or constructors for structs
|
// via assignment for simple types or constructors for structs
|
||||||
func (f *Field) TSBuild(pkg string) string {
|
func (f *Field) TSBuild(pkg string) string {
|
||||||
if !f.Type.IsStruct {
|
if !f.Type.IsStruct {
|
||||||
return fmt.Sprintf("source['%s']", f.JSName())
|
return fmt.Sprintf("safeSource['%s']", f.JSName())
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.Type.Package == "" || f.Type.Package == pkg {
|
if f.Type.Package == "" || f.Type.Package == pkg {
|
||||||
@ -141,7 +166,8 @@ func (f *Field) JSDef(pkg string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var result string
|
var result string
|
||||||
if f.Type.Package == "" || f.Type.Package == pkg {
|
isExternalStruct := f.Type.Package != "" && f.Type.Package != pkg && f.Type.IsStruct
|
||||||
|
if f.Type.Package == "" || f.Type.Package == pkg || !isExternalStruct {
|
||||||
result += fmt.Sprintf("%s: %s;", f.JSName(), jsType)
|
result += fmt.Sprintf("%s: %s;", f.JSName(), jsType)
|
||||||
} else {
|
} else {
|
||||||
parts := strings.Split(f.Type.Package, "/")
|
parts := strings.Split(f.Type.Package, "/")
|
||||||
@ -155,12 +181,45 @@ func (f *Field) JSDef(pkg string) string {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *Field) DefaultValue() string {
|
||||||
|
// Return the default value of the typescript version of the type as a string
|
||||||
|
switch f.Type.Name {
|
||||||
|
case "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uintptr", "float32", "float64", "uint64":
|
||||||
|
return "0"
|
||||||
|
case "string":
|
||||||
|
return `""`
|
||||||
|
case "bool":
|
||||||
|
return "false"
|
||||||
|
default:
|
||||||
|
return "null"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConstDef struct {
|
||||||
|
Name string
|
||||||
|
DocComment string
|
||||||
|
Value string
|
||||||
|
}
|
||||||
|
|
||||||
|
type TypeDef struct {
|
||||||
|
Name string
|
||||||
|
DocComments []string
|
||||||
|
Type string
|
||||||
|
Consts []*ConstDef
|
||||||
|
ShouldGenerate bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *TypeDef) GeneratedName() string {
|
||||||
|
return t.Name + "Enum"
|
||||||
|
}
|
||||||
|
|
||||||
type ParsedPackage struct {
|
type ParsedPackage struct {
|
||||||
Pkg *ast.Package
|
Pkg *ast.Package
|
||||||
Name string
|
Name string
|
||||||
Path string
|
Path string
|
||||||
Dir string
|
Dir string
|
||||||
StructCache map[structName]*StructDef
|
StructCache map[structName]*StructDef
|
||||||
|
TypeCache map[string]*TypeDef
|
||||||
}
|
}
|
||||||
|
|
||||||
type Project struct {
|
type Project struct {
|
||||||
@ -168,7 +227,19 @@ type Project struct {
|
|||||||
Path string
|
Path string
|
||||||
BoundMethods map[packagePath]map[structName][]*BoundMethod
|
BoundMethods map[packagePath]map[structName][]*BoundMethod
|
||||||
Models map[packagePath]map[structName]*StructDef
|
Models map[packagePath]map[structName]*StructDef
|
||||||
|
Types map[packagePath]map[structName]*TypeDef
|
||||||
anonymousStructIDCounter int
|
anonymousStructIDCounter int
|
||||||
|
Stats Stats
|
||||||
|
}
|
||||||
|
|
||||||
|
type Stats struct {
|
||||||
|
NumPackages int
|
||||||
|
NumStructs int
|
||||||
|
NumMethods int
|
||||||
|
NumEnums int
|
||||||
|
NumModels int
|
||||||
|
StartTime time.Time
|
||||||
|
EndTime time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseProject(projectPath string) (*Project, error) {
|
func ParseProject(projectPath string) (*Project, error) {
|
||||||
@ -176,6 +247,7 @@ func ParseProject(projectPath string) (*Project, error) {
|
|||||||
BoundMethods: make(map[packagePath]map[structName][]*BoundMethod),
|
BoundMethods: make(map[packagePath]map[structName][]*BoundMethod),
|
||||||
packageCache: make(map[string]*ParsedPackage),
|
packageCache: make(map[string]*ParsedPackage),
|
||||||
}
|
}
|
||||||
|
result.Stats.StartTime = time.Now()
|
||||||
pkgs, err := result.parseDirectory(projectPath)
|
pkgs, err := result.parseDirectory(projectPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -195,8 +267,8 @@ func ParseProject(projectPath string) (*Project, error) {
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GenerateBindingsAndModels(projectDir string, outputDir string) error {
|
func GenerateBindingsAndModels(options *flags.GenerateBindingsOptions) error {
|
||||||
p, err := ParseProject(projectDir)
|
p, err := ParseProject(options.ProjectDirectory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -204,37 +276,51 @@ func GenerateBindingsAndModels(projectDir string, outputDir string) error {
|
|||||||
if p.BoundMethods == nil {
|
if p.BoundMethods == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
err = os.MkdirAll(outputDir, 0755)
|
err = os.MkdirAll(options.OutputDirectory, 0755)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
p.Stats.NumMethods = len(p.BoundMethods)
|
||||||
generatedMethods := GenerateBindings(p.BoundMethods)
|
generatedMethods := GenerateBindings(p.BoundMethods)
|
||||||
for pkg, text := range generatedMethods {
|
for pkg, text := range generatedMethods {
|
||||||
// Write the file
|
// Write the file
|
||||||
err = os.WriteFile(filepath.Join(outputDir, "bindings_"+pkg+".js"), []byte(text), 0644)
|
err = os.WriteFile(filepath.Join(options.OutputDirectory, pkg+".js"), []byte(text), 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p.Stats.NumModels = len(p.Models)
|
||||||
|
p.Stats.NumEnums = len(p.Types)
|
||||||
|
|
||||||
// Generate Models
|
// Generate Models
|
||||||
if len(p.Models) > 0 {
|
if len(p.Models) > 0 {
|
||||||
generatedModels, err := GenerateModels(p.Models)
|
generatedModels, err := GenerateModels(p.Models, p.Types, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = os.WriteFile(filepath.Join(outputDir, "models.ts"), []byte(generatedModels), 0644)
|
err = os.WriteFile(filepath.Join(options.OutputDirectory, options.ModelsFilename), []byte(generatedModels), 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
absPath, err := filepath.Abs(projectDir)
|
p.Stats.EndTime = time.Now()
|
||||||
|
|
||||||
|
absPath, err := filepath.Abs(options.ProjectDirectory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
println("Generated bindings and models for project: " + absPath)
|
|
||||||
absPath, err = filepath.Abs(outputDir)
|
fmt.Printf("Processed: %s, %s, %s, %s, %s in %s.\n",
|
||||||
|
pluralise(p.Stats.NumPackages, "Package"),
|
||||||
|
pluralise(p.Stats.NumStructs, "Struct"),
|
||||||
|
pluralise(p.Stats.NumMethods, "Method"),
|
||||||
|
pluralise(p.Stats.NumEnums, "Enum"),
|
||||||
|
pluralise(p.Stats.NumModels, "Model"),
|
||||||
|
p.Stats.EndTime.Sub(p.Stats.StartTime).String())
|
||||||
|
|
||||||
|
absPath, err = filepath.Abs(options.OutputDirectory)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -243,6 +329,13 @@ func GenerateBindingsAndModels(projectDir string, outputDir string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func pluralise(number int, word string) string {
|
||||||
|
if number == 1 {
|
||||||
|
return fmt.Sprintf("%d %s", number, word)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%d %ss", number, word)
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Project) parseDirectory(dir string) (map[string]*ParsedPackage, error) {
|
func (p *Project) parseDirectory(dir string) (map[string]*ParsedPackage, error) {
|
||||||
if p.packageCache[dir] != nil {
|
if p.packageCache[dir] != nil {
|
||||||
return map[string]*ParsedPackage{dir: p.packageCache[dir]}, nil
|
return map[string]*ParsedPackage{dir: p.packageCache[dir]}, nil
|
||||||
@ -261,6 +354,7 @@ func (p *Project) parseDirectory(dir string) (map[string]*ParsedPackage, error)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var result = make(map[string]*ParsedPackage)
|
var result = make(map[string]*ParsedPackage)
|
||||||
|
p.Stats.NumPackages = len(pkgs)
|
||||||
for packageName, pkg := range pkgs {
|
for packageName, pkg := range pkgs {
|
||||||
parsedPackage := &ParsedPackage{
|
parsedPackage := &ParsedPackage{
|
||||||
Pkg: pkg,
|
Pkg: pkg,
|
||||||
@ -268,6 +362,7 @@ func (p *Project) parseDirectory(dir string) (map[string]*ParsedPackage, error)
|
|||||||
Path: packageName,
|
Path: packageName,
|
||||||
Dir: getDirectoryForPackage(pkg),
|
Dir: getDirectoryForPackage(pkg),
|
||||||
StructCache: make(map[structName]*StructDef),
|
StructCache: make(map[structName]*StructDef),
|
||||||
|
TypeCache: make(map[string]*TypeDef),
|
||||||
}
|
}
|
||||||
p.packageCache[packageName] = parsedPackage
|
p.packageCache[packageName] = parsedPackage
|
||||||
result[packageName] = parsedPackage
|
result[packageName] = parsedPackage
|
||||||
@ -285,6 +380,28 @@ func (p *Project) findApplicationNewCalls(pkgs map[string]*ParsedPackage) (err e
|
|||||||
for _, file := range thisPackage.Files {
|
for _, file := range thisPackage.Files {
|
||||||
// Use an ast.Inspector to find the calls to application.New
|
// Use an ast.Inspector to find the calls to application.New
|
||||||
ast.Inspect(file, func(n ast.Node) bool {
|
ast.Inspect(file, func(n ast.Node) bool {
|
||||||
|
// Check for const declaration
|
||||||
|
genDecl, ok := n.(*ast.GenDecl)
|
||||||
|
if ok {
|
||||||
|
switch genDecl.Tok {
|
||||||
|
case token.TYPE:
|
||||||
|
var comments []string
|
||||||
|
if genDecl.Doc != nil {
|
||||||
|
comments = CommentGroupToText(genDecl.Doc)
|
||||||
|
}
|
||||||
|
for _, spec := range genDecl.Specs {
|
||||||
|
if typeSpec, ok := spec.(*ast.TypeSpec); ok {
|
||||||
|
p.parseTypeDeclaration(typeSpec, pkg, comments)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case token.CONST:
|
||||||
|
p.parseConstDeclaration(genDecl, pkg)
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the node is a call expression
|
// Check if the node is a call expression
|
||||||
callExpr, ok := n.(*ast.CallExpr)
|
callExpr, ok := n.(*ast.CallExpr)
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -372,6 +489,7 @@ func (p *Project) findApplicationNewCalls(pkgs map[string]*ParsedPackage) (err e
|
|||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
p.addTypes(pkg.Path, pkg.TypeCache)
|
||||||
if !callFound {
|
if !callFound {
|
||||||
return fmt.Errorf("no Bound structs found")
|
return fmt.Errorf("no Bound structs found")
|
||||||
}
|
}
|
||||||
@ -443,7 +561,7 @@ func (p *Project) parseBoundStructMethods(name string, pkg *ParsedPackage) error
|
|||||||
method := &BoundMethod{
|
method := &BoundMethod{
|
||||||
ID: id,
|
ID: id,
|
||||||
Name: funcDecl.Name.Name,
|
Name: funcDecl.Name.Name,
|
||||||
DocComment: funcDecl.Doc.Text(),
|
DocComment: strings.TrimSpace(funcDecl.Doc.Text()),
|
||||||
Alias: alias,
|
Alias: alias,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -464,6 +582,20 @@ func (p *Project) parseBoundStructMethods(name string, pkg *ParsedPackage) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Project) addTypes(packagePath string, types map[string]*TypeDef) {
|
||||||
|
if types == nil || len(types) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if p.Types == nil {
|
||||||
|
p.Types = make(map[string]map[string]*TypeDef)
|
||||||
|
}
|
||||||
|
_, ok := p.Types[packagePath]
|
||||||
|
if !ok {
|
||||||
|
p.Types[packagePath] = make(map[string]*TypeDef)
|
||||||
|
}
|
||||||
|
p.Types[packagePath] = types
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Project) parseParameters(params *ast.FieldList, pkg *ParsedPackage) []*Parameter {
|
func (p *Project) parseParameters(params *ast.FieldList, pkg *ParsedPackage) []*Parameter {
|
||||||
var result []*Parameter
|
var result []*Parameter
|
||||||
for _, field := range params.List {
|
for _, field := range params.List {
|
||||||
@ -489,11 +621,21 @@ func (p *Project) parseParameters(params *ast.FieldList, pkg *ParsedPackage) []*
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Project) parseParameterType(field *ast.Field, pkg *ParsedPackage) *ParameterType {
|
func (p *Project) parseParameterType(field *ast.Field, pkg *ParsedPackage) *ParameterType {
|
||||||
result := &ParameterType{}
|
result := &ParameterType{
|
||||||
|
Package: pkg.Path,
|
||||||
|
}
|
||||||
result.Name = getTypeString(field.Type)
|
result.Name = getTypeString(field.Type)
|
||||||
switch t := field.Type.(type) {
|
switch t := field.Type.(type) {
|
||||||
case *ast.Ident:
|
case *ast.Ident:
|
||||||
result.IsStruct = isStructType(t)
|
result.IsStruct = isStructType(t)
|
||||||
|
if !result.IsStruct {
|
||||||
|
// Check if it's a type alias
|
||||||
|
typeDef, ok := pkg.TypeCache[t.Name]
|
||||||
|
if ok {
|
||||||
|
typeDef.ShouldGenerate = true
|
||||||
|
result.IsEnum = true
|
||||||
|
}
|
||||||
|
}
|
||||||
case *ast.StarExpr:
|
case *ast.StarExpr:
|
||||||
result = p.parseParameterType(&ast.Field{Type: t.X}, pkg)
|
result = p.parseParameterType(&ast.Field{Type: t.X}, pkg)
|
||||||
result.IsPointer = true
|
result.IsPointer = true
|
||||||
@ -597,10 +739,10 @@ func (p *Project) parseStructFields(structType *ast.StructType, pkg *ParsedPacka
|
|||||||
if !ok {
|
if !ok {
|
||||||
p.getStructDef(paramType.Name, pkg)
|
p.getStructDef(paramType.Name, pkg)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if paramType.Package == "" {
|
if paramType.Package == "" {
|
||||||
paramType.Package = pkg.Path
|
paramType.Package = pkg.Path
|
||||||
}
|
}
|
||||||
}
|
|
||||||
thisField.Type = paramType
|
thisField.Type = paramType
|
||||||
result = append(result, thisField)
|
result = append(result, thisField)
|
||||||
}
|
}
|
||||||
@ -822,6 +964,72 @@ func (p *Project) getFunctionFromName(name string, parsedPackage *ParsedPackage)
|
|||||||
return nil, fmt.Errorf("function not found")
|
return nil, fmt.Errorf("function not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Project) parseTypeDeclaration(decl *ast.TypeSpec, pkg *ParsedPackage, comments []string) {
|
||||||
|
switch t := decl.Type.(type) {
|
||||||
|
case *ast.Ident:
|
||||||
|
switch t.Name {
|
||||||
|
case "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64",
|
||||||
|
"uintptr", "float32", "float64", "string", "bool":
|
||||||
|
// Store this in the type cache
|
||||||
|
pkg.TypeCache[decl.Name.Name] = &TypeDef{
|
||||||
|
Name: decl.Name.Name,
|
||||||
|
Type: t.Name,
|
||||||
|
DocComments: TrimSlice(comments),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Project) parseConstDeclaration(decl *ast.GenDecl, pkg *ParsedPackage) {
|
||||||
|
// Check if the type of the constant is in the type cache and if it doesn't exist, return
|
||||||
|
var latestValues []ast.Expr
|
||||||
|
|
||||||
|
for _, spec := range decl.Specs {
|
||||||
|
valueSpec, ok := spec.(*ast.ValueSpec)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Extract the Type
|
||||||
|
typeString := getTypeString(valueSpec.Type)
|
||||||
|
if typeString == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// Check if the type is in the type cache
|
||||||
|
typeDecl, ok := pkg.TypeCache[typeString]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the latest values
|
||||||
|
if len(valueSpec.Values) > 0 {
|
||||||
|
latestValues = valueSpec.Values
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate over the names
|
||||||
|
for index, name := range valueSpec.Names {
|
||||||
|
constDecl := &ConstDef{
|
||||||
|
Name: name.Name,
|
||||||
|
Value: typeString,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the value
|
||||||
|
if len(latestValues) > 0 {
|
||||||
|
switch t := latestValues[index].(type) {
|
||||||
|
case *ast.BasicLit:
|
||||||
|
constDecl.Value = t.Value
|
||||||
|
case *ast.Ident:
|
||||||
|
constDecl.Value = t.Name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if valueSpec.Doc != nil {
|
||||||
|
constDecl.DocComment = strings.TrimSpace(valueSpec.Doc.Text())
|
||||||
|
}
|
||||||
|
typeDecl.Consts = append(typeDecl.Consts, constDecl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func getTypeString(expr ast.Expr) string {
|
func getTypeString(expr ast.Expr) string {
|
||||||
switch t := expr.(type) {
|
switch t := expr.(type) {
|
||||||
case *ast.Ident:
|
case *ast.Ident:
|
||||||
@ -852,7 +1060,10 @@ func isStructType(expr ast.Expr) bool {
|
|||||||
case *ast.SliceExpr:
|
case *ast.SliceExpr:
|
||||||
return isStructType(e.X)
|
return isStructType(e.X)
|
||||||
case *ast.Ident:
|
case *ast.Ident:
|
||||||
return e.Obj != nil && e.Obj.Kind == ast.Typ
|
if e.Obj != nil && e.Obj.Kind == ast.Typ {
|
||||||
|
return isStructType(e.Obj.Decl.(*ast.TypeSpec).Type)
|
||||||
|
}
|
||||||
|
return false
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -869,3 +1080,21 @@ func getDirectoryForPackage(pkg *ast.Package) string {
|
|||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CommentGroupToText(comments *ast.CommentGroup) []string {
|
||||||
|
if comments == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var result []string
|
||||||
|
for _, comment := range comments.List {
|
||||||
|
result = append(result, strings.TrimSpace(comment.Text))
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func TrimSlice(comments []string) []string {
|
||||||
|
for i, comment := range comments {
|
||||||
|
comments[i] = strings.TrimSpace(comment)
|
||||||
|
}
|
||||||
|
return comments
|
||||||
|
}
|
||||||
|
162
v3/internal/parser/parser_enum_test.go
Normal file
162
v3/internal/parser/parser_enum_test.go
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
package parser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseEnum(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
dir string
|
||||||
|
wantBoundMethods map[string]map[string][]*BoundMethod
|
||||||
|
wantEnums map[string]map[string]*EnumDef
|
||||||
|
wantModels map[string]map[string]*StructDef
|
||||||
|
wantTypes map[string]map[string]*TypeDef
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "should find a bound services with an enum",
|
||||||
|
dir: "testdata/enum",
|
||||||
|
wantErr: false,
|
||||||
|
wantBoundMethods: map[string]map[string][]*BoundMethod{
|
||||||
|
"main": {
|
||||||
|
"GreetService": {
|
||||||
|
{
|
||||||
|
Name: "Greet",
|
||||||
|
DocComment: "Greet does XYZ",
|
||||||
|
Inputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "name",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "title",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "Title",
|
||||||
|
IsEnum: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ID: 1411160069,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "NewPerson",
|
||||||
|
DocComment: "NewPerson creates a new person",
|
||||||
|
Inputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "name",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "Person",
|
||||||
|
IsStruct: true,
|
||||||
|
IsPointer: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ID: 1661412647,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantTypes: map[string]map[string]*TypeDef{
|
||||||
|
"main": {
|
||||||
|
"Title": {
|
||||||
|
Name: "Title",
|
||||||
|
Type: "string",
|
||||||
|
Consts: []*ConstDef{
|
||||||
|
{
|
||||||
|
Name: "Mister",
|
||||||
|
DocComment: "Mister is a title",
|
||||||
|
Value: `"Mr"`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Miss",
|
||||||
|
Value: `"Miss"`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Ms",
|
||||||
|
Value: `"Ms"`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Mrs",
|
||||||
|
Value: `"Mrs"`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Dr",
|
||||||
|
Value: `"Dr"`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ShouldGenerate: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantModels: map[string]map[string]*StructDef{
|
||||||
|
"main": {
|
||||||
|
"Person": {
|
||||||
|
Name: "Person",
|
||||||
|
Fields: []*Field{
|
||||||
|
{
|
||||||
|
Name: "Title",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "Title",
|
||||||
|
IsEnum: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Name",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := ParseProject(tt.dir)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("ParseDirectory() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(tt.wantBoundMethods, got.BoundMethods); diff != "" {
|
||||||
|
t.Errorf("ParseDirectory() failed:\n" + diff)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(tt.wantModels, got.Models) {
|
||||||
|
t.Errorf("ParseDirectory() failed:\n" + cmp.Diff(tt.wantModels, got.Models))
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(tt.wantTypes, got.Types); diff != "" {
|
||||||
|
t.Errorf("ParseDirectory() failed:\n" + diff)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
204
v3/internal/parser/parser_function_test.go
Normal file
204
v3/internal/parser/parser_function_test.go
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
package parser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseFunction(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
dir string
|
||||||
|
wantBoundMethods map[string]map[string][]*BoundMethod
|
||||||
|
wantEnums map[string]map[string]*EnumDef
|
||||||
|
wantModels map[string]map[string]*StructDef
|
||||||
|
wantTypes map[string]map[string]*TypeDef
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "should find a bound service returned from a function call",
|
||||||
|
dir: "testdata/function_single",
|
||||||
|
wantErr: false,
|
||||||
|
wantBoundMethods: map[string]map[string][]*BoundMethod{
|
||||||
|
"main": {
|
||||||
|
"GreetService": {
|
||||||
|
{
|
||||||
|
Name: "Greet",
|
||||||
|
DocComment: "Greet someone",
|
||||||
|
Inputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "name",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ID: 1411160069,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should find a bound service returned from a function call in another package",
|
||||||
|
dir: "testdata/function_from_imported_package",
|
||||||
|
wantErr: false,
|
||||||
|
wantBoundMethods: map[string]map[string][]*BoundMethod{
|
||||||
|
"main": {
|
||||||
|
"GreetService": {
|
||||||
|
{
|
||||||
|
Name: "Greet",
|
||||||
|
DocComment: "Greet does XYZ",
|
||||||
|
Inputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "name",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ID: 1411160069,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "NewPerson",
|
||||||
|
DocComment: "NewPerson creates a new person",
|
||||||
|
Inputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "name",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "Person",
|
||||||
|
IsPointer: true,
|
||||||
|
IsStruct: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ID: 1661412647,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"github.com/wailsapp/wails/v3/internal/parser/testdata/variable_single_from_other_function/services": {
|
||||||
|
"OtherService": {
|
||||||
|
{
|
||||||
|
Name: "Yay",
|
||||||
|
Outputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Type: &ParameterType{
|
||||||
|
Name: "Address",
|
||||||
|
IsStruct: true,
|
||||||
|
IsPointer: true,
|
||||||
|
Package: "github.com/wailsapp/wails/v3/internal/parser/testdata/variable_single_from_other_function/services",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ID: 302702907,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantModels: map[string]map[string]*StructDef{
|
||||||
|
"main": {
|
||||||
|
"Person": {
|
||||||
|
Name: "Person",
|
||||||
|
Fields: []*Field{
|
||||||
|
{
|
||||||
|
Name: "Name",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Address",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Name: "Address",
|
||||||
|
IsStruct: true,
|
||||||
|
IsPointer: true,
|
||||||
|
Package: "github.com/wailsapp/wails/v3/internal/parser/testdata/variable_single_from_other_function/services",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"github.com/wailsapp/wails/v3/internal/parser/testdata/variable_single_from_other_function/services": {
|
||||||
|
"Address": {
|
||||||
|
Name: "Address",
|
||||||
|
Fields: []*Field{
|
||||||
|
{
|
||||||
|
Name: "Street",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "github.com/wailsapp/wails/v3/internal/parser/testdata/variable_single_from_other_function/services",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "State",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "github.com/wailsapp/wails/v3/internal/parser/testdata/variable_single_from_other_function/services",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Country",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "github.com/wailsapp/wails/v3/internal/parser/testdata/variable_single_from_other_function/services",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := ParseProject(tt.dir)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("ParseDirectory() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(tt.wantBoundMethods, got.BoundMethods); diff != "" {
|
||||||
|
t.Errorf("ParseDirectory() failed:\n" + diff)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(tt.wantModels, got.Models) {
|
||||||
|
t.Errorf("ParseDirectory() failed:\n" + cmp.Diff(tt.wantModels, got.Models))
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(tt.wantTypes, got.Types); diff != "" {
|
||||||
|
t.Errorf("ParseDirectory() failed:\n" + diff)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
250
v3/internal/parser/parser_struct_literal_multiple_test.go
Normal file
250
v3/internal/parser/parser_struct_literal_multiple_test.go
Normal file
@ -0,0 +1,250 @@
|
|||||||
|
package parser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseStructLiteralMultiple(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
dir string
|
||||||
|
wantBoundMethods map[string]map[string][]*BoundMethod
|
||||||
|
wantEnums map[string]map[string]*EnumDef
|
||||||
|
wantModels map[string]map[string]*StructDef
|
||||||
|
wantTypes map[string]map[string]*TypeDef
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "should find multiple bound services",
|
||||||
|
dir: "testdata/struct_literal_multiple",
|
||||||
|
wantBoundMethods: map[string]map[string][]*BoundMethod{
|
||||||
|
"main": {
|
||||||
|
"GreetService": {
|
||||||
|
{
|
||||||
|
Name: "Greet",
|
||||||
|
DocComment: "",
|
||||||
|
Inputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "name",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ID: 1411160069,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"OtherService": {
|
||||||
|
{
|
||||||
|
Name: "Hello",
|
||||||
|
ID: 4249972365,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should find multiple bound services over multiple files",
|
||||||
|
dir: "testdata/struct_literal_multiple_files",
|
||||||
|
wantBoundMethods: map[string]map[string][]*BoundMethod{
|
||||||
|
"main": {
|
||||||
|
"GreetService": {
|
||||||
|
{
|
||||||
|
Name: "Greet",
|
||||||
|
DocComment: "",
|
||||||
|
Inputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "name",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ID: 1411160069,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"OtherService": {
|
||||||
|
{
|
||||||
|
Name: "Hello",
|
||||||
|
ID: 4249972365,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should find multiple bound services over multiple packages",
|
||||||
|
dir: "testdata/struct_literal_multiple_other",
|
||||||
|
wantErr: false,
|
||||||
|
wantBoundMethods: map[string]map[string][]*BoundMethod{
|
||||||
|
"main": {
|
||||||
|
"GreetService": {
|
||||||
|
{
|
||||||
|
Name: "Greet",
|
||||||
|
DocComment: "Greet does XYZ",
|
||||||
|
Inputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "name",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ID: 1411160069,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "NewPerson",
|
||||||
|
DocComment: "NewPerson creates a new person",
|
||||||
|
Inputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "name",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "Person",
|
||||||
|
IsPointer: true,
|
||||||
|
IsStruct: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ID: 1661412647,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"github.com/wailsapp/wails/v3/internal/parser/testdata/struct_literal_multiple_other/services": {
|
||||||
|
"OtherService": {
|
||||||
|
{
|
||||||
|
Name: "Yay",
|
||||||
|
Outputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Type: &ParameterType{
|
||||||
|
Name: "Address",
|
||||||
|
IsStruct: true,
|
||||||
|
IsPointer: true,
|
||||||
|
Package: "github.com/wailsapp/wails/v3/internal/parser/testdata/struct_literal_multiple_other/services",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ID: 469445984,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantModels: map[string]map[string]*StructDef{
|
||||||
|
"main": {
|
||||||
|
"Person": {
|
||||||
|
Name: "Person",
|
||||||
|
Fields: []*Field{
|
||||||
|
{
|
||||||
|
Name: "Name",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Address",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Name: "Address",
|
||||||
|
IsStruct: true,
|
||||||
|
IsPointer: true,
|
||||||
|
Package: "github.com/wailsapp/wails/v3/internal/parser/testdata/struct_literal_multiple_other/services",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"github.com/wailsapp/wails/v3/internal/parser/testdata/struct_literal_multiple_other/services": {
|
||||||
|
"Address": {
|
||||||
|
Name: "Address",
|
||||||
|
Fields: []*Field{
|
||||||
|
{
|
||||||
|
Name: "Street",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "github.com/wailsapp/wails/v3/internal/parser/testdata/struct_literal_multiple_other/services",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "State",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "github.com/wailsapp/wails/v3/internal/parser/testdata/struct_literal_multiple_other/services",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Country",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "github.com/wailsapp/wails/v3/internal/parser/testdata/struct_literal_multiple_other/services",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := ParseProject(tt.dir)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("ParseDirectory() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(tt.wantBoundMethods, got.BoundMethods); diff != "" {
|
||||||
|
t.Errorf("ParseDirectory() failed:\n" + diff)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(tt.wantModels, got.Models) {
|
||||||
|
t.Errorf("ParseDirectory() failed:\n" + cmp.Diff(tt.wantModels, got.Models))
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(tt.wantTypes, got.Types); diff != "" {
|
||||||
|
t.Errorf("ParseDirectory() failed:\n" + diff)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
1091
v3/internal/parser/parser_struct_literal_non_pointer_single_test.go
Normal file
1091
v3/internal/parser/parser_struct_literal_non_pointer_single_test.go
Normal file
File diff suppressed because it is too large
Load Diff
1092
v3/internal/parser/parser_struct_literal_single_test.go
Normal file
1092
v3/internal/parser/parser_struct_literal_single_test.go
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
238
v3/internal/parser/parser_variable_single_test.go
Normal file
238
v3/internal/parser/parser_variable_single_test.go
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
package parser
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/google/go-cmp/cmp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParseVariableSingle(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
dir string
|
||||||
|
wantBoundMethods map[string]map[string][]*BoundMethod
|
||||||
|
wantEnums map[string]map[string]*EnumDef
|
||||||
|
wantModels map[string]map[string]*StructDef
|
||||||
|
wantTypes map[string]map[string]*TypeDef
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "should find a bound services using a variable",
|
||||||
|
dir: "testdata/variable_single",
|
||||||
|
wantErr: false,
|
||||||
|
wantBoundMethods: map[string]map[string][]*BoundMethod{
|
||||||
|
"main": {
|
||||||
|
"GreetService": {
|
||||||
|
{
|
||||||
|
Name: "Greet",
|
||||||
|
DocComment: "Greet someone",
|
||||||
|
Inputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "name",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ID: 1411160069,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should find a bound services using a variable from function call",
|
||||||
|
dir: "testdata/variable_single_from_function",
|
||||||
|
wantErr: false,
|
||||||
|
wantBoundMethods: map[string]map[string][]*BoundMethod{
|
||||||
|
"main": {
|
||||||
|
"GreetService": {
|
||||||
|
{
|
||||||
|
Name: "Greet",
|
||||||
|
DocComment: "Greet someone",
|
||||||
|
Inputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "name",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ID: 1411160069,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "should find a bound services using a variable from function call in another package",
|
||||||
|
dir: "testdata/variable_single_from_other_function",
|
||||||
|
wantErr: false,
|
||||||
|
wantBoundMethods: map[string]map[string][]*BoundMethod{
|
||||||
|
"main": {
|
||||||
|
"GreetService": {
|
||||||
|
{
|
||||||
|
Name: "Greet",
|
||||||
|
DocComment: "Greet does XYZ",
|
||||||
|
Inputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "name",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ID: 1411160069,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "NewPerson",
|
||||||
|
DocComment: "NewPerson creates a new person",
|
||||||
|
Inputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "name",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Outputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Name: "",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "Person",
|
||||||
|
IsPointer: true,
|
||||||
|
IsStruct: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ID: 1661412647,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"github.com/wailsapp/wails/v3/internal/parser/testdata/variable_single_from_other_function/services": {
|
||||||
|
"OtherService": {
|
||||||
|
{
|
||||||
|
Name: "Yay",
|
||||||
|
Outputs: []*Parameter{
|
||||||
|
{
|
||||||
|
Type: &ParameterType{
|
||||||
|
Name: "Address",
|
||||||
|
IsStruct: true,
|
||||||
|
IsPointer: true,
|
||||||
|
Package: "github.com/wailsapp/wails/v3/internal/parser/testdata/variable_single_from_other_function/services",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ID: 302702907,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
wantModels: map[string]map[string]*StructDef{
|
||||||
|
"main": {
|
||||||
|
"Person": {
|
||||||
|
Name: "Person",
|
||||||
|
Fields: []*Field{
|
||||||
|
{
|
||||||
|
Name: "Name",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "main",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Address",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Name: "Address",
|
||||||
|
IsStruct: true,
|
||||||
|
IsPointer: true,
|
||||||
|
Package: "github.com/wailsapp/wails/v3/internal/parser/testdata/variable_single_from_other_function/services",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"github.com/wailsapp/wails/v3/internal/parser/testdata/variable_single_from_other_function/services": {
|
||||||
|
"Address": {
|
||||||
|
Name: "Address",
|
||||||
|
Fields: []*Field{
|
||||||
|
{
|
||||||
|
Name: "Street",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "github.com/wailsapp/wails/v3/internal/parser/testdata/variable_single_from_other_function/services",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "State",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "github.com/wailsapp/wails/v3/internal/parser/testdata/variable_single_from_other_function/services",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Country",
|
||||||
|
Type: &ParameterType{
|
||||||
|
Package: "github.com/wailsapp/wails/v3/internal/parser/testdata/variable_single_from_other_function/services",
|
||||||
|
Name: "string",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
got, err := ParseProject(tt.dir)
|
||||||
|
if (err != nil) != tt.wantErr {
|
||||||
|
t.Errorf("ParseDirectory() error = %v, wantErr %v", err, tt.wantErr)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(tt.wantBoundMethods, got.BoundMethods); diff != "" {
|
||||||
|
t.Errorf("ParseDirectory() failed:\n" + diff)
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(tt.wantModels, got.Models) {
|
||||||
|
t.Errorf("ParseDirectory() failed:\n" + cmp.Diff(tt.wantModels, got.Models))
|
||||||
|
}
|
||||||
|
if diff := cmp.Diff(tt.wantTypes, got.Types); diff != "" {
|
||||||
|
t.Errorf("ParseDirectory() failed:\n" + diff)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,16 +0,0 @@
|
|||||||
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}}
|
|
||||||
}
|
|
||||||
}
|
|
8
v3/internal/parser/templates/interfaces.ts.tmpl
Normal file
8
v3/internal/parser/templates/interfaces.ts.tmpl
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{{$pkg := .Package}}
|
||||||
|
export namespace {{.Package}} {
|
||||||
|
{{range $name, $def := .Models}}
|
||||||
|
export interface {{$def.Name}} { {{range $def.Fields}}
|
||||||
|
{{.JSDef $pkg}}{{end}}
|
||||||
|
}
|
||||||
|
{{end}}
|
||||||
|
}
|
@ -1,21 +1,31 @@
|
|||||||
{{$pkg := .Package}}
|
{{$pkg := .Package}}
|
||||||
export namespace {{.Package}} {
|
export namespace {{.Package}} {
|
||||||
|
{{range $enumindex, $enumdef := .Enums}}
|
||||||
|
{{- range $commentindex, $commentdef := .DocComments}}
|
||||||
|
{{$commentdef -}}
|
||||||
|
{{- end}}
|
||||||
|
export enum {{$enumdef.Name}} {
|
||||||
|
{{- range $constindex, $constdef := .Consts}}
|
||||||
|
{{- if $constdef.DocComment}}
|
||||||
|
// {{$constdef.DocComment}}
|
||||||
|
{{- end}}
|
||||||
|
{{$constdef.Name}} = {{$constdef.Value}},{{end}}
|
||||||
|
}
|
||||||
|
{{- end}}
|
||||||
{{range $name, $def := .Models}}
|
{{range $name, $def := .Models}}
|
||||||
export class {{$def.Name}} {
|
export class {{$def.Name}} {
|
||||||
{{range $def.Fields}}{{.JSDef $pkg}}
|
{{range $def.Fields}}{{.JSDef $pkg}}
|
||||||
{{end}}
|
{{end}}
|
||||||
static createFrom(source: any = {}) {
|
constructor(source: Partial<{{$def.Name}}> = {}) {
|
||||||
return new {{$def.Name}}(source);
|
const { {{$def.DefaultValueList}} } = source; {{range $def.Fields}}
|
||||||
|
this.{{.JSName}} = {{.JSName}};{{end}}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(source: any = {}) {
|
static createFrom(source: string | object = {}): {{$def.Name}} {
|
||||||
if ('string' === typeof source) {
|
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
|
||||||
source = JSON.parse(source);
|
return new {{$def.Name}}(parsedSource as Partial<{{$def.Name}}>);
|
||||||
}
|
}
|
||||||
|
|
||||||
{{range $def.Fields}}this.{{.JSName}} = {{.TSBuild $pkg}};
|
|
||||||
{{end}}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
{{end}}
|
{{end}}
|
||||||
}
|
}
|
29
v3/internal/parser/testdata/enum/bindings_main.js
vendored
Normal file
29
v3/internal/parser/testdata/enum/bindings_main.js
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// @ts-check
|
||||||
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import('./models').main.Title} mainTitle
|
||||||
|
* @typedef {import('./models').main.Person} mainPerson
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const GreetService = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GreetService.Greet
|
||||||
|
* Greet does XYZ
|
||||||
|
* @param name {string}
|
||||||
|
* @param title {mainTitle}
|
||||||
|
* @returns {Promise<string>}
|
||||||
|
**/
|
||||||
|
Greet: function(name, title) { return wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); },
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GreetService.NewPerson
|
||||||
|
* NewPerson creates a new person
|
||||||
|
* @param name {string}
|
||||||
|
* @returns {Promise<mainPerson>}
|
||||||
|
**/
|
||||||
|
NewPerson: function(name) { return wails.CallByID(1661412647, ...Array.prototype.slice.call(arguments, 0)); },
|
||||||
|
};
|
||||||
|
|
58
v3/internal/parser/testdata/enum/main.go
vendored
Normal file
58
v3/internal/parser/testdata/enum/main.go
vendored
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v3/pkg/application"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Title string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Mister is a title
|
||||||
|
Mister Title = "Mr"
|
||||||
|
Miss Title = "Miss"
|
||||||
|
Ms Title = "Ms"
|
||||||
|
Mrs Title = "Mrs"
|
||||||
|
Dr Title = "Dr"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GreetService is great
|
||||||
|
type GreetService struct {
|
||||||
|
SomeVariable int
|
||||||
|
lowerCase string
|
||||||
|
target *Person
|
||||||
|
}
|
||||||
|
|
||||||
|
type Person struct {
|
||||||
|
Title Title
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Greet does XYZ
|
||||||
|
func (*GreetService) Greet(name string, title Title) string {
|
||||||
|
return "Hello " + string(title) + " " + name
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPerson creates a new person
|
||||||
|
func (*GreetService) NewPerson(name string) *Person {
|
||||||
|
return &Person{Name: name}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := application.New(application.Options{
|
||||||
|
Bind: []interface{}{
|
||||||
|
&GreetService{},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
app.NewWebviewWindow()
|
||||||
|
|
||||||
|
err := app.Run()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
33
v3/internal/parser/testdata/enum/models.ts
vendored
Normal file
33
v3/internal/parser/testdata/enum/models.ts
vendored
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// @ts-check
|
||||||
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
export namespace main {
|
||||||
|
|
||||||
|
export enum Title {
|
||||||
|
// Mister is a title
|
||||||
|
Mister = "Mr",
|
||||||
|
Miss = "Miss",
|
||||||
|
Ms = "Ms",
|
||||||
|
Mrs = "Mrs",
|
||||||
|
Dr = "Dr",
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Person {
|
||||||
|
title: Title;
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
constructor(source: Partial<Person> = {}) {
|
||||||
|
const { title = null, name = "" } = source;
|
||||||
|
this.title = title;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static createFrom(source: string | object = {}): Person {
|
||||||
|
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
|
||||||
|
return new Person(parsedSource as Partial<Person>);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
30
v3/internal/parser/testdata/enum_from_imported_package/bindings_main.js
vendored
Normal file
30
v3/internal/parser/testdata/enum_from_imported_package/bindings_main.js
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// @ts-check
|
||||||
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import('./models').main.Person} mainPerson
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
window.go = window.go || {};
|
||||||
|
window.go.main = {
|
||||||
|
GreetService: {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GreetService.Greet
|
||||||
|
* Greet does XYZ
|
||||||
|
* @param name {string}
|
||||||
|
* @returns {Promise<string>}
|
||||||
|
**/
|
||||||
|
Greet: function(name) { return wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); },
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GreetService.NewPerson
|
||||||
|
* NewPerson creates a new person
|
||||||
|
* @param name {string}
|
||||||
|
* @returns {Promise<mainPerson>}
|
||||||
|
**/
|
||||||
|
NewPerson: function(name) { return wails.CallByID(1661412647, ...Array.prototype.slice.call(arguments, 0)); },
|
||||||
|
},
|
||||||
|
};
|
22
v3/internal/parser/testdata/enum_from_imported_package/bindings_services.js
vendored
Normal file
22
v3/internal/parser/testdata/enum_from_imported_package/bindings_services.js
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// @ts-check
|
||||||
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import('./models').services.Address} servicesAddress
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
window.go = window.go || {};
|
||||||
|
window.go.services = {
|
||||||
|
OtherService: {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OtherService.Yay
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @returns {Promise<servicesAddress>}
|
||||||
|
**/
|
||||||
|
Yay: function() { return wails.CallByID(302702907, ...Array.prototype.slice.call(arguments, 0)); },
|
||||||
|
},
|
||||||
|
};
|
37
v3/internal/parser/testdata/enum_from_imported_package/main.go
vendored
Normal file
37
v3/internal/parser/testdata/enum_from_imported_package/main.go
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
"github.com/wailsapp/wails/v3/internal/parser/testdata/enum_from_imported_package/services"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/wailsapp/wails/v3/pkg/application"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GreetService is great
|
||||||
|
type GreetService struct {
|
||||||
|
SomeVariable int
|
||||||
|
lowerCase string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Greet does XYZ
|
||||||
|
func (*GreetService) Greet(name string, title services.Title) string {
|
||||||
|
return "Hello " + title.String() + " " + name
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
app := application.New(application.Options{
|
||||||
|
Bind: []interface{}{
|
||||||
|
&GreetService{},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
app.NewWebviewWindow()
|
||||||
|
|
||||||
|
err := app.Run()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
47
v3/internal/parser/testdata/enum_from_imported_package/models.ts
vendored
Normal file
47
v3/internal/parser/testdata/enum_from_imported_package/models.ts
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// @ts-check
|
||||||
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
export namespace main {
|
||||||
|
|
||||||
|
export class Person {
|
||||||
|
name: string;
|
||||||
|
address: services.Address;
|
||||||
|
|
||||||
|
constructor(source: Partial<Person> = {}) {
|
||||||
|
const { name = "", address = null } = source;
|
||||||
|
this.name = name;
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
static createFrom(source: string | object = {}): Person {
|
||||||
|
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
|
||||||
|
return new Person(parsedSource as Partial<Person>);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace services {
|
||||||
|
|
||||||
|
export class Address {
|
||||||
|
street: string;
|
||||||
|
state: string;
|
||||||
|
country: string;
|
||||||
|
|
||||||
|
constructor(source: Partial<Address> = {}) {
|
||||||
|
const { street = "", state = "", country = "" } = source;
|
||||||
|
this.street = street;
|
||||||
|
this.state = state;
|
||||||
|
this.country = country;
|
||||||
|
}
|
||||||
|
|
||||||
|
static createFrom(source: string | object = {}): Address {
|
||||||
|
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
|
||||||
|
return new Address(parsedSource as Partial<Address>);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
16
v3/internal/parser/testdata/enum_from_imported_package/services/other.go
vendored
Normal file
16
v3/internal/parser/testdata/enum_from_imported_package/services/other.go
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package services
|
||||||
|
|
||||||
|
type Title string
|
||||||
|
|
||||||
|
func (t Title) String() string {
|
||||||
|
return string(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Mister is a title
|
||||||
|
Mister Title = "Mr"
|
||||||
|
Miss Title = "Miss"
|
||||||
|
Ms Title = "Ms"
|
||||||
|
Mrs Title = "Mrs"
|
||||||
|
Dr Title = "Dr"
|
||||||
|
)
|
@ -6,10 +6,7 @@
|
|||||||
* @typedef {import('./models').main.Person} mainPerson
|
* @typedef {import('./models').main.Person} mainPerson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
export const GreetService = {
|
||||||
window.go = window.go || {};
|
|
||||||
window.go.main = {
|
|
||||||
GreetService: {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GreetService.Greet
|
* GreetService.Greet
|
||||||
@ -26,5 +23,5 @@ window.go.main = {
|
|||||||
* @returns {Promise<mainPerson>}
|
* @returns {Promise<mainPerson>}
|
||||||
**/
|
**/
|
||||||
NewPerson: function(name) { return wails.CallByID(1661412647, ...Array.prototype.slice.call(arguments, 0)); },
|
NewPerson: function(name) { return wails.CallByID(1661412647, ...Array.prototype.slice.call(arguments, 0)); },
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,10 +6,7 @@
|
|||||||
* @typedef {import('./models').services.Address} servicesAddress
|
* @typedef {import('./models').services.Address} servicesAddress
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
export const OtherService = {
|
||||||
window.go = window.go || {};
|
|
||||||
window.go.services = {
|
|
||||||
OtherService: {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OtherService.Yay
|
* OtherService.Yay
|
||||||
@ -18,5 +15,5 @@ window.go.services = {
|
|||||||
* @returns {Promise<servicesAddress>}
|
* @returns {Promise<servicesAddress>}
|
||||||
**/
|
**/
|
||||||
Yay: function() { return wails.CallByID(302702907, ...Array.prototype.slice.call(arguments, 0)); },
|
Yay: function() { return wails.CallByID(302702907, ...Array.prototype.slice.call(arguments, 0)); },
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,48 +4,45 @@
|
|||||||
|
|
||||||
export namespace main {
|
export namespace main {
|
||||||
|
|
||||||
|
|
||||||
export class Person {
|
export class Person {
|
||||||
name: string;
|
name: string;
|
||||||
address: services.Address;
|
address: services.Address;
|
||||||
|
|
||||||
static createFrom(source: any = {}) {
|
constructor(source: Partial<Person> = {}) {
|
||||||
return new Person(source);
|
const { name = "", address = null } = source;
|
||||||
|
this.name = name;
|
||||||
|
this.address = address;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(source: any = {}) {
|
static createFrom(source: string | object = {}): Person {
|
||||||
if ('string' === typeof source) {
|
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
|
||||||
source = JSON.parse(source);
|
return new Person(parsedSource as Partial<Person>);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.name = source['name'];
|
|
||||||
this.address = services.Address.createFrom(source['address']);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace services {
|
export namespace services {
|
||||||
|
|
||||||
|
|
||||||
export class Address {
|
export class Address {
|
||||||
street: string;
|
street: string;
|
||||||
state: string;
|
state: string;
|
||||||
country: string;
|
country: string;
|
||||||
|
|
||||||
static createFrom(source: any = {}) {
|
constructor(source: Partial<Address> = {}) {
|
||||||
return new Address(source);
|
const { street = "", state = "", country = "" } = source;
|
||||||
|
this.street = street;
|
||||||
|
this.state = state;
|
||||||
|
this.country = country;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(source: any = {}) {
|
static createFrom(source: string | object = {}): Address {
|
||||||
if ('string' === typeof source) {
|
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
|
||||||
source = JSON.parse(source);
|
return new Address(parsedSource as Partial<Address>);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.street = source['street'];
|
|
||||||
this.state = source['state'];
|
|
||||||
this.country = source['country'];
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -2,10 +2,7 @@
|
|||||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
// This file is automatically generated. DO NOT EDIT
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
export const GreetService = {
|
||||||
window.go = window.go || {};
|
|
||||||
window.go.main = {
|
|
||||||
GreetService: {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GreetService.Greet
|
* GreetService.Greet
|
||||||
@ -14,5 +11,5 @@ window.go.main = {
|
|||||||
* @returns {Promise<string>}
|
* @returns {Promise<string>}
|
||||||
**/
|
**/
|
||||||
Greet: function(name) { return wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); },
|
Greet: function(name) { return wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); },
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,10 +2,7 @@
|
|||||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
// This file is automatically generated. DO NOT EDIT
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
export const GreetService = {
|
||||||
window.go = window.go || {};
|
|
||||||
window.go.main = {
|
|
||||||
GreetService: {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GreetService.Greet
|
* GreetService.Greet
|
||||||
@ -14,8 +11,9 @@ window.go.main = {
|
|||||||
* @returns {Promise<string>}
|
* @returns {Promise<string>}
|
||||||
**/
|
**/
|
||||||
Greet: function(name) { return wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); },
|
Greet: function(name) { return wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); },
|
||||||
},
|
};
|
||||||
OtherService: {
|
|
||||||
|
export const OtherService = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OtherService.Hello
|
* OtherService.Hello
|
||||||
@ -24,5 +22,5 @@ window.go.main = {
|
|||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
**/
|
**/
|
||||||
Hello: function() { return wails.CallByID(4249972365, ...Array.prototype.slice.call(arguments, 0)); },
|
Hello: function() { return wails.CallByID(4249972365, ...Array.prototype.slice.call(arguments, 0)); },
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,10 +2,7 @@
|
|||||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
// This file is automatically generated. DO NOT EDIT
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
export const GreetService = {
|
||||||
window.go = window.go || {};
|
|
||||||
window.go.main = {
|
|
||||||
GreetService: {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GreetService.Greet
|
* GreetService.Greet
|
||||||
@ -14,8 +11,9 @@ window.go.main = {
|
|||||||
* @returns {Promise<string>}
|
* @returns {Promise<string>}
|
||||||
**/
|
**/
|
||||||
Greet: function(name) { return wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); },
|
Greet: function(name) { return wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); },
|
||||||
},
|
};
|
||||||
OtherService: {
|
|
||||||
|
export const OtherService = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OtherService.Hello
|
* OtherService.Hello
|
||||||
@ -24,5 +22,5 @@ window.go.main = {
|
|||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
**/
|
**/
|
||||||
Hello: function() { return wails.CallByID(4249972365, ...Array.prototype.slice.call(arguments, 0)); },
|
Hello: function() { return wails.CallByID(4249972365, ...Array.prototype.slice.call(arguments, 0)); },
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,10 +6,7 @@
|
|||||||
* @typedef {import('./models').main.Person} mainPerson
|
* @typedef {import('./models').main.Person} mainPerson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
export const GreetService = {
|
||||||
window.go = window.go || {};
|
|
||||||
window.go.main = {
|
|
||||||
GreetService: {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GreetService.Greet
|
* GreetService.Greet
|
||||||
@ -26,5 +23,5 @@ window.go.main = {
|
|||||||
* @returns {Promise<mainPerson>}
|
* @returns {Promise<mainPerson>}
|
||||||
**/
|
**/
|
||||||
NewPerson: function(name) { return wails.CallByID(1661412647, ...Array.prototype.slice.call(arguments, 0)); },
|
NewPerson: function(name) { return wails.CallByID(1661412647, ...Array.prototype.slice.call(arguments, 0)); },
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,10 +6,7 @@
|
|||||||
* @typedef {import('./models').services.Address} servicesAddress
|
* @typedef {import('./models').services.Address} servicesAddress
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
export const OtherService = {
|
||||||
window.go = window.go || {};
|
|
||||||
window.go.services = {
|
|
||||||
OtherService: {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OtherService.Yay
|
* OtherService.Yay
|
||||||
@ -18,5 +15,5 @@ window.go.services = {
|
|||||||
* @returns {Promise<servicesAddress>}
|
* @returns {Promise<servicesAddress>}
|
||||||
**/
|
**/
|
||||||
Yay: function() { return wails.CallByID(469445984, ...Array.prototype.slice.call(arguments, 0)); },
|
Yay: function() { return wails.CallByID(469445984, ...Array.prototype.slice.call(arguments, 0)); },
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,48 +4,45 @@
|
|||||||
|
|
||||||
export namespace main {
|
export namespace main {
|
||||||
|
|
||||||
|
|
||||||
export class Person {
|
export class Person {
|
||||||
name: string;
|
name: string;
|
||||||
address: services.Address;
|
address: services.Address;
|
||||||
|
|
||||||
static createFrom(source: any = {}) {
|
constructor(source: Partial<Person> = {}) {
|
||||||
return new Person(source);
|
const { name = "", address = null } = source;
|
||||||
|
this.name = name;
|
||||||
|
this.address = address;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(source: any = {}) {
|
static createFrom(source: string | object = {}): Person {
|
||||||
if ('string' === typeof source) {
|
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
|
||||||
source = JSON.parse(source);
|
return new Person(parsedSource as Partial<Person>);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.name = source['name'];
|
|
||||||
this.address = services.Address.createFrom(source['address']);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace services {
|
export namespace services {
|
||||||
|
|
||||||
|
|
||||||
export class Address {
|
export class Address {
|
||||||
street: string;
|
street: string;
|
||||||
state: string;
|
state: string;
|
||||||
country: string;
|
country: string;
|
||||||
|
|
||||||
static createFrom(source: any = {}) {
|
constructor(source: Partial<Address> = {}) {
|
||||||
return new Address(source);
|
const { street = "", state = "", country = "" } = source;
|
||||||
|
this.street = street;
|
||||||
|
this.state = state;
|
||||||
|
this.country = country;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(source: any = {}) {
|
static createFrom(source: string | object = {}): Address {
|
||||||
if ('string' === typeof source) {
|
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
|
||||||
source = JSON.parse(source);
|
return new Address(parsedSource as Partial<Address>);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.street = source['street'];
|
|
||||||
this.state = source['state'];
|
|
||||||
this.country = source['country'];
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -6,10 +6,7 @@
|
|||||||
* @typedef {import('./models').main.Person} mainPerson
|
* @typedef {import('./models').main.Person} mainPerson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
export const GreetService = {
|
||||||
window.go = window.go || {};
|
|
||||||
window.go.main = {
|
|
||||||
GreetService: {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GreetService.ArrayInt
|
* GreetService.ArrayInt
|
||||||
@ -354,5 +351,5 @@ window.go.main = {
|
|||||||
* @returns {Promise<number | null>}
|
* @returns {Promise<number | null>}
|
||||||
**/
|
**/
|
||||||
UIntPointerInAndOutput: function(_in) { return wails.CallByID(1367187362, ...Array.prototype.slice.call(arguments, 0)); },
|
UIntPointerInAndOutput: function(_in) { return wails.CallByID(1367187362, ...Array.prototype.slice.call(arguments, 0)); },
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,61 +4,56 @@
|
|||||||
|
|
||||||
export namespace main {
|
export namespace main {
|
||||||
|
|
||||||
|
|
||||||
export class Person {
|
export class Person {
|
||||||
name: string;
|
name: string;
|
||||||
parent: Person;
|
parent: Person;
|
||||||
details: anon1;
|
details: anon1;
|
||||||
|
|
||||||
static createFrom(source: any = {}) {
|
constructor(source: Partial<Person> = {}) {
|
||||||
return new Person(source);
|
const { name = "", parent = null, details = null } = source;
|
||||||
|
this.name = name;
|
||||||
|
this.parent = parent;
|
||||||
|
this.details = details;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(source: any = {}) {
|
static createFrom(source: string | object = {}): Person {
|
||||||
if ('string' === typeof source) {
|
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
|
||||||
source = JSON.parse(source);
|
return new Person(parsedSource as Partial<Person>);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.name = source['name'];
|
|
||||||
this.parent = Person.createFrom(source['parent']);
|
|
||||||
this.details = anon1.createFrom(source['details']);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class anon1 {
|
export class anon1 {
|
||||||
age: number;
|
age: number;
|
||||||
address: anon2;
|
address: anon2;
|
||||||
|
|
||||||
static createFrom(source: any = {}) {
|
constructor(source: Partial<anon1> = {}) {
|
||||||
return new anon1(source);
|
const { age = 0, address = null } = source;
|
||||||
|
this.age = age;
|
||||||
|
this.address = address;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(source: any = {}) {
|
static createFrom(source: string | object = {}): anon1 {
|
||||||
if ('string' === typeof source) {
|
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
|
||||||
source = JSON.parse(source);
|
return new anon1(parsedSource as Partial<anon1>);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.age = source['age'];
|
|
||||||
this.address = anon2.createFrom(source['address']);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class anon2 {
|
export class anon2 {
|
||||||
street: string;
|
street: string;
|
||||||
|
|
||||||
static createFrom(source: any = {}) {
|
constructor(source: Partial<anon2> = {}) {
|
||||||
return new anon2(source);
|
const { street = "" } = source;
|
||||||
|
this.street = street;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(source: any = {}) {
|
static createFrom(source: string | object = {}): anon2 {
|
||||||
if ('string' === typeof source) {
|
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
|
||||||
source = JSON.parse(source);
|
return new anon2(parsedSource as Partial<anon2>);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.street = source['street'];
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -2,10 +2,7 @@
|
|||||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
// This file is automatically generated. DO NOT EDIT
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
export const GreetService = {
|
||||||
window.go = window.go || {};
|
|
||||||
window.go.main = {
|
|
||||||
GreetService: {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GreetService.Greet
|
* GreetService.Greet
|
||||||
@ -14,5 +11,5 @@ window.go.main = {
|
|||||||
* @returns {Promise<string>}
|
* @returns {Promise<string>}
|
||||||
**/
|
**/
|
||||||
Greet: function(name) { return wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); },
|
Greet: function(name) { return wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); },
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2,10 +2,7 @@
|
|||||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||||
// This file is automatically generated. DO NOT EDIT
|
// This file is automatically generated. DO NOT EDIT
|
||||||
|
|
||||||
|
export const GreetService = {
|
||||||
window.go = window.go || {};
|
|
||||||
window.go.main = {
|
|
||||||
GreetService: {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GreetService.Greet
|
* GreetService.Greet
|
||||||
@ -14,5 +11,5 @@ window.go.main = {
|
|||||||
* @returns {Promise<string>}
|
* @returns {Promise<string>}
|
||||||
**/
|
**/
|
||||||
Greet: function(name) { return wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); },
|
Greet: function(name) { return wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); },
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,10 +6,7 @@
|
|||||||
* @typedef {import('./models').main.Person} mainPerson
|
* @typedef {import('./models').main.Person} mainPerson
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
export const GreetService = {
|
||||||
window.go = window.go || {};
|
|
||||||
window.go.main = {
|
|
||||||
GreetService: {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GreetService.Greet
|
* GreetService.Greet
|
||||||
@ -26,5 +23,5 @@ window.go.main = {
|
|||||||
* @returns {Promise<mainPerson>}
|
* @returns {Promise<mainPerson>}
|
||||||
**/
|
**/
|
||||||
NewPerson: function(name) { return wails.CallByID(1661412647, ...Array.prototype.slice.call(arguments, 0)); },
|
NewPerson: function(name) { return wails.CallByID(1661412647, ...Array.prototype.slice.call(arguments, 0)); },
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -6,10 +6,7 @@
|
|||||||
* @typedef {import('./models').services.Address} servicesAddress
|
* @typedef {import('./models').services.Address} servicesAddress
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
export const OtherService = {
|
||||||
window.go = window.go || {};
|
|
||||||
window.go.services = {
|
|
||||||
OtherService: {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OtherService.Yay
|
* OtherService.Yay
|
||||||
@ -18,5 +15,5 @@ window.go.services = {
|
|||||||
* @returns {Promise<servicesAddress>}
|
* @returns {Promise<servicesAddress>}
|
||||||
**/
|
**/
|
||||||
Yay: function() { return wails.CallByID(302702907, ...Array.prototype.slice.call(arguments, 0)); },
|
Yay: function() { return wails.CallByID(302702907, ...Array.prototype.slice.call(arguments, 0)); },
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4,48 +4,45 @@
|
|||||||
|
|
||||||
export namespace main {
|
export namespace main {
|
||||||
|
|
||||||
|
|
||||||
export class Person {
|
export class Person {
|
||||||
name: string;
|
name: string;
|
||||||
address: services.Address;
|
address: services.Address;
|
||||||
|
|
||||||
static createFrom(source: any = {}) {
|
constructor(source: Partial<Person> = {}) {
|
||||||
return new Person(source);
|
const { name = "", address = null } = source;
|
||||||
|
this.name = name;
|
||||||
|
this.address = address;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(source: any = {}) {
|
static createFrom(source: string | object = {}): Person {
|
||||||
if ('string' === typeof source) {
|
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
|
||||||
source = JSON.parse(source);
|
return new Person(parsedSource as Partial<Person>);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.name = source['name'];
|
|
||||||
this.address = services.Address.createFrom(source['address']);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export namespace services {
|
export namespace services {
|
||||||
|
|
||||||
|
|
||||||
export class Address {
|
export class Address {
|
||||||
street: string;
|
street: string;
|
||||||
state: string;
|
state: string;
|
||||||
country: string;
|
country: string;
|
||||||
|
|
||||||
static createFrom(source: any = {}) {
|
constructor(source: Partial<Address> = {}) {
|
||||||
return new Address(source);
|
const { street = "", state = "", country = "" } = source;
|
||||||
|
this.street = street;
|
||||||
|
this.state = state;
|
||||||
|
this.country = country;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(source: any = {}) {
|
static createFrom(source: string | object = {}): Address {
|
||||||
if ('string' === typeof source) {
|
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
|
||||||
source = JSON.parse(source);
|
return new Address(parsedSource as Partial<Address>);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.street = source['street'];
|
|
||||||
this.state = source['state'];
|
|
||||||
this.country = source['country'];
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -412,8 +412,8 @@ tasks:
|
|||||||
dev:
|
dev:
|
||||||
summary: Runs the application in development mode
|
summary: Runs the application in development mode
|
||||||
preconditions:
|
preconditions:
|
||||||
- sh: wails3 tool checkport -u {{ "\"$WAILS_DEVSERVER_URL\"" }}
|
- sh: wails3 tool checkport -u {{ "\"$FRONTEND_DEVSERVER_URL\"" }}
|
||||||
msg: "Looks like the devserver isn't available. Please ensure you have run `wails3 task dev:frontend` in another terminal."
|
msg: 'Cannot connect to frontend dev server ({{ "$FRONTEND_DEVSERVER_URL" }}). Please ensure you have run `wails3 dev:frontend` in another terminal.'
|
||||||
cmds:
|
cmds:
|
||||||
- wails3 tool watcher -path {{ "{{.PATH}}" }} -preexec {{ "\"{{.PREEXEC}}\""}} {{ "{{.PREWAIT}}" }} -postexec {{ "\"{{.POSTEXEC}}\"" }} -ignorefiles {{ "{{.IGNOREFILES}}" }} -ignoredirs {{ "{{.IGNOREDIRS}}" }} -ignoreextensions {{ "{{.IGNOREEXTENSIONS}}" }} -exec {{ "\"{{.EXEC}}\"" }} -debounce {{ "{{.DEBOUNCE}}" }}
|
- wails3 tool watcher -path {{ "{{.PATH}}" }} -preexec {{ "\"{{.PREEXEC}}\""}} {{ "{{.PREWAIT}}" }} -postexec {{ "\"{{.POSTEXEC}}\"" }} -ignorefiles {{ "{{.IGNOREFILES}}" }} -ignoredirs {{ "{{.IGNOREDIRS}}" }} -ignoreextensions {{ "{{.IGNOREEXTENSIONS}}" }} -exec {{ "\"{{.EXEC}}\"" }} -debounce {{ "{{.DEBOUNCE}}" }}
|
||||||
vars:
|
vars:
|
||||||
@ -423,12 +423,12 @@ tasks:
|
|||||||
EXEC: 'wails3 task run'
|
EXEC: 'wails3 task run'
|
||||||
POSTEXEC: ''
|
POSTEXEC: ''
|
||||||
IGNOREFILES: 'Taskfile.yml'
|
IGNOREFILES: 'Taskfile.yml'
|
||||||
IGNOREDIRS: '.git,frontend'
|
IGNOREDIRS: '.git,frontend,.idea,.vscode,bin'
|
||||||
IGNOREEXTENSIONS: '.exe,.syso'
|
IGNOREEXTENSIONS: '.exe,.syso'
|
||||||
DEBOUNCE: 1000
|
DEBOUNCE: 1000
|
||||||
env:
|
env:
|
||||||
# This is the default vite dev server port
|
# This is the default vite dev server port
|
||||||
WAILS_DEVSERVER_URL: 'http://localhost:5173'
|
FRONTEND_DEVSERVER_URL: 'http://localhost:5173'
|
||||||
|
|
||||||
dev:reload:
|
dev:reload:
|
||||||
summary: Reloads the application
|
summary: Reloads the application
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
package templates
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/wailsapp/wails/v3/internal/flags"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestInstall(t *testing.T) {
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
options *flags.Init
|
|
||||||
wantErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "should install template",
|
|
||||||
options: &flags.Init{
|
|
||||||
ProjectName: "test",
|
|
||||||
TemplateName: "svelte",
|
|
||||||
Quiet: false,
|
|
||||||
},
|
|
||||||
wantErr: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
// Remove test directory if it exists
|
|
||||||
if _, err := os.Stat(tt.options.ProjectName); err == nil {
|
|
||||||
_ = os.RemoveAll(tt.options.ProjectName)
|
|
||||||
}
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
if err := Install(tt.options); (err != nil) != tt.wantErr {
|
|
||||||
t.Errorf("Install() error = %v, wantErr %v", err, tt.wantErr)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
t.Cleanup(func() {
|
|
||||||
path, _ := os.Getwd()
|
|
||||||
_ = os.RemoveAll(filepath.Join(path, "..", tt.options.ProjectName))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user