5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-04 03:10:22 +08:00
wails/v2/pkg/parser/findBoundStructs.go
Lea Anthony 62374b9b53
Js package generation (#554)
* WIP

* Generation of index.js

* Add RelativeToCwd

* Add JSDoc comments

* Convert to ES6 syntax

* Fix typo

* Initial generation of typescript declarations

* Typescript improvements

* Improved @returns jsdoc

* Improved declaration files

* Simplified output

* Rename file

* Tidy up

* Revert "Simplified output"

This reverts commit 15cdf7382b.

* Now parsing actual code

* Support Array types

* Reimagined parser

* Wrap parsing in Parser

* Rewritten module generator (TS Only)

* Final touches

* Slight refactor to improve output

* Struct comments. External struct literal binding

* Reworked project parser *working*

* remove debug info

* Refactor of parser

* remove the spew

* Better Ts support

* Better project generation logic

* Support local functions in bind()

* JS Object generation. Linting.

* Support json tags in module generation

* Updated mod files

* Support vscode file generation

* Better global.d.ts

* add ts-check to templates

* Support TS declaration files

* improved 'generate' command for module
2020-11-15 09:25:38 +11:00

153 lines
3.6 KiB
Go

package parser
import (
"fmt"
"go/ast"
)
// findBoundStructs will search through the Wails project looking
// for which structs have been bound using the `Bind()` method
func (p *Parser) findBoundStructs(pkg *Package) error {
// Iterate through the files in the package looking for the bound structs
for _, fileAst := range pkg.Gopackage.Syntax {
// Find the wails import name
wailsImportName := pkg.getWailsImportName(fileAst)
// If this file doesn't import wails, continue
if wailsImportName == "" {
continue
}
applicationVariableName := pkg.getApplicationVariableName(fileAst, wailsImportName)
if applicationVariableName == "" {
continue
}
var parseError error
ast.Inspect(fileAst, func(n ast.Node) bool {
// Parse Call expressions looking for bind calls
callExpr, ok := n.(*ast.CallExpr)
if !ok {
return true
}
// Check this is the right kind of expression (something.something())
f, ok := callExpr.Fun.(*ast.SelectorExpr)
if !ok {
return true
}
ident, ok := f.X.(*ast.Ident)
if !ok {
return true
}
if ident.Name != applicationVariableName {
return true
}
if f.Sel.Name != "Bind" {
return true
}
if len(callExpr.Args) != 1 {
return true
}
// Work out what was bound
switch boundItem := callExpr.Args[0].(type) {
// app.Bind( someFunction() )
case *ast.CallExpr:
switch fn := boundItem.Fun.(type) {
case *ast.Ident:
// boundStructs = append(boundStructs, newStruct(pkg.Name, fn.Name))
strct, err := p.getFunctionReturnType(pkg, fn.Name)
if err != nil {
parseError = err
return false
}
if strct == nil {
parseError = fmt.Errorf("unable to resolve function returntype: %s", fn.Name)
return false
}
strct.Package.boundStructs.Add(strct.Name)
case *ast.SelectorExpr:
ident, ok := fn.X.(*ast.Ident)
if !ok {
return true
}
packageName := ident.Name
functionName := fn.Sel.Name
println("Found bound function:", packageName+"."+functionName)
// Get package for package name
externalPackageName := pkg.getImportByName(packageName, fileAst)
externalPackage := p.getPackageByID(externalPackageName.ID)
strct, err := p.getFunctionReturnType(externalPackage, functionName)
if err != nil {
parseError = err
return false
}
if strct == nil {
// Unable to resolve function
return true
}
externalPackage.boundStructs.Add(strct.Name)
}
// Binding struct pointer literals
case *ast.UnaryExpr:
if boundItem.Op.String() != "&" {
return true
}
cl, ok := boundItem.X.(*ast.CompositeLit)
if !ok {
return true
}
switch boundStructExp := cl.Type.(type) {
// app.Bind( &myStruct{} )
case *ast.Ident:
pkg.boundStructs.Add(boundStructExp.Name)
// app.Bind( &mypackage.myStruct{} )
case *ast.SelectorExpr:
var structName = ""
var packageName = ""
switch x := boundStructExp.X.(type) {
case *ast.Ident:
packageName = x.Name
default:
// TODO: Save these warnings
// println("Identifier in binding not supported:")
return true
}
structName = boundStructExp.Sel.Name
referencedPackage := pkg.getImportByName(packageName, fileAst)
packageWrapper := p.getPackageByID(referencedPackage.ID)
packageWrapper.boundStructs.Add(structName)
}
default:
// TODO: Save these warnings
// println("Unsupported bind expression:")
// spew.Dump(boundItem)
}
return true
})
if parseError != nil {
return parseError
}
}
return nil
}