mirror of
https://github.com/wavetermdev/wails.git
synced 2026-08-05 13:53:43 -07:00
Parse structs bound from other packages
This commit is contained in:
@@ -3,10 +3,12 @@ package parser
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/build"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var packageCache = make(map[string]*ParsedPackage)
|
||||
@@ -235,24 +237,16 @@ func (p *Project) findApplicationNewCalls(pkgs map[string]*ParsedPackage) (err e
|
||||
if ok {
|
||||
// Check if the selector is an ident
|
||||
if _, ok := selector.X.(*ast.Ident); ok {
|
||||
//// Check if the ident is a package
|
||||
//if _, ok := context.packages[ident.Name]; !ok {
|
||||
// externalPackage, err := context.getPackageFromPath(ident.Name)
|
||||
// if err != nil {
|
||||
// println("Error getting package from path: " + err.Error())
|
||||
// return true
|
||||
// }
|
||||
// context.packages[ident.Name] = &parsedPackage{
|
||||
// name: ident.Name,
|
||||
// pkg: externalPackage,
|
||||
// boundStructs: make(map[string]*BoundStruct),
|
||||
// }
|
||||
//}
|
||||
//context.packages[ident.Name].boundStructs[selector.Sel.Name] = &BoundStruct{
|
||||
// Name: selector.Sel.Name,
|
||||
//}
|
||||
//p.parseStructFromExternalPackage(selector.Sel.Name, ident.Name, thisPackage)
|
||||
//p.addBoundStruct(ident.Name, selector.Sel.Name)
|
||||
// Look up the package
|
||||
var parsedPackage *ParsedPackage
|
||||
parsedPackage, err = p.getParsedPackageFromName(selector.X.(*ast.Ident).Name, pkg)
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
err = p.parseBoundStructMethods(selector.Sel.Name, parsedPackage)
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
continue
|
||||
}
|
||||
continue
|
||||
@@ -431,6 +425,58 @@ func (p *Project) parseStructFields(structType *ast.StructType, pkg *ParsedPacka
|
||||
return result
|
||||
}
|
||||
|
||||
func (p *Project) getParsedPackageFromName(packageName string, currentPackage *ParsedPackage) (*ParsedPackage, error) {
|
||||
for _, file := range currentPackage.Pkg.Files {
|
||||
for _, imp := range file.Imports {
|
||||
path, err := strconv.Unquote(imp.Path.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_, lastPathElement := filepath.Split(path)
|
||||
if imp.Name != nil && imp.Name.Name == packageName || lastPathElement == packageName {
|
||||
// Get the directory for the package
|
||||
dir, err := getPackageDir(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pkg, err := p.getPackageFromPath(dir, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ParsedPackage{
|
||||
Pkg: pkg,
|
||||
Name: packageName,
|
||||
Dir: dir,
|
||||
structCache: make(map[string]*StructDef),
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("package %s not found in %s", packageName, currentPackage.Name)
|
||||
}
|
||||
|
||||
func getPackageDir(importPath string) (string, error) {
|
||||
pkg, err := build.Import(importPath, "", build.FindOnly)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return pkg.Dir, nil
|
||||
}
|
||||
|
||||
func (p *Project) getPackageFromPath(packagedir string, packagepath string) (*ast.Package, error) {
|
||||
impPkg, err := parser.ParseDir(token.NewFileSet(), packagedir, nil, parser.AllErrors)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for impName, impPkg := range impPkg {
|
||||
if impName == "main" {
|
||||
continue
|
||||
}
|
||||
return impPkg, nil
|
||||
}
|
||||
return nil, fmt.Errorf("package not found in imported package %s", packagepath)
|
||||
}
|
||||
|
||||
func getTypeString(expr ast.Expr) string {
|
||||
switch t := expr.(type) {
|
||||
case *ast.Ident:
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
)
|
||||
|
||||
func TestExternalPackages(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
dir string
|
||||
wantBoundMethods map[string]map[string][]*BoundMethod
|
||||
wantErr bool
|
||||
}{}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := ParseProject(tt.dir)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("ParseDirectory() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if diff := cmp.Diff(tt.wantBoundMethods, got.BoundMethods); diff != "" {
|
||||
t.Errorf("ParseDirectory() failed:\n" + diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -915,12 +915,74 @@ func TestParseDirectory(t *testing.T) {
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
//{
|
||||
// name: "should find multiple bound services over multiple packages",
|
||||
// dir: "testdata/struct_literal_multiple_other",
|
||||
// //wantModels: []string{"main.GreetService", "services.OtherService", "main.Person"},
|
||||
// wantErr: false,
|
||||
//},
|
||||
{
|
||||
name: "should find multiple bound services over multiple packages",
|
||||
dir: "testdata/struct_literal_multiple_other",
|
||||
wantErr: false,
|
||||
wantBoundMethods: map[string]map[string][]*BoundMethod{
|
||||
"main": {
|
||||
"GreetService": {
|
||||
{
|
||||
Name: "Greet",
|
||||
DocComment: "Greet does XYZ\n",
|
||||
Inputs: []*Parameter{
|
||||
{
|
||||
Name: "name",
|
||||
Type: &ParameterType{
|
||||
Name: "string",
|
||||
},
|
||||
},
|
||||
},
|
||||
Outputs: []*Parameter{
|
||||
{
|
||||
Name: "",
|
||||
Type: &ParameterType{
|
||||
Name: "string",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "NewPerson",
|
||||
DocComment: "NewPerson creates a new person\n",
|
||||
Inputs: []*Parameter{
|
||||
{
|
||||
Name: "name",
|
||||
Type: &ParameterType{
|
||||
Name: "string",
|
||||
},
|
||||
},
|
||||
},
|
||||
Outputs: []*Parameter{
|
||||
{
|
||||
Name: "",
|
||||
Type: &ParameterType{
|
||||
Name: "Person",
|
||||
IsPointer: true,
|
||||
IsStruct: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"services": {
|
||||
"OtherService": {
|
||||
{
|
||||
Name: "Yay",
|
||||
Outputs: []*Parameter{
|
||||
{
|
||||
Type: &ParameterType{
|
||||
Name: "int",
|
||||
IsSlice: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user