|
|
|
@ -27,8 +27,9 @@ func (p TypeProperty) SetterName() string { |
|
|
|
} |
|
|
|
|
|
|
|
type FunctionArgument struct { |
|
|
|
Name string |
|
|
|
Type string |
|
|
|
Name string |
|
|
|
Type string |
|
|
|
Varidic bool |
|
|
|
} |
|
|
|
|
|
|
|
type TypeFunction struct { |
|
|
|
@ -43,18 +44,28 @@ func (f TypeFunction) GoName() string { |
|
|
|
|
|
|
|
type TypeStructure struct { |
|
|
|
Type string |
|
|
|
GlobalAPI string |
|
|
|
ImportJS bool |
|
|
|
Interface bool |
|
|
|
Inherits []string |
|
|
|
Implements []string |
|
|
|
Properties []TypeProperty |
|
|
|
Functions []TypeFunction |
|
|
|
String []string |
|
|
|
} |
|
|
|
|
|
|
|
func (t TypeStructure) Filename() string { |
|
|
|
return fmt.Sprintf("%s.go", strings.ToLower(t.Type)) |
|
|
|
} |
|
|
|
|
|
|
|
func (t TypeStructure) APIFilename() string { |
|
|
|
return fmt.Sprintf("%s/%s.go", t.PackageName(), strings.ToLower(t.Type)) |
|
|
|
} |
|
|
|
|
|
|
|
func (t TypeStructure) PackageName() string { |
|
|
|
return strings.ToLower(t.GlobalAPI) |
|
|
|
} |
|
|
|
|
|
|
|
func (t TypeStructure) ShortName() string { |
|
|
|
return strings.ToLower(string(t.Type[0])) |
|
|
|
} |
|
|
|
@ -72,20 +83,20 @@ func (t TypeStructure) writeReturnValue(out *bytes.Buffer, rt string) error { |
|
|
|
switch rt { |
|
|
|
case "string": |
|
|
|
out.WriteString("return val.String()\r\n") |
|
|
|
case "js.Value": |
|
|
|
case "Value": |
|
|
|
out.WriteString("return val") |
|
|
|
case "NodeIFace": |
|
|
|
out.WriteString("return &Node{ Value: val }\r\n") |
|
|
|
out.WriteString("return NewNode(val.JSValue())\r\n") |
|
|
|
case "*Element": |
|
|
|
out.WriteString("return &Element{ Value: val }\r\n") |
|
|
|
out.WriteString("return NewElement(val.JSValue())\r\n") |
|
|
|
case "[]*Element": |
|
|
|
out.WriteString("elms := make([]*Element, 0)\r\n") |
|
|
|
out.WriteString("for i := 0; i < val.Length(); i += 1 {\r\n") |
|
|
|
out.WriteString("\telms = append(elms, &Element{Value: val.Index(i)})\r\n") |
|
|
|
out.WriteString("\telms = append(elms, NewElement(val.Index(i)))\r\n") |
|
|
|
out.WriteString("}\r\n") |
|
|
|
out.WriteString("return elms\r\n") |
|
|
|
case "": |
|
|
|
// skip
|
|
|
|
out.WriteString("return val") |
|
|
|
default: |
|
|
|
return fmt.Errorf("Unknown function return type %s", rt) |
|
|
|
} |
|
|
|
@ -100,44 +111,117 @@ func (t TypeStructure) writeFunctions(out *bytes.Buffer, funcs []TypeFunction) e |
|
|
|
if i > 0 { |
|
|
|
out.WriteString(",") |
|
|
|
} |
|
|
|
out.WriteString(fmt.Sprintf("%s %s", arg.Name, arg.Type)) |
|
|
|
at := arg.Type |
|
|
|
if arg.Varidic { |
|
|
|
at = "..." + at |
|
|
|
} |
|
|
|
out.WriteString(fmt.Sprintf("%s %s", arg.Name, at)) |
|
|
|
} |
|
|
|
rt := f.ReturnType |
|
|
|
if rt == "" { |
|
|
|
rt = "Value" |
|
|
|
} |
|
|
|
out.WriteString(fmt.Sprintf(") %s {\r\n", f.ReturnType)) |
|
|
|
out.WriteString(fmt.Sprintf(") %s {\r\n", rt)) |
|
|
|
|
|
|
|
if f.ReturnType != "" { |
|
|
|
out.WriteString("val := ") |
|
|
|
for _, arg := range f.Arguments { |
|
|
|
if !arg.Varidic { |
|
|
|
continue |
|
|
|
} |
|
|
|
|
|
|
|
out.WriteString(fmt.Sprintf("%sVaridic := make([]interface{}, 0)\r\n", arg.Name)) |
|
|
|
out.WriteString(fmt.Sprintf("for _, a := range %s {\r\n", arg.Name)) |
|
|
|
out.WriteString(fmt.Sprintf("%sVaridic = append(%sVaridic, ToJSValue(a))\r\n", arg.Name, arg.Name)) |
|
|
|
out.WriteString("}\r\n") |
|
|
|
} |
|
|
|
out.WriteString(fmt.Sprintf("%s.Call(\"%s\"", t.ShortName(), f.Name)) |
|
|
|
|
|
|
|
out.WriteString(fmt.Sprintf("val := Value{ Value: %s.Call(\"%s\"", t.ShortName(), f.Name)) |
|
|
|
for _, arg := range f.Arguments { |
|
|
|
out.WriteString(",") |
|
|
|
out.WriteString(fmt.Sprintf("ToJSValue(%s)", arg.Name)) |
|
|
|
if arg.Varidic { |
|
|
|
out.WriteString(fmt.Sprintf("%sVaridic...", arg.Name)) |
|
|
|
} else { |
|
|
|
out.WriteString(fmt.Sprintf("ToJSValue(%s)", arg.Name)) |
|
|
|
} |
|
|
|
} |
|
|
|
out.WriteString(")\r\n") |
|
|
|
out.WriteString(")}\r\n") |
|
|
|
|
|
|
|
// Return value
|
|
|
|
t.writeReturnValue(out, f.ReturnType) |
|
|
|
t.writeReturnValue(out, rt) |
|
|
|
|
|
|
|
out.WriteString("}\r\n") |
|
|
|
} |
|
|
|
return nil |
|
|
|
} |
|
|
|
|
|
|
|
func (t TypeStructure) writeAPIFunctions(out *bytes.Buffer, funcs []TypeFunction) error { |
|
|
|
for _, f := range funcs { |
|
|
|
out.WriteString(fmt.Sprintf("func %s(", f.GoName())) |
|
|
|
for i, arg := range f.Arguments { |
|
|
|
if i > 0 { |
|
|
|
out.WriteString(",") |
|
|
|
} |
|
|
|
rt := arg.Type |
|
|
|
if rt == "*Element" { |
|
|
|
rt = "*dom.Element" |
|
|
|
} else if rt == "JSValue" { |
|
|
|
rt = "dom.JSValue" |
|
|
|
} else if rt == "*Callback" { |
|
|
|
rt = "*dom.Callback" |
|
|
|
} |
|
|
|
|
|
|
|
if arg.Varidic { |
|
|
|
rt = "..." + rt |
|
|
|
} |
|
|
|
out.WriteString(fmt.Sprintf("%s %s", arg.Name, rt)) |
|
|
|
} |
|
|
|
rt := f.ReturnType |
|
|
|
if rt == "" { |
|
|
|
rt = "Value" |
|
|
|
} |
|
|
|
if rt != "string" { |
|
|
|
if rt[0] == '*' { |
|
|
|
rt = "*dom." + strings.TrimLeft(rt, "*") |
|
|
|
} else if rt[0] == '[' { |
|
|
|
rt = "[]*dom." + strings.TrimLeft(rt, "[]*") |
|
|
|
} else { |
|
|
|
rt = "dom." + rt |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
out.WriteString(fmt.Sprintf(") %s {\r\n", rt)) |
|
|
|
out.WriteString(fmt.Sprintf("return %s.%s(", t.ShortName(), f.GoName())) |
|
|
|
for i, arg := range f.Arguments { |
|
|
|
if i > 0 { |
|
|
|
out.WriteString(",") |
|
|
|
} |
|
|
|
if arg.Varidic { |
|
|
|
out.WriteString(fmt.Sprintf("%s...", arg.Name)) |
|
|
|
} else { |
|
|
|
out.WriteString(fmt.Sprintf("%s", arg.Name)) |
|
|
|
} |
|
|
|
} |
|
|
|
out.WriteString(")}\r\n") |
|
|
|
} |
|
|
|
return nil |
|
|
|
} |
|
|
|
|
|
|
|
func (t TypeStructure) writeProperties(out *bytes.Buffer, props []TypeProperty) error { |
|
|
|
for _, p := range props { |
|
|
|
out.WriteString(fmt.Sprintf("func (%s *%s) %s() %s {\r\n", t.ShortName(), t.Type, p.GetterName(), p.Type)) |
|
|
|
if p.Type == "" { |
|
|
|
return fmt.Errorf("Property %q must have a type defined", p.Name) |
|
|
|
out.WriteString("\tval := ") |
|
|
|
rt := p.Type |
|
|
|
if rt == "" { |
|
|
|
rt = "Value" |
|
|
|
} |
|
|
|
out.WriteString(fmt.Sprintf("val := %s.Get(\"%s\")\r\n", t.ShortName(), p.Name)) |
|
|
|
|
|
|
|
out.WriteString(fmt.Sprintf("func (%s *%s) %s() %s {\r\n", t.ShortName(), t.Type, p.GetterName(), rt)) |
|
|
|
out.WriteString(fmt.Sprintf("val := Value{ Value: %s.Get(\"%s\")}\r\n", t.ShortName(), p.Name)) |
|
|
|
|
|
|
|
// Return value
|
|
|
|
t.writeReturnValue(out, p.Type) |
|
|
|
t.writeReturnValue(out, rt) |
|
|
|
|
|
|
|
out.WriteString(fmt.Sprintf("}\r\n")) |
|
|
|
|
|
|
|
if !p.ReadOnly { |
|
|
|
out.WriteString(fmt.Sprintf("func (%s *%s) %s(v %s){\r\n", t.ShortName(), t.Type, p.SetterName(), p.Type)) |
|
|
|
out.WriteString(fmt.Sprintf("func (%s *%s) %s(v %s){\r\n", t.ShortName(), t.Type, p.SetterName(), rt)) |
|
|
|
out.WriteString(fmt.Sprintf("\t%s.Set(\"%s\", v)\r\n", t.ShortName(), p.Name)) |
|
|
|
out.WriteString("}\r\n") |
|
|
|
} |
|
|
|
@ -145,6 +229,35 @@ func (t TypeStructure) writeProperties(out *bytes.Buffer, props []TypeProperty) |
|
|
|
return nil |
|
|
|
} |
|
|
|
|
|
|
|
func (t TypeStructure) writeAPIProperties(out *bytes.Buffer, props []TypeProperty) error { |
|
|
|
for _, p := range props { |
|
|
|
rt := p.Type |
|
|
|
if rt == "" { |
|
|
|
rt = "Value" |
|
|
|
} |
|
|
|
if rt != "string" { |
|
|
|
if rt[0] == '*' { |
|
|
|
rt = "*dom." + strings.TrimLeft(rt, "*") |
|
|
|
} else if rt[0] == '[' { |
|
|
|
rt = "[]*dom." + strings.TrimLeft(rt, "[]*") |
|
|
|
} else { |
|
|
|
rt = "dom." + rt |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
out.WriteString(fmt.Sprintf("func %s() %s {\r\n", p.GetterName(), rt)) |
|
|
|
out.WriteString(fmt.Sprintf("return %s.%s()", t.ShortName(), p.GetterName())) |
|
|
|
out.WriteString(fmt.Sprintf("}\r\n")) |
|
|
|
|
|
|
|
if !p.ReadOnly { |
|
|
|
out.WriteString(fmt.Sprintf("func %s(v %s){\r\n", p.SetterName(), rt)) |
|
|
|
out.WriteString(fmt.Sprintf("%s.%s(v)", t.ShortName(), p.SetterName())) |
|
|
|
out.WriteString("}\r\n") |
|
|
|
} |
|
|
|
} |
|
|
|
return nil |
|
|
|
} |
|
|
|
|
|
|
|
func (t TypeStructure) generateInterface(out *bytes.Buffer, types map[string]TypeStructure) error { |
|
|
|
out.WriteString(fmt.Sprintf("type %s interface {\r\n", t.Type)) |
|
|
|
|
|
|
|
@ -161,18 +274,25 @@ func (t TypeStructure) generateInterface(out *bytes.Buffer, types map[string]Typ |
|
|
|
func (t TypeStructure) generateStruct(out *bytes.Buffer, types map[string]TypeStructure) (err error) { |
|
|
|
out.WriteString(fmt.Sprintf("type %s struct {\r\n", t.Type)) |
|
|
|
|
|
|
|
out.WriteString("\tjs.Value\r\n") |
|
|
|
out.WriteString("\tValue\r\n") |
|
|
|
for _, name := range t.Inherits { |
|
|
|
out.WriteString(fmt.Sprintf("\t%s\r\n", name)) |
|
|
|
} |
|
|
|
|
|
|
|
out.WriteString("}\r\n") |
|
|
|
|
|
|
|
// Convert to type
|
|
|
|
out.WriteString(fmt.Sprintf("func JSTo%s (v js.Value) *%s { return &%s{ Value: v }}", t.Type, t.Type, t.Type)) |
|
|
|
// DEV: Start with upper case means it is public
|
|
|
|
if t.Type[0] == strings.ToUpper(string(t.Type[0]))[0] { |
|
|
|
// Constructor
|
|
|
|
out.WriteString(fmt.Sprintf("func New%s(v js.Value) *%s {\r\n", t.Type, t.Type)) |
|
|
|
out.WriteString("val := Value{ Value: v }\r\n") |
|
|
|
out.WriteString("if val.IsNull() || val.IsUndefined() { return nil }\r\n") |
|
|
|
out.WriteString(fmt.Sprintf("return val.To%s()\r\n", t.Type)) |
|
|
|
out.WriteString("}\r\n") |
|
|
|
|
|
|
|
// JSValue
|
|
|
|
out.WriteString(fmt.Sprintf("func (%s *%s) JSValue() js.Value { return %s.Value }\r\n", t.ShortName(), t.Type, t.ShortName())) |
|
|
|
// Convert to specific type helper
|
|
|
|
out.WriteString(fmt.Sprintf("func (v Value) To%s () *%s { return &%s{ Value: v }}\r\n", t.Type, t.Type, t.Type)) |
|
|
|
} |
|
|
|
|
|
|
|
// Properties
|
|
|
|
err = t.writeProperties(out, t.Properties) |
|
|
|
@ -214,7 +334,7 @@ func (t TypeStructure) Generate(types map[string]TypeStructure) ([]byte, error) |
|
|
|
out.WriteString("// DO NOT EDIT - generated file\r\n") |
|
|
|
out.WriteString("package dom\r\n") |
|
|
|
|
|
|
|
if t.Interface == false || t.ImportJS == true { |
|
|
|
if t.ImportJS { |
|
|
|
out.WriteString("import \"syscall/js\"\r\n") |
|
|
|
} |
|
|
|
|
|
|
|
@ -231,6 +351,55 @@ func (t TypeStructure) Generate(types map[string]TypeStructure) ([]byte, error) |
|
|
|
return format.Source(out.Bytes()) |
|
|
|
} |
|
|
|
|
|
|
|
func (t TypeStructure) GenerateAPI(types map[string]TypeStructure) ([]byte, error) { |
|
|
|
pkg := strings.ToLower(t.GlobalAPI) |
|
|
|
out := bytes.NewBuffer(make([]byte, 0)) |
|
|
|
out.WriteString("// DO NOT EDIT - generated file\r\n") |
|
|
|
out.WriteString(fmt.Sprintf("package %s\r\n", pkg)) |
|
|
|
|
|
|
|
if t.ImportJS { |
|
|
|
out.WriteString("import \"syscall/js\"\r\n") |
|
|
|
} |
|
|
|
out.WriteString("import dom \"github.com/brettlangdon/go-dom/v1\"\r\n") |
|
|
|
|
|
|
|
out.WriteString(fmt.Sprintf("var %s *dom.%s\r\n", t.ShortName(), t.Type)) |
|
|
|
out.WriteString("func init() {\r\n") |
|
|
|
out.WriteString(fmt.Sprintf("%s = dom.New%s(js.Global().Get(\"%s\"))\r\n", t.ShortName(), t.Type, t.GlobalAPI)) |
|
|
|
out.WriteString("}\r\n") |
|
|
|
|
|
|
|
err := t.writeAPIProperties(out, t.Properties) |
|
|
|
if err != nil { |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
|
|
|
|
err = t.writeAPIFunctions(out, t.Functions) |
|
|
|
if err != nil { |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
|
|
|
|
// Interfaces
|
|
|
|
for _, it := range t.Implements { |
|
|
|
i, ok := types[it] |
|
|
|
if !ok { |
|
|
|
return nil, fmt.Errorf("%q cannot implement unknown type %q", t.Type, it) |
|
|
|
} |
|
|
|
|
|
|
|
// Functions
|
|
|
|
err = t.writeAPIFunctions(out, i.Functions) |
|
|
|
if err != nil { |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
|
|
|
|
// Properties
|
|
|
|
err = t.writeAPIProperties(out, i.Properties) |
|
|
|
if err != nil { |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return format.Source(out.Bytes()) |
|
|
|
} |
|
|
|
|
|
|
|
func loadFile(fname string) (t TypeStructure, err error) { |
|
|
|
fp, err := os.Open(fname) |
|
|
|
if err != nil { |
|
|
|
@ -259,6 +428,28 @@ func processType(t TypeStructure, types map[string]TypeStructure) error { |
|
|
|
} |
|
|
|
defer out.Close() |
|
|
|
_, err = out.Write(contents) |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
} |
|
|
|
|
|
|
|
if t.GlobalAPI == "" { |
|
|
|
return nil |
|
|
|
} |
|
|
|
|
|
|
|
contents, err = t.GenerateAPI(types) |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
} |
|
|
|
err = os.MkdirAll(t.PackageName(), os.ModePerm) |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
} |
|
|
|
api, err := os.OpenFile(t.APIFilename(), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644) |
|
|
|
if err != nil { |
|
|
|
return err |
|
|
|
} |
|
|
|
defer api.Close() |
|
|
|
_, err = api.Write(contents) |
|
|
|
return err |
|
|
|
} |
|
|
|
|
|
|
|
|