mirror of
https://github.com/taigrr/wails.git
synced 2026-04-02 13:19:00 -07:00
Compare commits
1 Commits
feature/go
...
generate-s
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f382f45f94 |
37
cmd/wails/3_generate.go
Normal file
37
cmd/wails/3_generate.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/leaanthony/spinner"
|
||||
"github.com/wailsapp/wails/lib/stores"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
var generateStores = false
|
||||
|
||||
buildSpinner := spinner.NewSpinner()
|
||||
buildSpinner.SetSpinSpeed(50)
|
||||
|
||||
commandDescription := `This command will generate components`
|
||||
generateCommand := app.Command("generate", "Generate components").
|
||||
LongDescription(commandDescription).
|
||||
BoolFlag("s", "Generate Stores", &generateStores)
|
||||
|
||||
generateCommand.Action(func() error {
|
||||
|
||||
logger.PrintSmallBanner("Generating")
|
||||
fmt.Println()
|
||||
|
||||
if generateStores {
|
||||
err := stores.Generate()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
})
|
||||
}
|
||||
2
go.mod
2
go.mod
@@ -21,9 +21,9 @@ require (
|
||||
github.com/stretchr/testify v1.3.0 // indirect
|
||||
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba
|
||||
golang.org/x/image v0.0.0-20200430140353-33d19683fad8
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344 // indirect
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd
|
||||
golang.org/x/text v0.3.0
|
||||
golang.org/x/tools v0.0.0-20200902012652-d1954cc86c82
|
||||
gopkg.in/AlecAivazis/survey.v1 v1.8.4
|
||||
gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22
|
||||
)
|
||||
|
||||
18
go.sum
18
go.sum
@@ -64,15 +64,22 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba h1:2DHfQOxcpWdGf5q5IzCUFPNvRX9Icf+09RvQK2VnJq0=
|
||||
github.com/syossan27/tebata v0.0.0-20180602121909-b283fe4bc5ba/go.mod h1:iLnlXG2Pakcii2CU0cbY07DRCSvpWNa7nFxtevhOChk=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
golang.org/x/crypto v0.0.0-20190123085648-057139ce5d2b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw=
|
||||
golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344 h1:vGXIOMxbNfDTk/aXCmfdLgkrSV+Z2tcbze+pEc3v5W4=
|
||||
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180606202747-9527bec2660b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -83,6 +90,13 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20u
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200902012652-d1954cc86c82 h1:shxDsb9Dz27xzk3A0DxP0JuJnZMpKrdg8+E14eiUAX4=
|
||||
golang.org/x/tools v0.0.0-20200902012652-d1954cc86c82/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/AlecAivazis/survey.v1 v1.8.4 h1:10xXXN3wgIhPheb5NI58zFgZv32Ana7P3Tl4shW+0Qc=
|
||||
gopkg.in/AlecAivazis/survey.v1 v1.8.4/go.mod h1:iBNOmqKz/NUbZx3bA+4hAGLRC7fSK7tgtVDT4tB22XA=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
|
||||
14
lib/stores/generate.go
Normal file
14
lib/stores/generate.go
Normal file
@@ -0,0 +1,14 @@
|
||||
// Package stores
|
||||
package stores
|
||||
|
||||
import "os"
|
||||
|
||||
// Generate stores that are found in the project
|
||||
func Generate() error {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ParseProject(cwd)
|
||||
return nil
|
||||
}
|
||||
442
lib/stores/parse.go
Normal file
442
lib/stores/parse.go
Normal file
@@ -0,0 +1,442 @@
|
||||
package stores
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/leaanthony/slicer"
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
var internalMethods = slicer.String([]string{"WailsInit", "Wails Shutdown"})
|
||||
|
||||
var structCache = make(map[string]*ParsedStruct)
|
||||
var boundStructs = make(map[string]*ParsedStruct)
|
||||
var boundMethods = []string{}
|
||||
var boundStructPointerLiterals = []string{}
|
||||
var boundStructLiterals = slicer.StringSlicer{}
|
||||
var boundVariables = slicer.StringSlicer{}
|
||||
var app = ""
|
||||
var structPointerFunctionDecls = make(map[string]string)
|
||||
var structFunctionDecls = make(map[string]string)
|
||||
var variableStructDecls = make(map[string]string)
|
||||
var variableFunctionDecls = make(map[string]string)
|
||||
|
||||
type Parameter struct {
|
||||
Name string
|
||||
Type string
|
||||
}
|
||||
|
||||
type ParsedMethod struct {
|
||||
Struct string
|
||||
Name string
|
||||
Comments []string
|
||||
Inputs []*Parameter
|
||||
Returns []*Parameter
|
||||
}
|
||||
|
||||
type ParsedStruct struct {
|
||||
Name string
|
||||
Methods []*ParsedMethod
|
||||
}
|
||||
|
||||
type BoundStructs []*ParsedStruct
|
||||
|
||||
func ParseProject(projectPath string) {
|
||||
|
||||
cfg := &packages.Config{Mode: packages.NeedFiles | packages.NeedSyntax | packages.NeedTypesInfo}
|
||||
pkgs, err := packages.Load(cfg, projectPath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "load: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if packages.PrintErrors(pkgs) > 0 {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Iterate the packages
|
||||
for _, pkg := range pkgs {
|
||||
|
||||
// Iterate the files
|
||||
for _, file := range pkg.Syntax {
|
||||
|
||||
var wailsPkgVar = ""
|
||||
|
||||
ast.Inspect(file, func(n ast.Node) bool {
|
||||
switch x := n.(type) {
|
||||
// Parse import declarations
|
||||
case *ast.ImportSpec:
|
||||
// Determine what wails has been imported as
|
||||
if x.Path.Value == `"github.com/wailsapp/wails/v2"` {
|
||||
wailsPkgVar = x.Name.Name
|
||||
}
|
||||
// Parse calls. We are looking for app.Bind() calls
|
||||
case *ast.CallExpr:
|
||||
f, ok := x.Fun.(*ast.SelectorExpr)
|
||||
if ok {
|
||||
n, ok := f.X.(*ast.Ident)
|
||||
if ok {
|
||||
//Check this is the Bind() call associated with the app variable
|
||||
if n.Name == app && f.Sel.Name == "Bind" {
|
||||
if len(x.Args) == 1 {
|
||||
ce, ok := x.Args[0].(*ast.CallExpr)
|
||||
if ok {
|
||||
n, ok := ce.Fun.(*ast.Ident)
|
||||
if ok {
|
||||
// We found a bind method using a function call
|
||||
// EG: app.Bind( newMyStruct() )
|
||||
boundMethods = append(boundMethods, n.Name)
|
||||
}
|
||||
} else {
|
||||
// We also want to check for Bind( &MyStruct{} )
|
||||
ue, ok := x.Args[0].(*ast.UnaryExpr)
|
||||
if ok {
|
||||
if ue.Op.String() == "&" {
|
||||
cl, ok := ue.X.(*ast.CompositeLit)
|
||||
if ok {
|
||||
t, ok := cl.Type.(*ast.Ident)
|
||||
if ok {
|
||||
// We have found Bind( &MyStruct{} )
|
||||
boundStructPointerLiterals = append(boundStructPointerLiterals, t.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Let's check when the user binds a struct,
|
||||
// rather than a struct pointer: Bind( MyStruct{} )
|
||||
// We do this to provide better hints to the user
|
||||
cl, ok := x.Args[0].(*ast.CompositeLit)
|
||||
if ok {
|
||||
t, ok := cl.Type.(*ast.Ident)
|
||||
if ok {
|
||||
boundStructLiterals.Add(t.Name)
|
||||
}
|
||||
} else {
|
||||
// Also check for when we bind a variable
|
||||
// myVariable := &MyStruct{}
|
||||
// app.Bind( myVariable )
|
||||
i, ok := x.Args[0].(*ast.Ident)
|
||||
if ok {
|
||||
boundVariables.Add(i.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We scan assignments for a number of reasons:
|
||||
// * Determine the variable containing the main application
|
||||
// * Determine the type of variables that get used in Bind()
|
||||
// * Determine the type of variables that get created with var := &MyStruct{}
|
||||
case *ast.AssignStmt:
|
||||
for _, rhs := range x.Rhs {
|
||||
ce, ok := rhs.(*ast.CallExpr)
|
||||
if ok {
|
||||
se, ok := ce.Fun.(*ast.SelectorExpr)
|
||||
if ok {
|
||||
i, ok := se.X.(*ast.Ident)
|
||||
if ok {
|
||||
// Have we found the wails package name?
|
||||
if i.Name == wailsPkgVar {
|
||||
// Check we are calling a function to create the app
|
||||
if se.Sel.Name == "CreateApp" || se.Sel.Name == "CreateAppWithOptions" {
|
||||
if len(x.Lhs) == 1 {
|
||||
i, ok := x.Lhs[0].(*ast.Ident)
|
||||
if ok {
|
||||
// Found the app variable name
|
||||
app = i.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Check for function assignment
|
||||
// a := newMyStruct()
|
||||
fe, ok := ce.Fun.(*ast.Ident)
|
||||
if ok {
|
||||
if len(x.Lhs) == 1 {
|
||||
i, ok := x.Lhs[0].(*ast.Ident)
|
||||
if ok {
|
||||
// Store the variable -> Function mapping
|
||||
// so we can later resolve the type
|
||||
variableFunctionDecls[i.Name] = fe.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Check for literal assignment of struct
|
||||
// EG: myvar := MyStruct{}
|
||||
ue, ok := rhs.(*ast.UnaryExpr)
|
||||
if ok {
|
||||
cl, ok := ue.X.(*ast.CompositeLit)
|
||||
if ok {
|
||||
t, ok := cl.Type.(*ast.Ident)
|
||||
if ok {
|
||||
if len(x.Lhs) == 1 {
|
||||
i, ok := x.Lhs[0].(*ast.Ident)
|
||||
if ok {
|
||||
variableStructDecls[i.Name] = t.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// We scan for functions to build up a list of function names
|
||||
// for a number of reasons:
|
||||
// * Determine which functions are struct methods that are bound
|
||||
// * Determine
|
||||
case *ast.FuncDecl:
|
||||
if x.Recv != nil {
|
||||
// This is a struct method
|
||||
for _, field := range x.Recv.List {
|
||||
se, ok := field.Type.(*ast.StarExpr)
|
||||
if ok {
|
||||
// This is a struct pointer method
|
||||
i, ok := se.X.(*ast.Ident)
|
||||
if ok {
|
||||
// We want to ignore Internal functions
|
||||
if internalMethods.Contains(x.Name.Name) {
|
||||
continue
|
||||
}
|
||||
// If we haven't already found this struct,
|
||||
// Create a placeholder in the cache
|
||||
parsedStruct := structCache[i.Name]
|
||||
if parsedStruct == nil {
|
||||
structCache[i.Name] = &ParsedStruct{
|
||||
Name: i.Name,
|
||||
}
|
||||
parsedStruct = structCache[i.Name]
|
||||
}
|
||||
|
||||
// If this method is Public
|
||||
if string(x.Name.Name[0]) == strings.ToUpper((string(x.Name.Name[0]))) {
|
||||
structMethod := &ParsedMethod{
|
||||
Struct: i.Name,
|
||||
Name: x.Name.Name,
|
||||
}
|
||||
// Check if the method has comments.
|
||||
// If so, save it with the parsed method
|
||||
if x.Doc != nil {
|
||||
for _, comment := range x.Doc.List {
|
||||
stringComment := strings.TrimPrefix(comment.Text, "//")
|
||||
structMethod.Comments = append(structMethod.Comments, strings.TrimSpace(stringComment))
|
||||
}
|
||||
}
|
||||
|
||||
// Save the input parameters
|
||||
if x.Type.Params != nil {
|
||||
for _, inputField := range x.Type.Params.List {
|
||||
t, ok := inputField.Type.(*ast.Ident)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
for _, name := range inputField.Names {
|
||||
structMethod.Inputs = append(structMethod.Inputs, &Parameter{Name: name.Name, Type: t.Name})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save the output parameters
|
||||
if x.Type.Results != nil {
|
||||
for _, outputField := range x.Type.Results.List {
|
||||
t, ok := outputField.Type.(*ast.Ident)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if len(outputField.Names) == 0 {
|
||||
structMethod.Returns = append(structMethod.Returns, &Parameter{Type: t.Name})
|
||||
} else {
|
||||
for _, name := range outputField.Names {
|
||||
structMethod.Returns = append(structMethod.Returns, &Parameter{Name: name.Name, Type: t.Name})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Append this method to the parsed struct
|
||||
parsedStruct.Methods = append(parsedStruct.Methods, structMethod)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// This is a function declaration
|
||||
// We care about its name and return type
|
||||
// This will allow us to resolve types later
|
||||
functionName := x.Name.Name
|
||||
|
||||
// Look for one that returns a single value
|
||||
if x.Type != nil && x.Type.Results != nil && x.Type.Results.List != nil {
|
||||
if len(x.Type.Results.List) == 1 {
|
||||
// Check for *struct
|
||||
t, ok := x.Type.Results.List[0].Type.(*ast.StarExpr)
|
||||
if ok {
|
||||
s, ok := t.X.(*ast.Ident)
|
||||
if ok {
|
||||
// println("*** Function", functionName, "found which returns: *"+s.Name)
|
||||
structPointerFunctionDecls[functionName] = s.Name
|
||||
}
|
||||
} else {
|
||||
// Check for functions that return a struct
|
||||
// This is to help us provide hints if the user binds a struct
|
||||
t, ok := x.Type.Results.List[0].Type.(*ast.Ident)
|
||||
if ok {
|
||||
// println("*** Function", functionName, "found which returns: "+t.Name)
|
||||
structFunctionDecls[functionName] = t.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
// spew.Dump(file)
|
||||
}
|
||||
}
|
||||
|
||||
/***** Update bound structs ******/
|
||||
|
||||
// Resolve bound Methods
|
||||
for _, method := range boundMethods {
|
||||
s, ok := structPointerFunctionDecls[method]
|
||||
if !ok {
|
||||
s, ok = structFunctionDecls[method]
|
||||
if !ok {
|
||||
println("Fatal: Bind statement using", method, "but cannot find", method, "declaration")
|
||||
} else {
|
||||
println("Fatal: Cannot bind struct using method `" + method + "` because it returns a struct (" + s + "). Return a pointer to " + s + " instead.")
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
structDefinition := structCache[s]
|
||||
if structDefinition == nil {
|
||||
println("Fatal: Bind statement using `"+method+"` but cannot find struct", s, "definition")
|
||||
os.Exit(1)
|
||||
}
|
||||
boundStructs[s] = structDefinition
|
||||
}
|
||||
|
||||
// Resolve bound vars
|
||||
for _, structLiteral := range boundStructPointerLiterals {
|
||||
s, ok := structCache[structLiteral]
|
||||
if !ok {
|
||||
println("Fatal: Bind statement using", structLiteral, "but cannot find", structLiteral, "declaration")
|
||||
os.Exit(1)
|
||||
}
|
||||
boundStructs[structLiteral] = s
|
||||
}
|
||||
|
||||
// Resolve bound variables
|
||||
boundVariables.Each(func(variable string) {
|
||||
v, ok := variableStructDecls[variable]
|
||||
if !ok {
|
||||
method, ok := variableFunctionDecls[variable]
|
||||
if !ok {
|
||||
println("Fatal: Bind statement using variable `" + variable + "` which does not resolve to a struct pointer")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Resolve function name
|
||||
v, ok = structPointerFunctionDecls[method]
|
||||
if !ok {
|
||||
v, ok = structFunctionDecls[method]
|
||||
if !ok {
|
||||
println("Fatal: Bind statement using", method, "but cannot find", method, "declaration")
|
||||
} else {
|
||||
println("Fatal: Cannot bind variable `" + variable + "` because it resolves to a struct (" + v + "). Return a pointer to " + v + " instead.")
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
s, ok := structCache[v]
|
||||
if !ok {
|
||||
println("Fatal: Bind statement using variable `" + variable + "` which resolves to a `" + v + "` but cannot find its declaration")
|
||||
os.Exit(1)
|
||||
}
|
||||
boundStructs[v] = s
|
||||
|
||||
})
|
||||
|
||||
// Check for struct literals
|
||||
boundStructLiterals.Each(func(structName string) {
|
||||
println("Fatal: Cannot bind struct using struct literal `" + structName + "{}`. Create a pointer to " + structName + " instead.")
|
||||
os.Exit(1)
|
||||
})
|
||||
|
||||
// Check for bound variables
|
||||
// boundVariables.Each(func(varName string) {
|
||||
// println("Fatal: Cannot bind struct using struct literal `" + structName + "{}`. Create a pointer to " + structName + " instead.")
|
||||
// })
|
||||
|
||||
// spew.Dump(boundStructs)
|
||||
// os.Exit(0)
|
||||
|
||||
// }
|
||||
// Inspect the AST and print all identifiers and literals.
|
||||
|
||||
println("export {")
|
||||
|
||||
noOfStructs := len(boundStructs)
|
||||
structCount := 0
|
||||
for _, s := range boundStructs {
|
||||
structCount++
|
||||
println()
|
||||
println(" " + s.Name + ": {")
|
||||
println()
|
||||
noOfMethods := len(s.Methods)
|
||||
for methodCount, m := range s.Methods {
|
||||
println(" /****************")
|
||||
for _, comment := range m.Comments {
|
||||
println(" *", comment)
|
||||
}
|
||||
if len(m.Comments) > 0 {
|
||||
println(" *")
|
||||
}
|
||||
inputNames := ""
|
||||
for _, input := range m.Inputs {
|
||||
println(" * @param {"+input.Type+"}", input.Name)
|
||||
inputNames += input.Name + ", "
|
||||
}
|
||||
print(" * @return Promise<")
|
||||
for _, output := range m.Returns {
|
||||
print(output.Type + "|")
|
||||
}
|
||||
println("Error>")
|
||||
println(" *")
|
||||
println(" ***/")
|
||||
if len(inputNames) > 2 {
|
||||
inputNames = inputNames[:len(inputNames)-2]
|
||||
}
|
||||
println(" ", m.Name+": function("+inputNames+") {")
|
||||
println(" return window.backend." + s.Name + "." + m.Name + "(" + inputNames + ");")
|
||||
print(" }")
|
||||
if methodCount < noOfMethods-1 {
|
||||
print(",")
|
||||
}
|
||||
println()
|
||||
println()
|
||||
}
|
||||
print(" }")
|
||||
if structCount < noOfStructs-1 {
|
||||
print(",")
|
||||
}
|
||||
println()
|
||||
}
|
||||
println()
|
||||
println("}")
|
||||
println()
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user