mirror of
https://github.com/taigrr/wails.git
synced 2026-04-13 18:38:11 -07:00
Slight refactor to improve output
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
package backendjs
|
||||
|
||||
import "go/ast"
|
||||
import (
|
||||
"go/ast"
|
||||
)
|
||||
|
||||
func (p *Parser) parseAssignment(assignStmt *ast.AssignStmt) {
|
||||
func (p *Parser) parseAssignment(assignStmt *ast.AssignStmt, pkg *Package) {
|
||||
for _, rhs := range assignStmt.Rhs {
|
||||
ce, ok := rhs.(*ast.CallExpr)
|
||||
if ok {
|
||||
@@ -34,7 +36,7 @@ func (p *Parser) parseAssignment(assignStmt *ast.AssignStmt) {
|
||||
if ok {
|
||||
// Store the variable -> Function mapping
|
||||
// so we can later resolve the type
|
||||
p.variablesThatWereAssignedByFunctions[i.Name] = fe.Name
|
||||
pkg.variablesThatWereAssignedByFunctions[i.Name] = fe.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,7 +53,20 @@ func (p *Parser) parseAssignment(assignStmt *ast.AssignStmt) {
|
||||
if len(assignStmt.Lhs) == 1 {
|
||||
i, ok := assignStmt.Lhs[0].(*ast.Ident)
|
||||
if ok {
|
||||
p.variablesThatWereAssignedByStructLiterals[i.Name] = t.Name
|
||||
pkg.variablesThatWereAssignedByStructLiterals[i.Name] = t.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cl, ok := rhs.(*ast.CompositeLit)
|
||||
if ok {
|
||||
t, ok := cl.Type.(*ast.Ident)
|
||||
if ok {
|
||||
if len(assignStmt.Lhs) == 1 {
|
||||
i, ok := assignStmt.Lhs[0].(*ast.Ident)
|
||||
if ok {
|
||||
pkg.variablesThatWereAssignedByStructLiterals[i.Name] = t.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package backendjs
|
||||
|
||||
import "go/ast"
|
||||
|
||||
func (p *Parser) parseCallExpressions(x *ast.CallExpr) {
|
||||
func (p *Parser) parseCallExpressions(x *ast.CallExpr, pkg *Package) {
|
||||
f, ok := x.Fun.(*ast.SelectorExpr)
|
||||
if ok {
|
||||
n, ok := f.X.(*ast.Ident)
|
||||
@@ -14,9 +14,7 @@ func (p *Parser) parseCallExpressions(x *ast.CallExpr) {
|
||||
if ok {
|
||||
fn, ok := ce.Fun.(*ast.Ident)
|
||||
if ok {
|
||||
// We found a bind method using a function call
|
||||
// EG: app.Bind( newMyStruct() )
|
||||
p.structMethodsThatWereBound.Add(fn.Name)
|
||||
pkg.structMethodsThatWereBound.Add(fn.Name)
|
||||
}
|
||||
} else {
|
||||
// We also want to check for Bind( &MyStruct{} )
|
||||
@@ -27,8 +25,7 @@ func (p *Parser) parseCallExpressions(x *ast.CallExpr) {
|
||||
if ok {
|
||||
t, ok := cl.Type.(*ast.Ident)
|
||||
if ok {
|
||||
// We have found Bind( &MyStruct{} )
|
||||
p.structPointerLiteralsThatWereBound.Add(t.Name)
|
||||
pkg.structPointerLiteralsThatWereBound.Add(t.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -40,7 +37,8 @@ func (p *Parser) parseCallExpressions(x *ast.CallExpr) {
|
||||
if ok {
|
||||
t, ok := cl.Type.(*ast.Ident)
|
||||
if ok {
|
||||
p.structLiteralsThatWereBound.Add(t.Name)
|
||||
pkg.structLiteralsThatWereBound.Add(t.Name)
|
||||
|
||||
}
|
||||
} else {
|
||||
// Also check for when we bind a variable
|
||||
@@ -48,7 +46,7 @@ func (p *Parser) parseCallExpressions(x *ast.CallExpr) {
|
||||
// app.Bind( myVariable )
|
||||
i, ok := x.Args[0].(*ast.Ident)
|
||||
if ok {
|
||||
p.variablesThatWereBound.Add(i.Name)
|
||||
pkg.variablesThatWereBound.Add(i.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ func (p *Parser) parseFunctionDeclaration(funcDecl *ast.FuncDecl, pkg *Package)
|
||||
s, ok := t.X.(*ast.Ident)
|
||||
if ok {
|
||||
// println("*** Function", functionName, "found which returns: *"+s.Name)
|
||||
p.functionsThatReturnStructPointers[functionName] = s.Name
|
||||
pkg.functionsThatReturnStructPointers[functionName] = s.Name
|
||||
}
|
||||
} else {
|
||||
// Check for functions that return a struct
|
||||
@@ -140,7 +140,7 @@ func (p *Parser) parseFunctionDeclaration(funcDecl *ast.FuncDecl, pkg *Package)
|
||||
t, ok := funcDecl.Type.Results.List[0].Type.(*ast.Ident)
|
||||
if ok {
|
||||
// println("*** Function", functionName, "found which returns: "+t.Name)
|
||||
p.functionsThatReturnStructs[functionName] = t.Name
|
||||
pkg.functionsThatReturnStructs[functionName] = t.Name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,17 +4,22 @@
|
||||
{{- range .DeclarationReferences}}
|
||||
/// <reference types="../{{.}}" />{{- end}}
|
||||
|
||||
declare module {{.Name}} { {{range .Structs}}
|
||||
{{if .Comments }}{{range .Comments}}// {{ . }}{{end}}{{end}}
|
||||
interface {{.Name}} { {{ if $.StructIsUsedAsData .Name }}
|
||||
declare module {{.Name}} { {{- range .Structs}}
|
||||
{{- $usedAsData := $.StructIsUsedAsData .Name }}
|
||||
{{- if or .IsBound $usedAsData}}
|
||||
{{- if .Comments }}{{range .Comments}}// {{ . }}{{end}}{{- end}}
|
||||
|
||||
interface {{.Name}} { {{ if $usedAsData }}
|
||||
{{- range .Fields}}{{if .Comments }}
|
||||
{{range .Comments}}//{{ . }}{{end}}{{end}}
|
||||
{{range .Comments}}//{{ . }}{{end}}{{- end}}
|
||||
{{.Name}}: {{.TypeAsTSType}}; {{- end}} {{ end }}
|
||||
{{- if .IsBound }}
|
||||
{{- range .Methods}}
|
||||
{{- range .Comments}}
|
||||
// {{ . }}{{- end}}
|
||||
{{.Name}}({{.InputsAsTSText}}): Promise<{{.OutputsAsTSText}}>;
|
||||
{{- end}}
|
||||
}{{end}}
|
||||
{{- end}}{{end}}
|
||||
}{{- end}}
|
||||
{{- end}}
|
||||
|
||||
}
|
||||
@@ -25,12 +25,46 @@ type Package struct {
|
||||
// These are the structs declared in this package
|
||||
// that are used as data by either this or other packages
|
||||
structsUsedAsData slicer.StringSlicer
|
||||
|
||||
// A list of functions that return struct pointers
|
||||
functionsThatReturnStructPointers map[string]string
|
||||
|
||||
// A list of functions that return structs
|
||||
functionsThatReturnStructs map[string]string
|
||||
|
||||
// A list of struct literals that were bound to the application
|
||||
// EG: app.Bind( &mystruct{} )
|
||||
structLiteralsThatWereBound slicer.StringSlicer
|
||||
|
||||
// A list of struct pointer literals that were bound to the application
|
||||
// EG: app.Bind( &mystruct{} )
|
||||
structPointerLiteralsThatWereBound slicer.StringSlicer
|
||||
|
||||
// A list of methods that returns structs to the Bind method
|
||||
// EG: app.Bind( newMyStruct() )
|
||||
structMethodsThatWereBound slicer.StringSlicer
|
||||
|
||||
// A list of variables that were used for binding
|
||||
// Eg: myVar := &mystruct{}; app.Bind( myVar )
|
||||
variablesThatWereBound slicer.StringSlicer
|
||||
|
||||
// A list of variables that were assigned using a function call
|
||||
// EG: myVar := newStruct()
|
||||
variablesThatWereAssignedByFunctions map[string]string
|
||||
|
||||
// A map of variables that were assigned using a struct literal
|
||||
// EG: myVar := MyStruct{}
|
||||
variablesThatWereAssignedByStructLiterals map[string]string
|
||||
}
|
||||
|
||||
func (p *Parser) parsePackage(pkg *packages.Package, fset *token.FileSet) (*Package, error) {
|
||||
result := &Package{
|
||||
Name: pkg.Name,
|
||||
Structs: make(map[string]*Struct),
|
||||
Name: pkg.Name,
|
||||
Structs: make(map[string]*Struct),
|
||||
functionsThatReturnStructPointers: make(map[string]string),
|
||||
functionsThatReturnStructs: make(map[string]string),
|
||||
variablesThatWereAssignedByFunctions: make(map[string]string),
|
||||
variablesThatWereAssignedByStructLiterals: make(map[string]string),
|
||||
}
|
||||
|
||||
// Get the absolute path to the project's main.go file
|
||||
@@ -74,12 +108,12 @@ func (p *Parser) parsePackage(pkg *packages.Package, fset *token.FileSet) (*Pack
|
||||
|
||||
// Capture call expressions
|
||||
if callExpr, ok := n.(*ast.CallExpr); ok {
|
||||
p.parseCallExpressions(callExpr)
|
||||
p.parseCallExpressions(callExpr, result)
|
||||
}
|
||||
|
||||
// Parse Assignments
|
||||
if assignStmt, ok := n.(*ast.AssignStmt); ok {
|
||||
p.parseAssignment(assignStmt)
|
||||
p.parseAssignment(assignStmt, result)
|
||||
}
|
||||
|
||||
// Parse Function declarations
|
||||
@@ -158,3 +192,27 @@ func (p *Package) DeclarationReferences() []string {
|
||||
func (p *Package) StructIsUsedAsData(structName string) bool {
|
||||
return p.structsUsedAsData.Contains(structName)
|
||||
}
|
||||
|
||||
func (p *Package) resolveBoundStructLiterals() {
|
||||
p.structLiteralsThatWereBound.Each(func(structName string) {
|
||||
strct := p.Structs[structName]
|
||||
if strct == nil {
|
||||
println("Warning: Cannot find bound struct", structName, "in package", p.Name)
|
||||
return
|
||||
}
|
||||
println("Bound struct", strct.Name, "in package", p.Name)
|
||||
strct.IsBound = true
|
||||
})
|
||||
}
|
||||
|
||||
func (p *Package) resolveBoundStructPointerLiterals() {
|
||||
p.structPointerLiteralsThatWereBound.Each(func(structName string) {
|
||||
strct := p.Structs[structName]
|
||||
if strct == nil {
|
||||
println("Warning: Cannot find bound struct", structName, "in package", p.Name)
|
||||
return
|
||||
}
|
||||
println("Bound struct pointer", strct.Name, "in package", p.Name)
|
||||
strct.IsBound = true
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
|
||||
// This file is automatically generated. DO NOT EDIT
|
||||
|
||||
{{range $struct := .Structs }} {{ if .Methods }}
|
||||
{{range $struct := .Structs }}
|
||||
{{- if .IsBound }}
|
||||
{{ if .Methods }}
|
||||
export const {{.Name}} = {
|
||||
{{range .Methods }}
|
||||
/**{{if .Comments }}
|
||||
@@ -18,6 +20,7 @@ export const {{.Name}} = {
|
||||
{{end}}
|
||||
}
|
||||
{{end}}
|
||||
{{- end}}
|
||||
{{end}}
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package backendjs
|
||||
|
||||
import (
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/leaanthony/slicer"
|
||||
)
|
||||
|
||||
@@ -17,52 +18,154 @@ type Parser struct {
|
||||
// import mywails "github.com/wailsapp/wails/v2" -> mywails
|
||||
wailsPackageVariable string
|
||||
|
||||
// A list of methods that returns structs to the Bind method
|
||||
// EG: app.Bind( newMyStruct() )
|
||||
structMethodsThatWereBound slicer.StringSlicer
|
||||
|
||||
// A list of struct literals that were bound to the application
|
||||
// EG: app.Bind( &mystruct{} )
|
||||
structLiteralsThatWereBound slicer.StringSlicer
|
||||
|
||||
// A list of struct pointer literals that were bound to the application
|
||||
// EG: app.Bind( &mystruct{} )
|
||||
structPointerLiteralsThatWereBound slicer.StringSlicer
|
||||
|
||||
// A list of variables that were used for binding
|
||||
// Eg: myVar := &mystruct{}; app.Bind( myVar )
|
||||
variablesThatWereBound slicer.StringSlicer
|
||||
|
||||
// A list of variables that were assigned using a function call
|
||||
// EG: myVar := newStruct()
|
||||
variablesThatWereAssignedByFunctions map[string]string
|
||||
|
||||
// A map of variables that were assigned using a struct literal
|
||||
// EG: myVar := MyStruct{}
|
||||
variablesThatWereAssignedByStructLiterals map[string]string
|
||||
|
||||
// Internal methods (WailsInit/WailsShutdown)
|
||||
internalMethods *slicer.StringSlicer
|
||||
|
||||
// A list of functions that return struct pointers
|
||||
functionsThatReturnStructPointers map[string]string
|
||||
|
||||
// A list of functions that return structs
|
||||
functionsThatReturnStructs map[string]string
|
||||
}
|
||||
|
||||
// NewParser creates a new Wails Project parser
|
||||
func NewParser() *Parser {
|
||||
return &Parser{
|
||||
Packages: make(map[string]*Package),
|
||||
variablesThatWereAssignedByFunctions: make(map[string]string),
|
||||
variablesThatWereAssignedByStructLiterals: make(map[string]string),
|
||||
functionsThatReturnStructPointers: make(map[string]string),
|
||||
functionsThatReturnStructs: make(map[string]string),
|
||||
internalMethods: slicer.String([]string{"WailsInit", "WailsShutdown"}),
|
||||
Packages: make(map[string]*Package),
|
||||
internalMethods: slicer.String([]string{"WailsInit", "WailsShutdown"}),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) resolve() error {
|
||||
|
||||
// Resolve bound structs
|
||||
err := p.resolveBoundStructs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) resolveBoundStructs() error {
|
||||
|
||||
// Resolve Struct Literals
|
||||
p.resolveBoundStructLiterals()
|
||||
|
||||
// Resolve Struct Pointer Literals
|
||||
p.resolveBoundStructPointerLiterals()
|
||||
|
||||
// Resolve functions that were bound
|
||||
// EG: app.Bind( newBasic() )
|
||||
p.resolveBoundFunctions()
|
||||
|
||||
// Resolve variables that were bound
|
||||
p.resolveBoundVariables()
|
||||
|
||||
return nil
|
||||
}
|
||||
func (p *Parser) resolveBoundStructLiterals() {
|
||||
|
||||
// Resolve struct literals in each package
|
||||
for _, pkg := range p.Packages {
|
||||
pkg.resolveBoundStructLiterals()
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) resolveBoundStructPointerLiterals() {
|
||||
|
||||
// Resolve struct pointer literals
|
||||
for _, pkg := range p.Packages {
|
||||
pkg.resolveBoundStructPointerLiterals()
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) resolveBoundFunctions() {
|
||||
|
||||
// Loop over packages
|
||||
for _, pkg := range p.Packages {
|
||||
|
||||
// Iterate over the method names
|
||||
pkg.structMethodsThatWereBound.Each(func(functionName string) {
|
||||
println("Resolving: ", functionName)
|
||||
// Resolve each method name
|
||||
structName := p.resolveFunctionReturnType(pkg, functionName)
|
||||
|
||||
strct := pkg.Structs[structName]
|
||||
if strct == nil {
|
||||
println("WARNING: Unable to find definition for struct", structName)
|
||||
}
|
||||
strct.IsBound = true
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// resolveFunctionReturnType gets the return type for the given package/function name combination
|
||||
func (p *Parser) resolveFunctionReturnType(pkg *Package, functionName string) string {
|
||||
structName := pkg.functionsThatReturnStructPointers[functionName]
|
||||
if structName == "" {
|
||||
spew.Dump(pkg.functionsThatReturnStructs)
|
||||
structName = pkg.functionsThatReturnStructs[functionName]
|
||||
}
|
||||
if structName == "" {
|
||||
println("WARNING: Unable to resolve bound function", functionName, "in package", pkg.Name)
|
||||
}
|
||||
return structName
|
||||
}
|
||||
|
||||
func (p *Parser) markStructAsBound(pkg *Package, structName string) {
|
||||
strct := pkg.Structs[structName]
|
||||
if strct == nil {
|
||||
println("WARNING: Unable to find definition for struct", structName)
|
||||
}
|
||||
println("Found bound struct:", strct.Name)
|
||||
strct.IsBound = true
|
||||
}
|
||||
|
||||
func (p *Parser) resolveBoundVariables() {
|
||||
|
||||
for _, pkg := range p.Packages {
|
||||
|
||||
// Iterate over the method names
|
||||
pkg.variablesThatWereBound.Each(func(variableName string) {
|
||||
println("Resolving variable: ", variableName)
|
||||
|
||||
var structName string
|
||||
|
||||
// Resolve each method name
|
||||
funcName := pkg.variablesThatWereAssignedByFunctions[variableName]
|
||||
if funcName != "" {
|
||||
// Found function name - resolve Function return type
|
||||
structName = p.resolveFunctionReturnType(pkg, funcName)
|
||||
}
|
||||
|
||||
// If we couldn't resolve to a function, then let's try struct literals
|
||||
if structName == "" {
|
||||
funcName = pkg.variablesThatWereAssignedByStructLiterals[variableName]
|
||||
if funcName != "" {
|
||||
// Found function name - resolve Function return type
|
||||
structName = p.resolveFunctionReturnType(pkg, funcName)
|
||||
}
|
||||
}
|
||||
|
||||
if structName == "" {
|
||||
println("WARNING: Unable to resolve bound variable", variableName, "in package", pkg.Name)
|
||||
return
|
||||
}
|
||||
|
||||
p.markStructAsBound(pkg, structName)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Parser) bindStructByStructName(sn *StructName) {
|
||||
// Get package
|
||||
pkg := p.Packages[sn.Package]
|
||||
if pkg == nil {
|
||||
// Ignore, it will get picked up by the compiler
|
||||
return
|
||||
}
|
||||
|
||||
strct := pkg.Structs[sn.Name]
|
||||
if strct == nil {
|
||||
// Ignore, it will get picked up by the compiler
|
||||
return
|
||||
}
|
||||
|
||||
println("Found bound Struct:", sn.ToString())
|
||||
strct.IsBound = true
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ type StructName struct {
|
||||
Package string
|
||||
}
|
||||
|
||||
// ToString returns a text representation of the struct name
|
||||
// ToString returns a text representation of the struct anme
|
||||
func (s *StructName) ToString() string {
|
||||
result := ""
|
||||
if s.Package != "" {
|
||||
@@ -48,7 +48,7 @@ type Field struct {
|
||||
|
||||
// JSType returns the Javascript type for this field
|
||||
func (f *Field) JSType() string {
|
||||
return goTypeToJS(f)
|
||||
return string(goTypeToJS(f))
|
||||
}
|
||||
|
||||
// TypeAsTSType converts the Field type to something TS wants
|
||||
|
||||
Reference in New Issue
Block a user