mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-04 05:20:00 +08:00

* 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
153 lines
3.6 KiB
Go
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
|
|
}
|