Initial bindings generation

This commit is contained in:
Lea Anthony 2023-03-01 21:31:29 +11:00
commit 868b769e7f
4 changed files with 186 additions and 5 deletions

View file

@ -17,10 +17,9 @@ function Greet(name) {
return wails.Call(GreetService("Greet", name));
}
window.go = {
main: {
GreetService: {
Greet,
}
window.go = window.go || {};
Object.window.go.main = {
GreetService: {
Greet,
}
};

View file

@ -0,0 +1,80 @@
package parser
import (
"strings"
)
const helperTemplate = `function {{structName}}(method) {
return {
packageName: "{{packageName}}",
serviceName: "{{structName}}",
methodName: method,
args: Array.prototype.slice.call(arguments, 1),
};
}`
func GenerateHelper(packageName, structName string) string {
result := strings.ReplaceAll(helperTemplate, "{{packageName}}", packageName)
result = strings.ReplaceAll(result, "{{structName}}", structName)
return result
}
const bindingTemplate = `
/**
* {{structName}}.{{methodName}}
* Comments
* @param name {string}
* @returns {Promise<string>}
*/
function {{methodName}}({{args}}) {
return wails.Call({{structName}}("{{methodName}}", {{args}}));
}
`
func GenerateBinding(structName string, method *BoundMethod) string {
result := strings.ReplaceAll(bindingTemplate, "{{structName}}", structName)
result = strings.ReplaceAll(result, "{{methodName}}", method.Name)
result = strings.ReplaceAll(result, "Comments", strings.TrimSpace(method.DocComment))
var params string
for _, input := range method.Inputs {
params += " * @param " + input.Name + " {" + input.JSType() + "}\n"
}
params = strings.TrimSuffix(params, "\n")
result = strings.ReplaceAll(result, " * @param name {string}", params)
var args string
for _, input := range method.Inputs {
args += input.Name + ", "
}
args = strings.TrimSuffix(args, ", ")
result = strings.ReplaceAll(result, "{{args}}", args)
return result
}
func GenerateBindings(bindings map[string]map[string][]*BoundMethod) string {
var result string
for packageName, packageBindings := range bindings {
for structName, bindings := range packageBindings {
result += GenerateHelper(packageName, structName)
for _, binding := range bindings {
result += GenerateBinding(structName, binding)
}
}
}
result += `
window.go = window.go || {};
`
for packageName, packageBindings := range bindings {
result += "Object.window.go." + packageName + " = {\n"
for structName, methods := range packageBindings {
result += " " + structName + ": {\n"
for _, method := range methods {
result += " " + method.Name + ",\n"
}
result += " }\n"
}
result += "};\n"
}
return result
}

View file

@ -0,0 +1,66 @@
package parser
import (
"github.com/google/go-cmp/cmp"
"testing"
)
const expectedGreetService = `function GreetService(method) {
return {
packageName: "main",
serviceName: "GreetService",
methodName: method,
args: Array.prototype.slice.call(arguments, 1),
};
}
/**
* GreetService.Greet
* Greet someone
* @param name {string}
* @returns {Promise<string>}
*/
function Greet(name) {
return wails.Call(GreetService("Greet", name));
}
window.go = window.go || {};
Object.window.go.main = {
GreetService: {
Greet,
}
};
`
func TestGenerateGreetService(t *testing.T) {
parsedMethods := map[string]map[string][]*BoundMethod{
"main": {
"GreetService": {
{
Name: "Greet",
DocComment: "Greet someone\n",
Inputs: []*Parameter{
{
Name: "name",
Type: &ParameterType{
Name: "string",
},
},
},
Outputs: []*Parameter{
{
Name: "",
Type: &ParameterType{
Name: "string",
},
},
},
},
},
},
}
got := GenerateBindings(parsedMethods)
if diff := cmp.Diff(expectedGreetService, got); diff != "" {
t.Fatalf("GenerateService() mismatch (-want +got):\n%s", diff)
}
}

View file

@ -38,6 +38,42 @@ type Parameter struct {
Type *ParameterType
}
func (p *Parameter) JSType() string {
// Convert type to javascript equivalent type
var typeName string
switch p.Type.Name {
case "int", "int8", "int16", "int32", "int64", "uint", "uint8", "uint16", "uint32", "uint64", "uintptr":
typeName = "number"
case "string":
typeName = "string"
case "bool":
typeName = "boolean"
default:
typeName = p.Type.Name
}
// if the type is a struct, we need to add the package name
if p.Type.IsStruct {
if p.Type.Package != "" {
parts := strings.Split(p.Type.Package, "/")
typeName = parts[len(parts)-1] + "." + typeName
// TODO: Check if this is a duplicate package name
}
}
// Add slice suffix
if p.Type.IsSlice {
typeName += "[]"
}
// Add pointer suffix
if p.Type.IsPointer {
typeName += " | null"
}
return typeName
}
type BoundMethod struct {
Name string
DocComment string