mirror of
https://github.com/taigrr/wails.git
synced 2026-04-13 18:38:11 -07:00
Reworked project parser *working*
This commit is contained in:
55
v2/pkg/parser/applicationVariable.go
Normal file
55
v2/pkg/parser/applicationVariable.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
func (p *Parser) getApplicationVariableName(pkg *packages.Package, wailsImportName string) (string, bool) {
|
||||
|
||||
var applicationVariableName = ""
|
||||
|
||||
// Iterate through the whole package looking for the application name
|
||||
for _, fileAst := range pkg.Syntax {
|
||||
ast.Inspect(fileAst, func(n ast.Node) bool {
|
||||
// Parse Assignments looking for application name
|
||||
if assignStmt, ok := n.(*ast.AssignStmt); ok {
|
||||
|
||||
// Check the RHS is of the form:
|
||||
// `app := wails.CreateApp()` or
|
||||
// `app := wails.CreateAppWithOptions`
|
||||
for _, rhs := range assignStmt.Rhs {
|
||||
ce, ok := rhs.(*ast.CallExpr)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
se, ok := ce.Fun.(*ast.SelectorExpr)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
i, ok := se.X.(*ast.Ident)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
// Have we found the wails import name?
|
||||
if i.Name == wailsImportName {
|
||||
// Check we are calling a function to create the app
|
||||
if se.Sel.Name == "CreateApp" || se.Sel.Name == "CreateAppWithOptions" {
|
||||
if len(assignStmt.Lhs) == 1 {
|
||||
i, ok := assignStmt.Lhs[0].(*ast.Ident)
|
||||
if ok {
|
||||
// Found the app variable name
|
||||
applicationVariableName = i.Name
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
return applicationVariableName, applicationVariableName != ""
|
||||
}
|
||||
155
v2/pkg/parser/boundStructs.go
Normal file
155
v2/pkg/parser/boundStructs.go
Normal file
@@ -0,0 +1,155 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
func (p *Parser) getImportByName(pkg *packages.Package, importName string) *packages.Package {
|
||||
// Find package path
|
||||
for _, imp := range pkg.Imports {
|
||||
if imp.Name == importName {
|
||||
return imp
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) findBoundStructsInPackage(pkg *packages.Package, applicationVariableName string) []*StructReference {
|
||||
|
||||
var boundStructs []*StructReference
|
||||
|
||||
// Iterate through the whole package looking for the bound structs
|
||||
for _, fileAst := range pkg.Syntax {
|
||||
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))
|
||||
// println("Found bound function:", fn.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)
|
||||
|
||||
// strct := p.getFunctionReturnType(packageName, functionName)
|
||||
// if strct == nil {
|
||||
// // Unable to resolve function
|
||||
// return true
|
||||
// }
|
||||
// boundStructs = append(boundStructs, strct)
|
||||
// }
|
||||
|
||||
// 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:
|
||||
boundStruct := newStructReference(pkg.Name, boundStructExp.Name)
|
||||
boundStructs = append(boundStructs, boundStruct)
|
||||
|
||||
// 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 := p.getImportByName(pkg, packageName)
|
||||
boundStruct := newStructReference(referencedPackage.Name, structName)
|
||||
boundStructs = append(boundStructs, boundStruct)
|
||||
}
|
||||
|
||||
// Binding struct literals
|
||||
case *ast.CompositeLit:
|
||||
switch literal := boundItem.Type.(type) {
|
||||
|
||||
// app.Bind( myStruct{} )
|
||||
case *ast.Ident:
|
||||
structName := literal.Name
|
||||
boundStruct := newStructReference(pkg.Name, structName)
|
||||
boundStructs = append(boundStructs, boundStruct)
|
||||
|
||||
// app.Bind( mypackage.myStruct{} )
|
||||
case *ast.SelectorExpr:
|
||||
var structName = ""
|
||||
var packageName = ""
|
||||
switch x := literal.X.(type) {
|
||||
case *ast.Ident:
|
||||
packageName = x.Name
|
||||
default:
|
||||
// TODO: Save these warnings
|
||||
// println("Identifier in binding not supported:")
|
||||
return true
|
||||
}
|
||||
structName = literal.Sel.Name
|
||||
|
||||
referencedPackage := p.getImportByName(pkg, packageName)
|
||||
boundStruct := newStructReference(referencedPackage.Name, structName)
|
||||
boundStructs = append(boundStructs, boundStruct)
|
||||
}
|
||||
|
||||
default:
|
||||
// TODO: Save these warnings
|
||||
// println("Unsupported bind expression:")
|
||||
// spew.Dump(boundItem)
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
}
|
||||
return boundStructs
|
||||
}
|
||||
21
v2/pkg/parser/comments.go
Normal file
21
v2/pkg/parser/comments.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (p *Parser) parseComments(comments *ast.CommentGroup) []string {
|
||||
var result []string
|
||||
|
||||
if comments == nil {
|
||||
return result
|
||||
}
|
||||
|
||||
for _, comment := range comments.List {
|
||||
commentText := strings.TrimPrefix(comment.Text, "//")
|
||||
result = append(result, commentText)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
112
v2/pkg/parser/field.go
Normal file
112
v2/pkg/parser/field.go
Normal file
@@ -0,0 +1,112 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
)
|
||||
|
||||
// Field defines a parsed struct field
|
||||
type Field struct {
|
||||
Name string
|
||||
Type string
|
||||
Struct *Struct
|
||||
Comments []string
|
||||
|
||||
// This struct reference is to temporarily hold the name
|
||||
// of the struct during parsing
|
||||
structReference *StructReference
|
||||
}
|
||||
|
||||
func (p *Parser) parseField(field *ast.Field, thisPackageName string) ([]*Field, error) {
|
||||
var result []*Field
|
||||
|
||||
var fieldType string
|
||||
var structReference *StructReference
|
||||
|
||||
// Determine type
|
||||
switch t := field.Type.(type) {
|
||||
case *ast.Ident:
|
||||
fieldType = t.Name
|
||||
case *ast.StarExpr:
|
||||
fieldType = "struct"
|
||||
packageName, structName, err := p.parseStructNameFromStarExpr(t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If we don't ahve a package name, it means it's in this package
|
||||
if packageName == "" {
|
||||
packageName = thisPackageName
|
||||
}
|
||||
|
||||
// Temporarily store the struct reference
|
||||
structReference = newStructReference(packageName, structName)
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("Unsupported field found in struct: %+v", t)
|
||||
}
|
||||
|
||||
// Loop over names if we have
|
||||
if len(field.Names) > 0 {
|
||||
for _, name := range field.Names {
|
||||
|
||||
// Create a field per name
|
||||
thisField := &Field{
|
||||
Comments: p.parseComments(field.Doc),
|
||||
}
|
||||
thisField.Name = name.Name
|
||||
thisField.Type = fieldType
|
||||
thisField.structReference = structReference
|
||||
|
||||
result = append(result, thisField)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// When we have no name
|
||||
thisField := &Field{
|
||||
Comments: p.parseComments(field.Doc),
|
||||
}
|
||||
thisField.Type = fieldType
|
||||
thisField.structReference = structReference
|
||||
|
||||
result = append(result, thisField)
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (p *Parser) resolveFieldReferences(fields []*Field) error {
|
||||
|
||||
// Loop over fields
|
||||
for _, field := range fields {
|
||||
|
||||
// If we have a struct reference but no actual struct,
|
||||
// we need to resolve it
|
||||
if field.structReference != nil && field.Struct == nil {
|
||||
fqn := field.structReference.FullyQualifiedName()
|
||||
println("Need to resolve struct reference: ", fqn)
|
||||
// Check the cache for the struct
|
||||
structPointer, err := p.ParseStruct(field.structReference.Package, field.structReference.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
field.Struct = structPointer
|
||||
if field.Struct != nil {
|
||||
// Save the fact that the struct is used as data
|
||||
field.Struct.UsedAsData = true
|
||||
println("Resolved struct reference:", fqn)
|
||||
|
||||
// Resolve *its* references
|
||||
err = p.resolveStructReferences(field.Struct)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
println("Unable to resolve struct reference:", fqn)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
5
v2/pkg/parser/functions.go
Normal file
5
v2/pkg/parser/functions.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package parser
|
||||
|
||||
func (p *Parser) getFunctionReturnType(packageName string, functionName string) *Struct {
|
||||
return nil
|
||||
}
|
||||
106
v2/pkg/parser/method.go
Normal file
106
v2/pkg/parser/method.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Method defines a struct method
|
||||
type Method struct {
|
||||
Name string
|
||||
Comments []string
|
||||
Inputs []*Field
|
||||
Returns []*Field
|
||||
}
|
||||
|
||||
func (p *Parser) parseStructMethods(boundStruct *Struct) error {
|
||||
for _, fileAst := range boundStruct.Package.Syntax {
|
||||
|
||||
// Track errors
|
||||
var parseError error
|
||||
|
||||
ast.Inspect(fileAst, func(n ast.Node) bool {
|
||||
|
||||
if funcDecl, ok := n.(*ast.FuncDecl); ok {
|
||||
|
||||
if funcDecl.Recv == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
// This is a struct method
|
||||
for _, field := range funcDecl.Recv.List {
|
||||
switch f := field.Type.(type) {
|
||||
case *ast.StarExpr:
|
||||
// This is a struct pointer method
|
||||
ident, ok := f.X.(*ast.Ident) // _ ?
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// Check this method is for this struct
|
||||
if ident.Name != boundStruct.Name {
|
||||
continue
|
||||
}
|
||||
|
||||
// We want to ignore Internal functions
|
||||
if p.internalMethods.Contains(funcDecl.Name.Name) {
|
||||
continue
|
||||
}
|
||||
|
||||
// If this method is not Public, ignore
|
||||
if string(funcDecl.Name.Name[0]) != strings.ToUpper((string(funcDecl.Name.Name[0]))) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Create our struct
|
||||
structMethod := &Method{
|
||||
Name: funcDecl.Name.Name,
|
||||
Comments: p.parseComments(funcDecl.Doc),
|
||||
}
|
||||
|
||||
// Save the input parameters
|
||||
if funcDecl.Type.Params != nil {
|
||||
for _, inputField := range funcDecl.Type.Params.List {
|
||||
fields, err := p.parseField(inputField, boundStruct.Package.Name)
|
||||
if err != nil {
|
||||
parseError = err
|
||||
return false
|
||||
}
|
||||
|
||||
structMethod.Inputs = append(structMethod.Inputs, fields...)
|
||||
}
|
||||
}
|
||||
|
||||
// Save the output parameters
|
||||
if funcDecl.Type.Results != nil {
|
||||
for _, outputField := range funcDecl.Type.Results.List {
|
||||
fields, err := p.parseField(outputField, boundStruct.Package.Name)
|
||||
if err != nil {
|
||||
parseError = err
|
||||
return false
|
||||
}
|
||||
|
||||
structMethod.Returns = append(structMethod.Returns, fields...)
|
||||
}
|
||||
}
|
||||
|
||||
// Append this method to the parsed struct
|
||||
boundStruct.Methods = append(boundStruct.Methods, structMethod)
|
||||
|
||||
default:
|
||||
// Unsupported
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
// If we got an error, return it
|
||||
if parseError != nil {
|
||||
return parseError
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
93
v2/pkg/parser/parseStruct.go
Normal file
93
v2/pkg/parser/parseStruct.go
Normal file
@@ -0,0 +1,93 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
)
|
||||
|
||||
// getCachedStruct attempts to get an already parsed struct from the
|
||||
// struct cache
|
||||
func (p *Parser) getCachedStruct(packageName string, structName string) *Struct {
|
||||
fqn := packageName + "." + structName
|
||||
return p.parsedStructs[fqn]
|
||||
}
|
||||
|
||||
// ParseStruct will attempt to parse the given struct using
|
||||
// the package it references
|
||||
func (p *Parser) ParseStruct(packageName string, structName string) (*Struct, error) {
|
||||
|
||||
// Check the cache
|
||||
result := p.getCachedStruct(packageName, structName)
|
||||
if result != nil {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// Find the package
|
||||
pkg := p.getPackageByName(packageName)
|
||||
if pkg == nil {
|
||||
// TODO: Find package via imports?
|
||||
println("Cannot find package", packageName)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Iterate through the whole package looking for the bound structs
|
||||
for _, fileAst := range pkg.Syntax {
|
||||
|
||||
// Track errors
|
||||
var parseError error
|
||||
|
||||
ast.Inspect(fileAst, func(n ast.Node) bool {
|
||||
if genDecl, ok := n.(*ast.GenDecl); ok {
|
||||
for _, spec := range genDecl.Specs {
|
||||
if typeSpec, ok := spec.(*ast.TypeSpec); ok {
|
||||
if structType, ok := typeSpec.Type.(*ast.StructType); ok {
|
||||
structDefinitionName := typeSpec.Name.Name
|
||||
if structDefinitionName == structName {
|
||||
|
||||
// Create the new struct
|
||||
result = p.newStruct(pkg, structDefinitionName)
|
||||
|
||||
// Save comments
|
||||
result.Comments = p.parseComments(genDecl.Doc)
|
||||
|
||||
parseError = p.parseStructMethods(result)
|
||||
if parseError != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// Parse the struct fields
|
||||
parseError = p.parseStructFields(structType, result)
|
||||
|
||||
// Cache this struct
|
||||
key := result.FullyQualifiedName()
|
||||
p.parsedStructs[key] = result
|
||||
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
// If we got an error, return it
|
||||
if parseError != nil {
|
||||
return nil, parseError
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseStructFields(structType *ast.StructType, boundStruct *Struct) error {
|
||||
|
||||
// Parse the fields
|
||||
for _, field := range structType.Fields.List {
|
||||
fields, err := p.parseField(field, boundStruct.Package.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
boundStruct.Fields = append(boundStruct.Fields, fields...)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
168
v2/pkg/parser/parser.go
Normal file
168
v2/pkg/parser/parser.go
Normal file
@@ -0,0 +1,168 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/token"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
"github.com/leaanthony/slicer"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
type Parser struct {
|
||||
|
||||
// Placeholders for Go's parser
|
||||
goPackages []*packages.Package
|
||||
fileSet *token.FileSet
|
||||
internalMethods *slicer.StringSlicer
|
||||
|
||||
// This is a map of structs that have been parsed
|
||||
// The key is <package>.<structname>
|
||||
parsedStructs map[string]*Struct
|
||||
|
||||
// The list of struct names that are bound
|
||||
BoundStructReferences []*StructReference
|
||||
|
||||
// The list of structs that are bound
|
||||
BoundStructs []*Struct
|
||||
}
|
||||
|
||||
func NewParser() *Parser {
|
||||
return &Parser{
|
||||
fileSet: token.NewFileSet(),
|
||||
internalMethods: slicer.String([]string{"WailsInit", "WailsShutdown"}),
|
||||
parsedStructs: make(map[string]*Struct),
|
||||
}
|
||||
}
|
||||
|
||||
// ParseProject will parse the Wails project in the given directory
|
||||
func (p *Parser) ParseProject(dir string) error {
|
||||
|
||||
var err error
|
||||
|
||||
err = p.loadPackages(dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = p.findBoundStructs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = p.parseBoundStructs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
spew.Dump(p.BoundStructs)
|
||||
println("******* Parsed Structs *******")
|
||||
fmt.Printf("%+v\n", p.parsedStructs)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (p *Parser) loadPackages(projectPath string) error {
|
||||
mode := packages.NeedName |
|
||||
packages.NeedFiles |
|
||||
packages.NeedSyntax |
|
||||
packages.NeedTypes |
|
||||
packages.NeedImports |
|
||||
packages.NeedTypesInfo
|
||||
|
||||
cfg := &packages.Config{Fset: p.fileSet, Mode: mode, Dir: projectPath}
|
||||
pkgs, err := packages.Load(cfg, "./...")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Problem loading packages")
|
||||
}
|
||||
// Check for errors
|
||||
var parseError error
|
||||
for _, pkg := range pkgs {
|
||||
for _, err := range pkg.Errors {
|
||||
if parseError == nil {
|
||||
parseError = errors.New(err.Error())
|
||||
} else {
|
||||
parseError = errors.Wrap(parseError, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if parseError != nil {
|
||||
return parseError
|
||||
}
|
||||
|
||||
p.goPackages = pkgs
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) getPackageByName(packageName string) *packages.Package {
|
||||
for _, pkg := range p.goPackages {
|
||||
if pkg.Name == packageName {
|
||||
return pkg
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) getWailsImportName(pkg *packages.Package) (string, bool) {
|
||||
// Scan the imports for the wails v2 import
|
||||
for key, details := range pkg.Imports {
|
||||
if key == "github.com/wailsapp/wails/v2" {
|
||||
return details.Name, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
// findBoundStructs will search through the Wails project looking
|
||||
// for which structs have been bound using the `Bind()` method
|
||||
func (p *Parser) findBoundStructs() error {
|
||||
|
||||
// Try each of the packages to find the Bind() calls
|
||||
for _, pkg := range p.goPackages {
|
||||
|
||||
// Does this package import Wails?
|
||||
wailsImportName, imported := p.getWailsImportName(pkg)
|
||||
if !imported {
|
||||
continue
|
||||
}
|
||||
|
||||
// Do we create an app using CreateApp?
|
||||
appVariableName, created := p.getApplicationVariableName(pkg, wailsImportName)
|
||||
if !created {
|
||||
continue
|
||||
}
|
||||
|
||||
boundStructReferences := p.findBoundStructsInPackage(pkg, appVariableName)
|
||||
p.BoundStructReferences = append(p.BoundStructReferences, boundStructReferences...)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) parseBoundStructs() error {
|
||||
|
||||
// Iterate the structs
|
||||
for _, boundStructReference := range p.BoundStructReferences {
|
||||
// Parse the struct
|
||||
boundStruct, err := p.ParseStruct(boundStructReference.Package, boundStructReference.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.BoundStructs = append(p.BoundStructs, boundStruct)
|
||||
}
|
||||
|
||||
// Resolve the references between the structs
|
||||
// This is when a field of one struct is a struct type
|
||||
for _, boundStruct := range p.BoundStructs {
|
||||
err := p.resolveStructReferences(boundStruct)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
46
v2/pkg/parser/parser_test.go
Normal file
46
v2/pkg/parser/parser_test.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/leaanthony/slicer"
|
||||
"github.com/matryer/is"
|
||||
"github.com/wailsapp/wails/v2/internal/fs"
|
||||
)
|
||||
|
||||
func TestParser(t *testing.T) {
|
||||
|
||||
is := is.New(t)
|
||||
|
||||
// Local project dir
|
||||
projectDir := fs.RelativePath("./testproject")
|
||||
|
||||
p := NewParser()
|
||||
|
||||
// Check parsing worked
|
||||
err := p.ParseProject(projectDir)
|
||||
is.NoErr(err)
|
||||
|
||||
// Expected structs
|
||||
expectedBoundStructs := slicer.String()
|
||||
expectedBoundStructs.Add("main.Basic", "mypackage.Manager")
|
||||
|
||||
// We expect these to be the same length
|
||||
is.Equal(expectedBoundStructs.Length(), len(p.BoundStructs))
|
||||
|
||||
// Check bound structs
|
||||
for _, boundStruct := range p.BoundStructs {
|
||||
|
||||
// Check the names are correct
|
||||
fqn := boundStruct.FullyQualifiedName()
|
||||
is.True(expectedBoundStructs.Contains(fqn))
|
||||
|
||||
// Check that the structs have comments
|
||||
is.True(len(boundStruct.Comments) > 0)
|
||||
|
||||
// Check that the structs have methods
|
||||
is.True(len(boundStruct.Methods) > 0)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
109
v2/pkg/parser/struct.go
Normal file
109
v2/pkg/parser/struct.go
Normal file
@@ -0,0 +1,109 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
|
||||
"golang.org/x/tools/go/packages"
|
||||
)
|
||||
|
||||
type Struct struct {
|
||||
Package *packages.Package
|
||||
Name string
|
||||
Comments []string
|
||||
Fields []*Field
|
||||
Methods []*Method
|
||||
|
||||
// This is true when this struct is used as a datatype
|
||||
UsedAsData bool
|
||||
}
|
||||
|
||||
// newStruct creates a new struct and stores in the cache
|
||||
func (p *Parser) newStruct(pkg *packages.Package, name string) *Struct {
|
||||
|
||||
result := &Struct{
|
||||
Package: pkg,
|
||||
Name: name,
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// FullyQualifiedName returns the fully qualified name of this struct
|
||||
func (s *Struct) FullyQualifiedName() string {
|
||||
return s.Package.Name + "." + s.Name
|
||||
}
|
||||
|
||||
func (p *Parser) parseStructNameFromStarExpr(starExpr *ast.StarExpr) (string, string, error) {
|
||||
pkg := ""
|
||||
name := ""
|
||||
// Determine the FQN
|
||||
switch x := starExpr.X.(type) {
|
||||
case *ast.SelectorExpr:
|
||||
switch i := x.X.(type) {
|
||||
case *ast.Ident:
|
||||
pkg = i.Name
|
||||
default:
|
||||
return "", "", fmt.Errorf("Unsupported Selector expression: %+v", i)
|
||||
}
|
||||
|
||||
name = x.Sel.Name
|
||||
|
||||
case *ast.StarExpr:
|
||||
switch s := x.X.(type) {
|
||||
case *ast.Ident:
|
||||
name = s.Name
|
||||
default:
|
||||
return "", "", fmt.Errorf("Unsupported Star expression: %+v", s)
|
||||
}
|
||||
case *ast.Ident:
|
||||
name = x.Name
|
||||
default:
|
||||
return "", "", fmt.Errorf("Unsupported Star.X expression: %+v", x)
|
||||
}
|
||||
return pkg, name, nil
|
||||
}
|
||||
|
||||
// StructReference defines a reference to a fully qualified struct
|
||||
type StructReference struct {
|
||||
Package string
|
||||
Name string
|
||||
}
|
||||
|
||||
func newStructReference(packageName string, structName string) *StructReference {
|
||||
return &StructReference{Package: packageName, Name: structName}
|
||||
}
|
||||
|
||||
// FullyQualifiedName returns a string representing the struct reference
|
||||
func (s *StructReference) FullyQualifiedName() string {
|
||||
return s.Package + "." + s.Name
|
||||
}
|
||||
|
||||
func (p *Parser) resolveStructReferences(boundStruct *Struct) error {
|
||||
|
||||
var err error
|
||||
|
||||
// Resolve field references
|
||||
err = p.resolveFieldReferences(boundStruct.Fields)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check if method fields need resolving
|
||||
for _, method := range boundStruct.Methods {
|
||||
|
||||
// Resolve method inputs
|
||||
err = p.resolveFieldReferences(method.Inputs)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Resolve method outputs
|
||||
err = p.resolveFieldReferences(method.Returns)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
59
v2/pkg/parser/testproject/basic.go
Normal file
59
v2/pkg/parser/testproject/basic.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
wails "github.com/wailsapp/wails/v2"
|
||||
)
|
||||
|
||||
// Basic application struct
|
||||
type Basic struct {
|
||||
runtime *wails.Runtime
|
||||
}
|
||||
|
||||
// // Another application struct
|
||||
// type Another struct {
|
||||
// runtime *wails.Runtime
|
||||
// }
|
||||
|
||||
// func (a *Another) Doit() {
|
||||
|
||||
// }
|
||||
|
||||
// // newBasicPointer creates a new Basic application struct
|
||||
// func newBasicPointer() *Basic {
|
||||
// return &Basic{}
|
||||
// }
|
||||
|
||||
// // newBasic creates a new Basic application struct
|
||||
// func newBasic() Basic {
|
||||
// return Basic{}
|
||||
// }
|
||||
|
||||
// WailsInit is called at application startup
|
||||
func (b *Basic) WailsInit(runtime *wails.Runtime) error {
|
||||
// Perform your setup here
|
||||
b.runtime = runtime
|
||||
runtime.Window.SetTitle("jsbundle")
|
||||
return nil
|
||||
}
|
||||
|
||||
// WailsShutdown is called at application termination
|
||||
func (b *Basic) WailsShutdown() {
|
||||
// Perform your teardown here
|
||||
}
|
||||
|
||||
// // NewPerson creates a new person
|
||||
// func (b *Basic) NewPerson(name string, age int) *mypackage.Person {
|
||||
// return &mypackage.Person{Name: name, Age: age}
|
||||
// }
|
||||
|
||||
// Greet returns a greeting for the given name
|
||||
func (b *Basic) Greet(name string) string {
|
||||
return fmt.Sprintf("Hello %s!", name)
|
||||
}
|
||||
|
||||
// // RemovePerson Removes the given person
|
||||
// func (b *Basic) RemovePerson(p *mypackage.Person) {
|
||||
// // dummy
|
||||
// }
|
||||
9
v2/pkg/parser/testproject/go.mod
Normal file
9
v2/pkg/parser/testproject/go.mod
Normal file
@@ -0,0 +1,9 @@
|
||||
module testproject
|
||||
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/wailsapp/wails/v2 v2.0.0-alpha
|
||||
)
|
||||
|
||||
replace github.com/wailsapp/wails/v2 v2.0.0-alpha => /home/lea/Data/projects/wails/v2
|
||||
83
v2/pkg/parser/testproject/go.sum
Normal file
83
v2/pkg/parser/testproject/go.sum
Normal file
@@ -0,0 +1,83 @@
|
||||
github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgkuj+NQRlZcDbAbM1ORAbXjXX77sX7T289U=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
||||
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
|
||||
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA=
|
||||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0=
|
||||
github.com/leaanthony/gosod v0.0.4/go.mod h1:nGMCb1PJfXwBDbOAike78jEYlpqge+xUKFf0iBKjKxU=
|
||||
github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
|
||||
github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/tdewolff/minify v2.3.6+incompatible/go.mod h1:9Ov578KJUmAWpS6NeZwRZyT56Uf6o3Mcz9CEsg8USYs=
|
||||
github.com/tdewolff/minify/v2 v2.9.5/go.mod h1:jshtBj/uUJH6JX1fuxTLnnHOA1RVJhF5MM+leJzDKb4=
|
||||
github.com/tdewolff/parse v2.3.4+incompatible/go.mod h1:8oBwCsVmUkgHO8M5iCzSIDtpzXOT0WXX9cWhz+bIzJQ=
|
||||
github.com/tdewolff/parse/v2 v2.5.3/go.mod h1:WzaJpRSbwq++EIQHYIRTpbYKNA3gn9it1Ik++q4zyho=
|
||||
github.com/tdewolff/test v1.0.6/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/xyproto/xpm v1.2.1/go.mod h1:cMnesLsD0PBXLgjDfTDEaKr8XyTFsnP1QycSqRw7BiY=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
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/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0=
|
||||
21
v2/pkg/parser/testproject/main.go
Normal file
21
v2/pkg/parser/testproject/main.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testproject/mypackage"
|
||||
|
||||
"github.com/wailsapp/wails/v2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Create application with options
|
||||
app := wails.CreateApp("jsbundle", 1024, 768)
|
||||
|
||||
/***** Struct Literal *****/
|
||||
|
||||
// Local struct pointer literal *WORKING*
|
||||
app.Bind(&Basic{})
|
||||
|
||||
// External struct pointer literal
|
||||
app.Bind(&mypackage.Manager{})
|
||||
|
||||
}
|
||||
36
v2/pkg/parser/testproject/mypackage/mypackage.go
Normal file
36
v2/pkg/parser/testproject/mypackage/mypackage.go
Normal file
@@ -0,0 +1,36 @@
|
||||
// Package mypackage does all the things a mypackage can do
|
||||
package mypackage
|
||||
|
||||
type Address struct {
|
||||
Number int
|
||||
Street string
|
||||
Town string
|
||||
Postcode string
|
||||
}
|
||||
|
||||
// Person defines a Person in the application
|
||||
type Person struct {
|
||||
// Name is a name
|
||||
Name string
|
||||
Age int
|
||||
Address *Address
|
||||
}
|
||||
|
||||
// Manager is the Mr Manager
|
||||
type Manager struct {
|
||||
Name string
|
||||
TwoIC *Person
|
||||
}
|
||||
|
||||
// Hire me some peoples!
|
||||
func (m *Manager) Hire(name, test string, bob int) *Person {
|
||||
return &Person{Name: name}
|
||||
}
|
||||
|
||||
// func NewManagerPointer() *Manager {
|
||||
// return &Manager{}
|
||||
// }
|
||||
|
||||
// func NewManager() Manager {
|
||||
// return Manager{}
|
||||
// }
|
||||
Reference in New Issue
Block a user