Support generating enums from imported package

This commit is contained in:
Lea Anthony 2023-12-20 08:06:35 +11:00
commit cdf4bdd2ba
No known key found for this signature in database
GPG key ID: 33DAF7BB90A58405
9 changed files with 105 additions and 67 deletions

View file

@ -46,8 +46,7 @@ func TestGenerateBindings(t *testing.T) {
{
"testdata/enum_from_imported_package",
map[string]string{
"main": getFile("testdata/enum_from_imported_package/bindings_main.js"),
"services": getFile("testdata/enum_from_imported_package/bindings_services.js"),
"main": getFile("testdata/enum_from_imported_package/bindings_main.js"),
},
true,
},

View file

@ -58,7 +58,7 @@ func pkgAlias(fullPkg string) string {
}
func GenerateModels(models map[packagePath]map[structName]*StructDef, enums map[packagePath]map[string]*TypeDef, options *flags.GenerateBindingsOptions) (string, error) {
if models == nil {
if models == nil && enums == nil {
return "", nil
}
@ -71,6 +71,9 @@ func GenerateModels(models map[packagePath]map[structName]*StructDef, enums map[
for pkg := range models {
keys = append(keys, pkg)
}
for pkg := range enums {
keys = append(keys, pkg)
}
sort.Slice(keys, func(i, j int) bool {
return pkgAlias(keys[i]) < pkgAlias(keys[j])

View file

@ -99,6 +99,18 @@ func TestGenerateModels(t *testing.T) {
dir: "testdata/enum",
want: getFile("testdata/enum/models.js"),
},
{
name: "enum from imported package",
dir: "testdata/enum_from_imported_package",
want: getFile("testdata/enum_from_imported_package/models.ts"),
useTypescript: true,
},
{
name: "enum from imported package",
dir: "testdata/enum_from_imported_package",
want: getFile("testdata/enum_from_imported_package/models.js"),
useTypescript: false,
},
{
name: "enum interface",
dir: "testdata/enum-interface",

View file

@ -403,6 +403,7 @@ func (p *Project) parseDirectory(dir string) (map[string]*ParsedPackage, error)
StructCache: make(map[structName]*StructDef),
TypeCache: make(map[string]*TypeDef),
}
p.parseTypes(map[string]*ParsedPackage{packageName: parsedPackage})
p.packageCache[packageName] = parsedPackage
result[packageName] = parsedPackage
}
@ -413,6 +414,8 @@ func (p *Project) findApplicationNewCalls(pkgs map[string]*ParsedPackage) (err e
var callFound bool
p.parseTypes(pkgs)
for _, pkg := range pkgs {
thisPackage := pkg.Pkg
// Iterate through the package's files
@ -701,6 +704,14 @@ func (p *Project) parseParameterType(field *ast.Field, pkg *ParsedPackage) *Para
log.Fatal(err)
}
result.IsStruct = p.getStructDef(t.Sel.Name, extPackage)
if !result.IsStruct {
// Check if it's a type alias
typeDef, ok := extPackage.TypeCache[t.Sel.Name]
if ok {
typeDef.ShouldGenerate = true
result.IsEnum = true
}
}
result.Package = extPackage.Path
case *ast.ArrayType:
result.IsSlice = true
@ -814,8 +825,13 @@ func (p *Project) getParsedPackageFromName(packageName string, currentPackage *P
Path: path,
Dir: dir,
StructCache: make(map[string]*StructDef),
TypeCache: make(map[string]*TypeDef),
}
p.packageCache[path] = result
// Parse types
p.parseTypes(map[string]*ParsedPackage{path: result})
return result, nil
}
}
@ -832,7 +848,7 @@ func getPackageDir(importPath string) (string, error) {
}
func (p *Project) getPackageFromPath(packagedir string, packagepath string) (*ast.Package, error) {
impPkg, err := parser.ParseDir(token.NewFileSet(), packagedir, nil, parser.AllErrors)
impPkg, err := parser.ParseDir(token.NewFileSet(), packagedir, nil, parser.AllErrors|parser.ParseComments)
if err != nil {
return nil, err
}
@ -1074,6 +1090,42 @@ func (p *Project) RelativePackageDir(path string) string {
return strings.TrimPrefix(path, p.Path)
}
func (p *Project) parseTypes(pkgs map[string]*ParsedPackage) {
for _, pkg := range pkgs {
thisPackage := pkg.Pkg
// Iterate through the package's files
for _, file := range thisPackage.Files {
// Use an ast.Inspector to find the calls to application.New
ast.Inspect(file, func(n ast.Node) bool {
// Check for const declaration
genDecl, ok := n.(*ast.GenDecl)
if ok {
switch genDecl.Tok {
case token.TYPE:
var comments []string
if genDecl.Doc != nil {
comments = CommentGroupToText(genDecl.Doc)
}
for _, spec := range genDecl.Specs {
if typeSpec, ok := spec.(*ast.TypeSpec); ok {
p.parseTypeDeclaration(typeSpec, pkg, comments)
}
}
case token.CONST:
p.parseConstDeclaration(genDecl, pkg)
default:
}
return true
}
return true
})
}
p.addTypes(pkg.Path, pkg.TypeCache)
}
}
func getTypeString(expr ast.Expr) string {
switch t := expr.(type) {
case *ast.Ident:

View file

@ -2,13 +2,17 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
/**
* @typedef {import('./models').services.Title} servicesTitle
*/
export const GreetService = {
/**
* GreetService.Greet
* Greet does XYZ
* @param name {string}
* @param title {Title}
* @param title {servicesTitle}
* @returns {Promise<string>}
**/
Greet: function(name, title) { return wails.CallByID(1411160069, ...Array.prototype.slice.call(arguments, 0)); },

View file

@ -2,13 +2,17 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
/**
* @typedef {import('./models').services.Title} servicesTitle
*/
export const GreetService = {
/**
* GreetService.Greet
* Greet does XYZ
* @param name {string}
* @param title {Title}
* @param title {servicesTitle}
* @returns {Promise<string>}
**/
Greet: function(name, title) { return wails.CallByName("main.GreetService.Greet", ...Array.prototype.slice.call(arguments, 0)); },

View file

@ -1,22 +0,0 @@
// @ts-check
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
/**
* @typedef {import('./models').services.Address} servicesAddress
*/
window.go = window.go || {};
window.go.services = {
OtherService: {
/**
* OtherService.Yay
*
*
* @returns {Promise<servicesAddress>}
**/
Yay: function() { return wails.CallByID(302702907, ...Array.prototype.slice.call(arguments, 0)); },
},
};

View file

@ -0,0 +1,17 @@
// @ts-check
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
// Defining the services namespace
export const services = {};
// Simulating the enum with an object
services.Title = {
// Mister is a title
Mister: "Mr",
Miss: "Miss",
Ms: "Ms",
Mrs: "Mrs",
Dr: "Dr",
};

View file

@ -2,46 +2,15 @@
// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL
// This file is automatically generated. DO NOT EDIT
export namespace main {
export class Person {
name: string;
address: services.Address;
constructor(source: Partial<Person> = {}) {
const { name = "", address = null } = source;
this.name = name;
this.address = address;
}
static createFrom(source: string | object = {}): Person {
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
return new Person(parsedSource as Partial<Person>);
}
}
}
export namespace services {
export class Address {
street: string;
state: string;
country: string;
constructor(source: Partial<Address> = {}) {
const { street = "", state = "", country = "" } = source;
this.street = street;
this.state = state;
this.country = country;
}
static createFrom(source: string | object = {}): Address {
let parsedSource = typeof source === 'string' ? JSON.parse(source) : source;
return new Address(parsedSource as Partial<Address>);
}
export enum Title {
// Mister is a title
Mister = "Mr",
Miss = "Miss",
Ms = "Ms",
Mrs = "Mrs",
Dr = "Dr",
}
}
}