diff --git a/v2/internal/typescriptify/js-reserved-keywords.go b/v2/internal/typescriptify/js-reserved-keywords.go index 7750fb90a..4f9aa09f4 100644 --- a/v2/internal/typescriptify/js-reserved-keywords.go +++ b/v2/internal/typescriptify/js-reserved-keywords.go @@ -61,7 +61,7 @@ var jsReservedKeywords []string = []string{ "typeof", "var", "void", - "volotile", + "volatile", "while", "with", "yield", diff --git a/v3/examples/binding/GreetService.go b/v3/examples/binding/GreetService.go index 1295acb65..389b51c09 100644 --- a/v3/examples/binding/GreetService.go +++ b/v3/examples/binding/GreetService.go @@ -1,8 +1,16 @@ package main +type Person struct { + name string +} + type GreetService struct { } func (*GreetService) Greet(name string) string { return "Hello " + name } + +func (*GreetService) GreetPerson(person Person) string { + return "Hello " + person.name +} diff --git a/v3/examples/binding/bindings_main.js b/v3/examples/binding/bindings_main.js index aad1983c0..064a7c135 100644 --- a/v3/examples/binding/bindings_main.js +++ b/v3/examples/binding/bindings_main.js @@ -2,6 +2,8 @@ // Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL // This file is automatically generated. DO NOT EDIT +import {main} from './models'; + function GreetService(method) { return { packageName: "main", @@ -21,9 +23,21 @@ function Greet(name) { return wails.Call(GreetService("Greet", name)); } +/** + * GreetService.GreetPerson + * + * @param person {main.Person} + * @returns {Promise} + **/ +function GreetPerson(person) { + return wails.Call(GreetService("GreetPerson", person)); +} + window.go = window.go || {}; window.go.main = { GreetService: { Greet, + GreetPerson, }, }; + diff --git a/v3/examples/binding/models.ts b/v3/examples/binding/models.ts new file mode 100644 index 000000000..5d00fe3c2 --- /dev/null +++ b/v3/examples/binding/models.ts @@ -0,0 +1,24 @@ +// @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; // Warning: this is unexported in the Go struct. + + static createFrom(source: any = {}) { + return new Person(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) { + source = JSON.parse(source); + } + + this.name = source["name"] + + } + } + +} diff --git a/v3/internal/parser/bindings.go b/v3/internal/parser/bindings.go index 793c83635..a5562648a 100644 --- a/v3/internal/parser/bindings.go +++ b/v3/internal/parser/bindings.go @@ -42,10 +42,78 @@ function {{methodName}}({{inputs}}) { } ` +var reservedWords = []string{ + "abstract", + "arguments", + "await", + "boolean", + "break", + "byte", + "case", + "catch", + "char", + "class", + "const", + "continue", + "debugger", + "default", + "delete", + "do", + "double", + "else", + "enum", + "eval", + "export", + "extends", + "false", + "final", + "finally", + "float", + "for", + "function", + "goto", + "if", + "implements", + "import", + "in", + "instanceof", + "int", + "interface", + "let", + "long", + "native", + "new", + "null", + "package", + "private", + "protected", + "public", + "return", + "short", + "static", + "super", + "switch", + "synchronized", + "this", + "throw", + "throws", + "transient", + "true", + "try", + "typeof", + "var", + "void", + "volatile", + "while", + "with", + "yield", + "object", +} + func sanitiseJSVarName(name string) string { // if the name is a reserved word, prefix with an // underscore - if strings.Contains("break,case,catch,class,const,continue,debugger,default,delete,do,else,enum,export,extends,false,finally,for,function,if,implements,import,in,instanceof,interface,let,new,null,package,private,protected,public,return,static,super,switch,this,throw,true,try,typeof,var,void,while,with,yield", name) { + if lo.Contains(reservedWords, name) { return "_" + name } return name @@ -69,7 +137,6 @@ func GenerateBinding(structName string, method *BoundMethod) (string, []string) if len(params) == 0 { params = " *" } - ////params += "\n" result = strings.ReplaceAll(result, " * @param name {string}", params) var inputs string for _, input := range method.Inputs { diff --git a/v3/internal/parser/models.go b/v3/internal/parser/models.go index bd0022315..3f52a7ad5 100644 --- a/v3/internal/parser/models.go +++ b/v3/internal/parser/models.go @@ -1,17 +1,22 @@ package parser import ( + "bytes" + "embed" "io" "text/template" ) +//go:embed templates +var templates embed.FS + type ModelDefinitions struct { Package string Models map[string]*StructDef } func GenerateModel(wr io.Writer, def *ModelDefinitions) error { - tmpl, err := template.New("model.ts.tmpl").ParseFiles("templates/model.ts.tmpl") + tmpl, err := template.New("model.ts.tmpl").ParseFS(templates, "templates/model.ts.tmpl") if err != nil { println("Unable to create class template: " + err.Error()) return err @@ -25,8 +30,24 @@ func GenerateModel(wr io.Writer, def *ModelDefinitions) error { return nil } -func GenerateModels(models map[packagePath]map[structName]*StructDef) string { - return "" +const modelsHeader = `// @ts-check +// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL +// This file is automatically generated. DO NOT EDIT +` + +func GenerateModels(models map[packagePath]map[structName]*StructDef) (string, error) { + var buffer bytes.Buffer + buffer.WriteString(modelsHeader) + for pkg, pkgModels := range models { + err := GenerateModel(&buffer, &ModelDefinitions{ + Package: pkg, + Models: pkgModels, + }) + if err != nil { + return "", err + } + } + return buffer.String(), nil } //func GenerateClass(wr io.Writer, def *StructDef) error { diff --git a/v3/internal/parser/parser.go b/v3/internal/parser/parser.go index ba9ef2c1d..d022cd219 100644 --- a/v3/internal/parser/parser.go +++ b/v3/internal/parser/parser.go @@ -93,12 +93,20 @@ func (f *Field) JSName() string { func (f *Field) JSDef(pkg string) string { name := f.JSName() + var result string + if f.Type.Package == "" || f.Type.Package == pkg { - return fmt.Sprintf("%s: %s;", name, f.Type.Name) + result += fmt.Sprintf("%s: %s;", name, f.Type.Name) + } else { + parts := strings.Split(f.Type.Package, "/") + result += fmt.Sprintf("%s: %s.%s;", name, parts[len(parts)-1], f.Type.Name) } - parts := strings.Split(f.Type.Package, "/") - return fmt.Sprintf("%s: %s.%s;", name, parts[len(parts)-1], f.Type.Name) + if !ast.IsExported(f.Name) { + result += " // Warning: this is unexported in the Go struct." + } + + return result } type ParsedPackage struct { @@ -165,8 +173,11 @@ func GenerateBindingsAndModels(projectDir string, outputDir string) error { // Generate Models if len(p.Models) > 0 { - generatedModels := GenerateModels(p.Models) - err = os.WriteFile(filepath.Join(outputDir, "models.js"), []byte(generatedModels), 0644) + generatedModels, err := GenerateModels(p.Models) + if err != nil { + return err + } + err = os.WriteFile(filepath.Join(outputDir, "models.ts"), []byte(generatedModels), 0644) if err != nil { return err }