5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-19 02:19:31 +08:00

Support bindings, model & enum generation

This commit is contained in:
Lea Anthony 2023-12-12 21:51:40 +11:00
parent 43c4966873
commit 4b04c10f14
No known key found for this signature in database
GPG Key ID: 33DAF7BB90A58405
44 changed files with 3910 additions and 3126 deletions

View File

@ -1,15 +1,10 @@
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 {
Silent bool `name:"silent" description:"Silent mode"`
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)
func GenerateBindings(options *flags.GenerateBindingsOptions) error {
return parser.GenerateBindingsAndModels(options)
}

View 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"`
}

View File

@ -58,6 +58,9 @@ This package contains the static analyser used for parsing Wails projects so tha
- [ ] Maps
- [x] Structs
- [ ] Generation of bindings
- [ ] Classes
- [ ] Interfaces
- [ ] Enums
## Limitations

View File

@ -19,12 +19,18 @@ const bindingTemplate = `
/**
* {{structName}}.{{methodName}}
*Comments
* @param name {string}
* @param names {string}
* @returns {Promise<string>}
**/
{{methodName}}: function({{inputs}}) { return wails.CallByID({{ID}}, ...Array.prototype.slice.call(arguments, 0)); },
`
const enumTemplate = `
export enum {{.EnumName}} {
{{.EnumValues}}
}
`
var reservedWords = []string{
"abstract",
"arguments",
@ -119,18 +125,19 @@ func GenerateBinding(structName string, method *BoundMethod) (string, []string,
pkgName := getPackageName(input)
if pkgName != "" {
models = append(models, pkgName)
if input.Type.IsStruct {
nsStruct := input.NamespacedStructType()
namespacedStructs = append(namespacedStructs, nsStruct)
}
}
params += " * @param " + inputName + " {" + input.JSType() + "}\n"
if input.Type.IsStruct || input.Type.IsEnum {
nsStruct := input.NamespacedStructType()
namespacedStructs = append(namespacedStructs, nsStruct)
}
params += " * @param " + inputName + " {" + input.JSType() + "}\n"
}
params = strings.TrimSuffix(params, "\n")
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
for _, input := range method.Inputs {
pkgName := getPackageName(input)
@ -232,19 +239,8 @@ func GenerateBindings(bindings map[string]map[string][]*BoundMethod) map[string]
packageBindings := bindings[packageName]
structNames := lo.Keys(packageBindings)
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 {
/**
* 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"
result[normalisedPackageNames[packageName]] += "export const " + structName + " = {\n"
methods := packageBindings[structName]
sort.Slice(methods, func(i, j int) bool {
return methods[i].Name < methods[j].Name
@ -255,9 +251,8 @@ window.go = window.go || {};
allModels = append(allModels, models...)
result[normalisedPackageNames[packageName]] += thisBinding
}
result[normalisedPackageNames[packageName]] += " },\n"
result[normalisedPackageNames[packageName]] += "};\n\n"
}
result[normalisedPackageNames[packageName]] += "};\n"
if len(allNamespacedStructs) > 0 {
typedefs := "/**\n"

View File

@ -27,6 +27,12 @@ func TestGenerateBindings(t *testing.T) {
dir string
want map[string]string
}{
{
"testdata/enum",
map[string]string{
"main": getFile("testdata/enum/bindings_main.js"),
},
},
{
"testdata/function_single",
map[string]string{

View File

@ -3,6 +3,7 @@ package parser
import (
"bytes"
"embed"
"github.com/wailsapp/wails/v3/internal/flags"
"io"
"sort"
"strings"
@ -15,16 +16,27 @@ var templates embed.FS
type ModelDefinitions struct {
Package string
Models map[string]*StructDef
Enums map[string]*TypeDef
}
func GenerateModel(wr io.Writer, def *ModelDefinitions) error {
tmpl, err := template.New("model.ts.tmpl").ParseFS(templates, "templates/model.ts.tmpl")
func GenerateModel(wr io.Writer, def *ModelDefinitions, options *flags.GenerateBindingsOptions) error {
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 {
println("Unable to create class template: " + err.Error())
return err
}
err = tmpl.ExecuteTemplate(wr, "model.ts.tmpl", def)
err = tmpl.ExecuteTemplate(wr, templateName, def)
if err != nil {
println("Problem executing template: " + err.Error())
return err
@ -42,7 +54,7 @@ func pkgAlias(fullPkg string) string {
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 {
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)
// and then sort resulting list by the alias
var keys []string
for pkg, _ := range models {
for pkg := range models {
keys = append(keys, pkg)
}
@ -65,120 +77,11 @@ func GenerateModels(models map[packagePath]map[structName]*StructDef) (string, e
err := GenerateModel(&buffer, &ModelDefinitions{
Package: pkgAlias(pkg),
Models: models[pkg],
})
Enums: enums[pkg],
}, options)
if err != nil {
return "", err
}
}
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
//}

View File

@ -2,6 +2,7 @@ package parser
import (
"github.com/google/go-cmp/cmp"
"github.com/wailsapp/wails/v3/internal/flags"
"os"
"path/filepath"
"strings"
@ -15,40 +16,39 @@ func TestGenerateModels(t *testing.T) {
want string
}{
{
"testdata/function_single",
"",
dir: "testdata/function_single",
},
{
"testdata/function_from_imported_package",
getFile("testdata/function_from_imported_package/models.ts"),
dir: "testdata/function_from_imported_package",
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",
getFile("testdata/variable_single_from_other_function/models.ts"),
dir: "testdata/variable_single_from_other_function",
want: getFile("testdata/variable_single_from_other_function/models.ts"),
},
{
"testdata/struct_literal_single",
getFile("testdata/struct_literal_single/models.ts"),
dir: "testdata/struct_literal_single",
want: getFile("testdata/struct_literal_single/models.ts"),
},
{
"testdata/struct_literal_multiple",
"",
dir: "testdata/struct_literal_multiple",
},
{
"testdata/struct_literal_multiple_other",
getFile("testdata/struct_literal_multiple_other/models.ts"),
dir: "testdata/struct_literal_multiple_other",
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 {
@ -60,7 +60,7 @@ func TestGenerateModels(t *testing.T) {
}
// Generate Models
got, err := GenerateModels(project.Models)
got, err := GenerateModels(project.Models, project.Types, &flags.GenerateBindingsOptions{})
if err != nil {
t.Fatalf("GenerateModels() error = %v", err)
}

View File

@ -2,6 +2,7 @@ package parser
import (
"fmt"
"github.com/wailsapp/wails/v3/internal/flags"
"go/ast"
"go/build"
"go/parser"
@ -12,6 +13,7 @@ import (
"reflect"
"strconv"
"strings"
"time"
"github.com/samber/lo"
"github.com/wailsapp/wails/v3/internal/hash"
@ -26,16 +28,39 @@ type StructDef struct {
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 {
Name string
IsStruct bool
IsSlice bool
IsPointer bool
IsEnum bool
MapKey *ParameterType
MapValue *ParameterType
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 {
Name string
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 p.Type.IsStruct {
if p.Type.IsStruct || p.Type.IsEnum {
typeName = p.NamespacedStructType()
typeName = strings.ReplaceAll(typeName, ".", "")
}
@ -117,7 +142,7 @@ func (f *Field) JSName() string {
// via assignment for simple types or constructors for structs
func (f *Field) TSBuild(pkg string) string {
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 {
@ -141,7 +166,8 @@ func (f *Field) JSDef(pkg string) 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)
} else {
parts := strings.Split(f.Type.Package, "/")
@ -155,12 +181,45 @@ func (f *Field) JSDef(pkg string) string {
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 {
Pkg *ast.Package
Name string
Path string
Dir string
StructCache map[structName]*StructDef
TypeCache map[string]*TypeDef
}
type Project struct {
@ -168,7 +227,19 @@ type Project struct {
Path string
BoundMethods map[packagePath]map[structName][]*BoundMethod
Models map[packagePath]map[structName]*StructDef
Types map[packagePath]map[structName]*TypeDef
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) {
@ -176,6 +247,7 @@ func ParseProject(projectPath string) (*Project, error) {
BoundMethods: make(map[packagePath]map[structName][]*BoundMethod),
packageCache: make(map[string]*ParsedPackage),
}
result.Stats.StartTime = time.Now()
pkgs, err := result.parseDirectory(projectPath)
if err != nil {
return nil, err
@ -195,8 +267,8 @@ func ParseProject(projectPath string) (*Project, error) {
return result, nil
}
func GenerateBindingsAndModels(projectDir string, outputDir string) error {
p, err := ParseProject(projectDir)
func GenerateBindingsAndModels(options *flags.GenerateBindingsOptions) error {
p, err := ParseProject(options.ProjectDirectory)
if err != nil {
return err
}
@ -204,37 +276,51 @@ func GenerateBindingsAndModels(projectDir string, outputDir string) error {
if p.BoundMethods == nil {
return nil
}
err = os.MkdirAll(outputDir, 0755)
err = os.MkdirAll(options.OutputDirectory, 0755)
if err != nil {
return err
}
p.Stats.NumMethods = len(p.BoundMethods)
generatedMethods := GenerateBindings(p.BoundMethods)
for pkg, text := range generatedMethods {
// 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 {
return err
}
}
p.Stats.NumModels = len(p.Models)
p.Stats.NumEnums = len(p.Types)
// Generate Models
if len(p.Models) > 0 {
generatedModels, err := GenerateModels(p.Models)
generatedModels, err := GenerateModels(p.Models, p.Types, options)
if err != nil {
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 {
return err
}
}
absPath, err := filepath.Abs(projectDir)
p.Stats.EndTime = time.Now()
absPath, err := filepath.Abs(options.ProjectDirectory)
if err != nil {
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 {
return err
}
@ -243,6 +329,13 @@ func GenerateBindingsAndModels(projectDir string, outputDir string) error {
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) {
if 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
}
var result = make(map[string]*ParsedPackage)
p.Stats.NumPackages = len(pkgs)
for packageName, pkg := range pkgs {
parsedPackage := &ParsedPackage{
Pkg: pkg,
@ -268,6 +362,7 @@ func (p *Project) parseDirectory(dir string) (map[string]*ParsedPackage, error)
Path: packageName,
Dir: getDirectoryForPackage(pkg),
StructCache: make(map[structName]*StructDef),
TypeCache: make(map[string]*TypeDef),
}
p.packageCache[packageName] = parsedPackage
result[packageName] = parsedPackage
@ -285,6 +380,28 @@ func (p *Project) findApplicationNewCalls(pkgs map[string]*ParsedPackage) (err e
for _, file := range thisPackage.Files {
// Use an ast.Inspector to find the calls to application.New
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
callExpr, ok := n.(*ast.CallExpr)
if !ok {
@ -372,6 +489,7 @@ func (p *Project) findApplicationNewCalls(pkgs map[string]*ParsedPackage) (err e
return true
})
}
p.addTypes(pkg.Path, pkg.TypeCache)
if !callFound {
return fmt.Errorf("no Bound structs found")
}
@ -443,7 +561,7 @@ func (p *Project) parseBoundStructMethods(name string, pkg *ParsedPackage) error
method := &BoundMethod{
ID: id,
Name: funcDecl.Name.Name,
DocComment: funcDecl.Doc.Text(),
DocComment: strings.TrimSpace(funcDecl.Doc.Text()),
Alias: alias,
}
@ -464,6 +582,20 @@ func (p *Project) parseBoundStructMethods(name string, pkg *ParsedPackage) error
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 {
var result []*Parameter
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 {
result := &ParameterType{}
result := &ParameterType{
Package: pkg.Path,
}
result.Name = getTypeString(field.Type)
switch t := field.Type.(type) {
case *ast.Ident:
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:
result = p.parseParameterType(&ast.Field{Type: t.X}, pkg)
result.IsPointer = true
@ -597,9 +739,9 @@ func (p *Project) parseStructFields(structType *ast.StructType, pkg *ParsedPacka
if !ok {
p.getStructDef(paramType.Name, pkg)
}
if paramType.Package == "" {
paramType.Package = pkg.Path
}
}
if paramType.Package == "" {
paramType.Package = pkg.Path
}
thisField.Type = paramType
result = append(result, thisField)
@ -822,6 +964,72 @@ func (p *Project) getFunctionFromName(name string, parsedPackage *ParsedPackage)
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 {
switch t := expr.(type) {
case *ast.Ident:
@ -852,7 +1060,10 @@ func isStructType(expr ast.Expr) bool {
case *ast.SliceExpr:
return isStructType(e.X)
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:
return false
}
@ -869,3 +1080,21 @@ func getDirectoryForPackage(pkg *ast.Package) string {
}
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
}

View 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)
}
})
}
}

View 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)
}
})
}
}

View 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)
}
})
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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)
}
})
}
}

View File

@ -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}}
}
}

View 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}}
}

View File

@ -1,21 +1,31 @@
{{$pkg := .Package}}
export namespace {{.Package}} {
{{range $name, $def := .Models}}
export class {{$def.Name}} {
{{range $def.Fields}}{{.JSDef $pkg}}
{{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}}
export class {{$def.Name}} {
{{range $def.Fields}}{{.JSDef $pkg}}
{{end}}
constructor(source: Partial<{{$def.Name}}> = {}) {
const { {{$def.DefaultValueList}} } = source; {{range $def.Fields}}
this.{{.JSName}} = {{.JSName}};{{end}}
}
static createFrom(source: string | object = {}): {{$def.Name}} {
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
return new {{$def.Name}}(parsedSource as Partial<{{$def.Name}}>);
}
}
{{end}}
static createFrom(source: any = {}) {
return new {{$def.Name}}(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) {
source = JSON.parse(source);
}
{{range $def.Fields}}this.{{.JSName}} = {{.TSBuild $pkg}};
{{end}}
}
}
{{end}}
}
}

View 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)); },
};

View 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)
}
}

View 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>);
}
}
}

View 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)); },
},
};

View 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)); },
},
};

View 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)
}
}

View 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>);
}
}
}

View 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"
)

View File

@ -6,15 +6,12 @@
* @typedef {import('./models').main.Person} mainPerson
*/
window.go = window.go || {};
window.go.main = {
GreetService: {
export const GreetService = {
/**
* GreetService.Greet
* Greet does XYZ
* @param name {string}
* @param name {string}
* @returns {Promise<string>}
**/
Greet: function(name) { return wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); },
@ -22,9 +19,9 @@ window.go.main = {
/**
* GreetService.NewPerson
* NewPerson creates a new person
* @param name {string}
* @param name {string}
* @returns {Promise<mainPerson>}
**/
NewPerson: function(name) { return wails.CallByID(1661412647, ...Array.prototype.slice.call(arguments, 0)); },
},
};

View File

@ -6,17 +6,14 @@
* @typedef {import('./models').services.Address} servicesAddress
*/
window.go = window.go || {};
window.go.services = {
OtherService: {
export const OtherService = {
/**
* OtherService.Yay
*
*
*
* @returns {Promise<servicesAddress>}
**/
Yay: function() { return wails.CallByID(302702907, ...Array.prototype.slice.call(arguments, 0)); },
},
};

View File

@ -3,49 +3,46 @@
// This file is automatically generated. DO NOT EDIT
export namespace main {
export class Person {
name: string;
address: services.Address;
static createFrom(source: any = {}) {
return new Person(source);
}
export class Person {
name: string;
address: services.Address;
constructor(source: Partial<Person> = {}) {
const { name = "", address = null } = source;
this.name = name;
this.address = address;
}
constructor(source: any = {}) {
if ('string' === typeof source) {
source = JSON.parse(source);
}
static createFrom(source: string | object = {}): Person {
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
return new Person(parsedSource as Partial<Person>);
}
this.name = source['name'];
this.address = services.Address.createFrom(source['address']);
}
}
}
export namespace services {
export class Address {
street: string;
state: string;
country: string;
static createFrom(source: any = {}) {
return new Address(source);
}
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;
}
constructor(source: any = {}) {
if ('string' === typeof source) {
source = JSON.parse(source);
}
static createFrom(source: string | object = {}): Address {
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
return new Address(parsedSource as Partial<Address>);
}
this.street = source['street'];
this.state = source['state'];
this.country = source['country'];
}
}
}
}

View File

@ -2,17 +2,14 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
window.go = window.go || {};
window.go.main = {
GreetService: {
export const GreetService = {
/**
* GreetService.Greet
* Greet someone
* @param name {string}
* @param name {string}
* @returns {Promise<string>}
**/
Greet: function(name) { return wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); },
},
};

View File

@ -2,27 +2,25 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
window.go = window.go || {};
window.go.main = {
GreetService: {
export const GreetService = {
/**
* GreetService.Greet
*
* @param name {string}
* @param name {string}
* @returns {Promise<string>}
**/
Greet: function(name) { return wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); },
},
OtherService: {
};
export const OtherService = {
/**
* OtherService.Hello
*
*
*
* @returns {Promise<void>}
**/
Hello: function() { return wails.CallByID(4249972365, ...Array.prototype.slice.call(arguments, 0)); },
},
};

View File

@ -2,27 +2,25 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
window.go = window.go || {};
window.go.main = {
GreetService: {
export const GreetService = {
/**
* GreetService.Greet
*
* @param name {string}
* @param name {string}
* @returns {Promise<string>}
**/
Greet: function(name) { return wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); },
},
OtherService: {
};
export const OtherService = {
/**
* OtherService.Hello
*
*
*
* @returns {Promise<void>}
**/
Hello: function() { return wails.CallByID(4249972365, ...Array.prototype.slice.call(arguments, 0)); },
},
};

View File

@ -6,15 +6,12 @@
* @typedef {import('./models').main.Person} mainPerson
*/
window.go = window.go || {};
window.go.main = {
GreetService: {
export const GreetService = {
/**
* GreetService.Greet
* Greet does XYZ
* @param name {string}
* @param name {string}
* @returns {Promise<string>}
**/
Greet: function(name) { return wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); },
@ -22,9 +19,9 @@ window.go.main = {
/**
* GreetService.NewPerson
* NewPerson creates a new person
* @param name {string}
* @param name {string}
* @returns {Promise<mainPerson>}
**/
NewPerson: function(name) { return wails.CallByID(1661412647, ...Array.prototype.slice.call(arguments, 0)); },
},
};

View File

@ -6,17 +6,14 @@
* @typedef {import('./models').services.Address} servicesAddress
*/
window.go = window.go || {};
window.go.services = {
OtherService: {
export const OtherService = {
/**
* OtherService.Yay
*
*
*
* @returns {Promise<servicesAddress>}
**/
Yay: function() { return wails.CallByID(469445984, ...Array.prototype.slice.call(arguments, 0)); },
},
};

View File

@ -3,49 +3,46 @@
// This file is automatically generated. DO NOT EDIT
export namespace main {
export class Person {
name: string;
address: services.Address;
static createFrom(source: any = {}) {
return new Person(source);
}
export class Person {
name: string;
address: services.Address;
constructor(source: Partial<Person> = {}) {
const { name = "", address = null } = source;
this.name = name;
this.address = address;
}
constructor(source: any = {}) {
if ('string' === typeof source) {
source = JSON.parse(source);
}
static createFrom(source: string | object = {}): Person {
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
return new Person(parsedSource as Partial<Person>);
}
this.name = source['name'];
this.address = services.Address.createFrom(source['address']);
}
}
}
export namespace services {
export class Address {
street: string;
state: string;
country: string;
static createFrom(source: any = {}) {
return new Address(source);
}
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;
}
constructor(source: any = {}) {
if ('string' === typeof source) {
source = JSON.parse(source);
}
static createFrom(source: string | object = {}): Address {
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
return new Address(parsedSource as Partial<Address>);
}
this.street = source['street'];
this.state = source['state'];
this.country = source['country'];
}
}
}
}

View File

@ -6,15 +6,12 @@
* @typedef {import('./models').main.Person} mainPerson
*/
window.go = window.go || {};
window.go.main = {
GreetService: {
export const GreetService = {
/**
* GreetService.ArrayInt
*
* @param _in {number[]}
* @param _in {number[]}
* @returns {Promise<void>}
**/
ArrayInt: function(_in) { return wails.CallByID(3862002418, ...Array.prototype.slice.call(arguments, 0)); },
@ -22,7 +19,7 @@ window.go.main = {
/**
* GreetService.BoolInBoolOut
*
* @param _in {boolean}
* @param _in {boolean}
* @returns {Promise<boolean>}
**/
BoolInBoolOut: function(_in) { return wails.CallByID(2424639793, ...Array.prototype.slice.call(arguments, 0)); },
@ -30,7 +27,7 @@ window.go.main = {
/**
* GreetService.Float32InFloat32Out
*
* @param _in {number}
* @param _in {number}
* @returns {Promise<number>}
**/
Float32InFloat32Out: function(_in) { return wails.CallByID(3132595881, ...Array.prototype.slice.call(arguments, 0)); },
@ -38,7 +35,7 @@ window.go.main = {
/**
* GreetService.Float64InFloat64Out
*
* @param _in {number}
* @param _in {number}
* @returns {Promise<number>}
**/
Float64InFloat64Out: function(_in) { return wails.CallByID(2182412247, ...Array.prototype.slice.call(arguments, 0)); },
@ -46,7 +43,7 @@ window.go.main = {
/**
* GreetService.Greet
* Greet someone
* @param name {string}
* @param name {string}
* @returns {Promise<string>}
**/
Greet: function(name) { return wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); },
@ -54,7 +51,7 @@ window.go.main = {
/**
* GreetService.Int16InIntOut
*
* @param _in {number}
* @param _in {number}
* @returns {Promise<number>}
**/
Int16InIntOut: function(_in) { return wails.CallByID(3306292566, ...Array.prototype.slice.call(arguments, 0)); },
@ -62,7 +59,7 @@ window.go.main = {
/**
* GreetService.Int16PointerInAndOutput
*
* @param _in {number | null}
* @param _in {number | null}
* @returns {Promise<number | null>}
**/
Int16PointerInAndOutput: function(_in) { return wails.CallByID(1754277916, ...Array.prototype.slice.call(arguments, 0)); },
@ -70,7 +67,7 @@ window.go.main = {
/**
* GreetService.Int32InIntOut
*
* @param _in {number}
* @param _in {number}
* @returns {Promise<number>}
**/
Int32InIntOut: function(_in) { return wails.CallByID(1909469092, ...Array.prototype.slice.call(arguments, 0)); },
@ -78,7 +75,7 @@ window.go.main = {
/**
* GreetService.Int32PointerInAndOutput
*
* @param _in {number | null}
* @param _in {number | null}
* @returns {Promise<number | null>}
**/
Int32PointerInAndOutput: function(_in) { return wails.CallByID(4251088558, ...Array.prototype.slice.call(arguments, 0)); },
@ -86,7 +83,7 @@ window.go.main = {
/**
* GreetService.Int64InIntOut
*
* @param _in {number}
* @param _in {number}
* @returns {Promise<number>}
**/
Int64InIntOut: function(_in) { return wails.CallByID(1343888303, ...Array.prototype.slice.call(arguments, 0)); },
@ -94,7 +91,7 @@ window.go.main = {
/**
* GreetService.Int64PointerInAndOutput
*
* @param _in {number | null}
* @param _in {number | null}
* @returns {Promise<number | null>}
**/
Int64PointerInAndOutput: function(_in) { return wails.CallByID(2205561041, ...Array.prototype.slice.call(arguments, 0)); },
@ -102,7 +99,7 @@ window.go.main = {
/**
* GreetService.Int8InIntOut
*
* @param _in {number}
* @param _in {number}
* @returns {Promise<number>}
**/
Int8InIntOut: function(_in) { return wails.CallByID(572240879, ...Array.prototype.slice.call(arguments, 0)); },
@ -110,7 +107,7 @@ window.go.main = {
/**
* GreetService.Int8PointerInAndOutput
*
* @param _in {number | null}
* @param _in {number | null}
* @returns {Promise<number | null>}
**/
Int8PointerInAndOutput: function(_in) { return wails.CallByID(2189402897, ...Array.prototype.slice.call(arguments, 0)); },
@ -118,7 +115,7 @@ window.go.main = {
/**
* GreetService.IntInIntOut
*
* @param _in {number}
* @param _in {number}
* @returns {Promise<number>}
**/
IntInIntOut: function(_in) { return wails.CallByID(642881729, ...Array.prototype.slice.call(arguments, 0)); },
@ -126,7 +123,7 @@ window.go.main = {
/**
* GreetService.IntPointerInAndOutput
*
* @param _in {number | null}
* @param _in {number | null}
* @returns {Promise<number | null>}
**/
IntPointerInAndOutput: function(_in) { return wails.CallByID(1066151743, ...Array.prototype.slice.call(arguments, 0)); },
@ -134,7 +131,7 @@ window.go.main = {
/**
* GreetService.IntPointerInputNamedOutputs
*
* @param _in {number | null}
* @param _in {number | null}
* @returns {Promise<number | null, void>}
**/
IntPointerInputNamedOutputs: function(_in) { return wails.CallByID(2718999663, ...Array.prototype.slice.call(arguments, 0)); },
@ -142,7 +139,7 @@ window.go.main = {
/**
* GreetService.MapIntInt
*
* @param _in {map}
* @param _in {map}
* @returns {Promise<void>}
**/
MapIntInt: function(_in) { return wails.CallByID(2386486356, ...Array.prototype.slice.call(arguments, 0)); },
@ -150,7 +147,7 @@ window.go.main = {
/**
* GreetService.MapIntPointerInt
*
* @param _in {map}
* @param _in {map}
* @returns {Promise<void>}
**/
MapIntPointerInt: function(_in) { return wails.CallByID(550413585, ...Array.prototype.slice.call(arguments, 0)); },
@ -158,7 +155,7 @@ window.go.main = {
/**
* GreetService.MapIntSliceInt
*
* @param _in {map}
* @param _in {map}
* @returns {Promise<void>}
**/
MapIntSliceInt: function(_in) { return wails.CallByID(2900172572, ...Array.prototype.slice.call(arguments, 0)); },
@ -166,7 +163,7 @@ window.go.main = {
/**
* GreetService.MapIntSliceIntInMapIntSliceIntOut
*
* @param _in {map}
* @param _in {map}
* @returns {Promise<map>}
**/
MapIntSliceIntInMapIntSliceIntOut: function(_in) { return wails.CallByID(881980169, ...Array.prototype.slice.call(arguments, 0)); },
@ -174,7 +171,7 @@ window.go.main = {
/**
* GreetService.NoInputsStringOut
*
*
*
* @returns {Promise<string>}
**/
NoInputsStringOut: function() { return wails.CallByID(1075577233, ...Array.prototype.slice.call(arguments, 0)); },
@ -182,7 +179,7 @@ window.go.main = {
/**
* GreetService.PointerBoolInBoolOut
*
* @param _in {boolean | null}
* @param _in {boolean | null}
* @returns {Promise<boolean | null>}
**/
PointerBoolInBoolOut: function(_in) { return wails.CallByID(3589606958, ...Array.prototype.slice.call(arguments, 0)); },
@ -190,7 +187,7 @@ window.go.main = {
/**
* GreetService.PointerFloat32InFloat32Out
*
* @param _in {number | null}
* @param _in {number | null}
* @returns {Promise<number | null>}
**/
PointerFloat32InFloat32Out: function(_in) { return wails.CallByID(224675106, ...Array.prototype.slice.call(arguments, 0)); },
@ -198,7 +195,7 @@ window.go.main = {
/**
* GreetService.PointerFloat64InFloat64Out
*
* @param _in {number | null}
* @param _in {number | null}
* @returns {Promise<number | null>}
**/
PointerFloat64InFloat64Out: function(_in) { return wails.CallByID(2124953624, ...Array.prototype.slice.call(arguments, 0)); },
@ -206,7 +203,7 @@ window.go.main = {
/**
* GreetService.PointerMapIntInt
*
* @param _in {map | null}
* @param _in {map | null}
* @returns {Promise<void>}
**/
PointerMapIntInt: function(_in) { return wails.CallByID(3516977899, ...Array.prototype.slice.call(arguments, 0)); },
@ -214,7 +211,7 @@ window.go.main = {
/**
* GreetService.PointerStringInStringOut
*
* @param _in {string | null}
* @param _in {string | null}
* @returns {Promise<string | null>}
**/
PointerStringInStringOut: function(_in) { return wails.CallByID(229603958, ...Array.prototype.slice.call(arguments, 0)); },
@ -222,7 +219,7 @@ window.go.main = {
/**
* GreetService.StringArrayInputNamedOutput
*
* @param _in {string[]}
* @param _in {string[]}
* @returns {Promise<string[]>}
**/
StringArrayInputNamedOutput: function(_in) { return wails.CallByID(3678582682, ...Array.prototype.slice.call(arguments, 0)); },
@ -230,7 +227,7 @@ window.go.main = {
/**
* GreetService.StringArrayInputNamedOutputs
*
* @param _in {string[]}
* @param _in {string[]}
* @returns {Promise<string[], void>}
**/
StringArrayInputNamedOutputs: function(_in) { return wails.CallByID(319259595, ...Array.prototype.slice.call(arguments, 0)); },
@ -238,7 +235,7 @@ window.go.main = {
/**
* GreetService.StringArrayInputStringArrayOut
*
* @param _in {string[]}
* @param _in {string[]}
* @returns {Promise<string[]>}
**/
StringArrayInputStringArrayOut: function(_in) { return wails.CallByID(383995060, ...Array.prototype.slice.call(arguments, 0)); },
@ -246,7 +243,7 @@ window.go.main = {
/**
* GreetService.StringArrayInputStringOut
*
* @param _in {string[]}
* @param _in {string[]}
* @returns {Promise<string>}
**/
StringArrayInputStringOut: function(_in) { return wails.CallByID(1091960237, ...Array.prototype.slice.call(arguments, 0)); },
@ -254,7 +251,7 @@ window.go.main = {
/**
* GreetService.StructInputStructOutput
*
* @param _in {mainPerson}
* @param _in {mainPerson}
* @returns {Promise<mainPerson>}
**/
StructInputStructOutput: function(_in) { return wails.CallByID(3835643147, ...Array.prototype.slice.call(arguments, 0)); },
@ -262,7 +259,7 @@ window.go.main = {
/**
* GreetService.StructPointerInputErrorOutput
*
* @param _in {mainPerson | null}
* @param _in {mainPerson | null}
* @returns {Promise<void>}
**/
StructPointerInputErrorOutput: function(_in) { return wails.CallByID(2447692557, ...Array.prototype.slice.call(arguments, 0)); },
@ -270,7 +267,7 @@ window.go.main = {
/**
* GreetService.StructPointerInputStructPointerOutput
*
* @param _in {mainPerson | null}
* @param _in {mainPerson | null}
* @returns {Promise<mainPerson>}
**/
StructPointerInputStructPointerOutput: function(_in) { return wails.CallByID(2943477349, ...Array.prototype.slice.call(arguments, 0)); },
@ -278,7 +275,7 @@ window.go.main = {
/**
* GreetService.UInt16InUIntOut
*
* @param _in {number}
* @param _in {number}
* @returns {Promise<number>}
**/
UInt16InUIntOut: function(_in) { return wails.CallByID(3401034892, ...Array.prototype.slice.call(arguments, 0)); },
@ -286,7 +283,7 @@ window.go.main = {
/**
* GreetService.UInt16PointerInAndOutput
*
* @param _in {number | null}
* @param _in {number | null}
* @returns {Promise<number | null>}
**/
UInt16PointerInAndOutput: function(_in) { return wails.CallByID(1236957573, ...Array.prototype.slice.call(arguments, 0)); },
@ -294,7 +291,7 @@ window.go.main = {
/**
* GreetService.UInt32InUIntOut
*
* @param _in {number}
* @param _in {number}
* @returns {Promise<number>}
**/
UInt32InUIntOut: function(_in) { return wails.CallByID(1160383782, ...Array.prototype.slice.call(arguments, 0)); },
@ -302,7 +299,7 @@ window.go.main = {
/**
* GreetService.UInt32PointerInAndOutput
*
* @param _in {number | null}
* @param _in {number | null}
* @returns {Promise<number | null>}
**/
UInt32PointerInAndOutput: function(_in) { return wails.CallByID(1739300671, ...Array.prototype.slice.call(arguments, 0)); },
@ -310,7 +307,7 @@ window.go.main = {
/**
* GreetService.UInt64InUIntOut
*
* @param _in {number}
* @param _in {number}
* @returns {Promise<number>}
**/
UInt64InUIntOut: function(_in) { return wails.CallByID(793803239, ...Array.prototype.slice.call(arguments, 0)); },
@ -318,7 +315,7 @@ window.go.main = {
/**
* GreetService.UInt64PointerInAndOutput
*
* @param _in {number | null}
* @param _in {number | null}
* @returns {Promise<number | null>}
**/
UInt64PointerInAndOutput: function(_in) { return wails.CallByID(1403757716, ...Array.prototype.slice.call(arguments, 0)); },
@ -326,7 +323,7 @@ window.go.main = {
/**
* GreetService.UInt8InUIntOut
*
* @param _in {number}
* @param _in {number}
* @returns {Promise<number>}
**/
UInt8InUIntOut: function(_in) { return wails.CallByID(2988345717, ...Array.prototype.slice.call(arguments, 0)); },
@ -334,7 +331,7 @@ window.go.main = {
/**
* GreetService.UInt8PointerInAndOutput
*
* @param _in {number | null}
* @param _in {number | null}
* @returns {Promise<number | null>}
**/
UInt8PointerInAndOutput: function(_in) { return wails.CallByID(518250834, ...Array.prototype.slice.call(arguments, 0)); },
@ -342,7 +339,7 @@ window.go.main = {
/**
* GreetService.UIntInUIntOut
*
* @param _in {number}
* @param _in {number}
* @returns {Promise<number>}
**/
UIntInUIntOut: function(_in) { return wails.CallByID(2836661285, ...Array.prototype.slice.call(arguments, 0)); },
@ -350,9 +347,9 @@ window.go.main = {
/**
* GreetService.UIntPointerInAndOutput
*
* @param _in {number | null}
* @param _in {number | null}
* @returns {Promise<number | null>}
**/
UIntPointerInAndOutput: function(_in) { return wails.CallByID(1367187362, ...Array.prototype.slice.call(arguments, 0)); },
},
};

View File

@ -3,62 +3,57 @@
// This file is automatically generated. DO NOT EDIT
export namespace main {
export class Person {
name: string;
parent: Person;
details: anon1;
static createFrom(source: any = {}) {
return new Person(source);
}
constructor(source: any = {}) {
if ('string' === typeof source) {
source = JSON.parse(source);
}
this.name = source['name'];
this.parent = Person.createFrom(source['parent']);
this.details = anon1.createFrom(source['details']);
}
}
export class anon1 {
age: number;
address: anon2;
static createFrom(source: any = {}) {
return new anon1(source);
}
export class Person {
name: string;
parent: Person;
details: anon1;
constructor(source: Partial<Person> = {}) {
const { name = "", parent = null, details = null } = source;
this.name = name;
this.parent = parent;
this.details = details;
}
constructor(source: any = {}) {
if ('string' === typeof source) {
source = JSON.parse(source);
}
static createFrom(source: string | object = {}): Person {
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
return new Person(parsedSource as Partial<Person>);
}
this.age = source['age'];
this.address = anon2.createFrom(source['address']);
}
}
export class anon2 {
street: string;
static createFrom(source: any = {}) {
return new anon2(source);
}
export class anon1 {
age: number;
address: anon2;
constructor(source: Partial<anon1> = {}) {
const { age = 0, address = null } = source;
this.age = age;
this.address = address;
}
constructor(source: any = {}) {
if ('string' === typeof source) {
source = JSON.parse(source);
}
static createFrom(source: string | object = {}): anon1 {
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
return new anon1(parsedSource as Partial<anon1>);
}
this.street = source['street'];
}
}
}
export class anon2 {
street: string;
constructor(source: Partial<anon2> = {}) {
const { street = "" } = source;
this.street = street;
}
static createFrom(source: string | object = {}): anon2 {
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
return new anon2(parsedSource as Partial<anon2>);
}
}
}

View File

@ -2,17 +2,14 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
window.go = window.go || {};
window.go.main = {
GreetService: {
export const GreetService = {
/**
* GreetService.Greet
* Greet someone
* @param name {string}
* @param name {string}
* @returns {Promise<string>}
**/
Greet: function(name) { return wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); },
},
};

View File

@ -2,17 +2,14 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
window.go = window.go || {};
window.go.main = {
GreetService: {
export const GreetService = {
/**
* GreetService.Greet
* Greet someone
* @param name {string}
* @param name {string}
* @returns {Promise<string>}
**/
Greet: function(name) { return wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); },
},
};

View File

@ -6,15 +6,12 @@
* @typedef {import('./models').main.Person} mainPerson
*/
window.go = window.go || {};
window.go.main = {
GreetService: {
export const GreetService = {
/**
* GreetService.Greet
* Greet does XYZ
* @param name {string}
* @param name {string}
* @returns {Promise<string>}
**/
Greet: function(name) { return wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); },
@ -22,9 +19,9 @@ window.go.main = {
/**
* GreetService.NewPerson
* NewPerson creates a new person
* @param name {string}
* @param name {string}
* @returns {Promise<mainPerson>}
**/
NewPerson: function(name) { return wails.CallByID(1661412647, ...Array.prototype.slice.call(arguments, 0)); },
},
};

View File

@ -6,17 +6,14 @@
* @typedef {import('./models').services.Address} servicesAddress
*/
window.go = window.go || {};
window.go.services = {
OtherService: {
export const OtherService = {
/**
* OtherService.Yay
*
*
*
* @returns {Promise<servicesAddress>}
**/
Yay: function() { return wails.CallByID(302702907, ...Array.prototype.slice.call(arguments, 0)); },
},
};

View File

@ -3,49 +3,46 @@
// This file is automatically generated. DO NOT EDIT
export namespace main {
export class Person {
name: string;
address: services.Address;
static createFrom(source: any = {}) {
return new Person(source);
}
export class Person {
name: string;
address: services.Address;
constructor(source: Partial<Person> = {}) {
const { name = "", address = null } = source;
this.name = name;
this.address = address;
}
constructor(source: any = {}) {
if ('string' === typeof source) {
source = JSON.parse(source);
}
static createFrom(source: string | object = {}): Person {
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
return new Person(parsedSource as Partial<Person>);
}
this.name = source['name'];
this.address = services.Address.createFrom(source['address']);
}
}
}
export namespace services {
export class Address {
street: string;
state: string;
country: string;
static createFrom(source: any = {}) {
return new Address(source);
}
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;
}
constructor(source: any = {}) {
if ('string' === typeof source) {
source = JSON.parse(source);
}
static createFrom(source: string | object = {}): Address {
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
return new Address(parsedSource as Partial<Address>);
}
this.street = source['street'];
this.state = source['state'];
this.country = source['country'];
}
}
}
}

View File

@ -412,8 +412,8 @@ tasks:
dev:
summary: Runs the application in development mode
preconditions:
- sh: wails3 tool checkport -u {{ "\"$WAILS_DEVSERVER_URL\"" }}
msg: "Looks like the devserver isn't available. Please ensure you have run `wails3 task dev:frontend` in another terminal."
- sh: wails3 tool checkport -u {{ "\"$FRONTEND_DEVSERVER_URL\"" }}
msg: 'Cannot connect to frontend dev server ({{ "$FRONTEND_DEVSERVER_URL" }}). Please ensure you have run `wails3 dev:frontend` in another terminal.'
cmds:
- wails3 tool watcher -path {{ "{{.PATH}}" }} -preexec {{ "\"{{.PREEXEC}}\""}} {{ "{{.PREWAIT}}" }} -postexec {{ "\"{{.POSTEXEC}}\"" }} -ignorefiles {{ "{{.IGNOREFILES}}" }} -ignoredirs {{ "{{.IGNOREDIRS}}" }} -ignoreextensions {{ "{{.IGNOREEXTENSIONS}}" }} -exec {{ "\"{{.EXEC}}\"" }} -debounce {{ "{{.DEBOUNCE}}" }}
vars:
@ -423,12 +423,12 @@ tasks:
EXEC: 'wails3 task run'
POSTEXEC: ''
IGNOREFILES: 'Taskfile.yml'
IGNOREDIRS: '.git,frontend'
IGNOREDIRS: '.git,frontend,.idea,.vscode,bin'
IGNOREEXTENSIONS: '.exe,.syso'
DEBOUNCE: 1000
env:
# This is the default vite dev server port
WAILS_DEVSERVER_URL: 'http://localhost:5173'
FRONTEND_DEVSERVER_URL: 'http://localhost:5173'
dev:reload:
summary: Reloads the application

View File

@ -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))
})
}
}