support dirs

This commit is contained in:
Egor Aristov 2025-10-27 17:29:08 +03:00
parent dfd0bf381f
commit 855d742203
Signed by: egor3f
GPG Key ID: 40482A264AAEC85F
5 changed files with 126 additions and 53 deletions

View File

@ -7,12 +7,8 @@ import (
"fmt"
)
type callable interface {
Call(method string, params ...any) (kittenipc.Vals, error)
}
type TsIpcApi struct {
Ipc callable
Ipc kittenipc.Callable
}
func (t *TsIpcApi) Div(
@ -20,9 +16,10 @@ func (t *TsIpcApi) Div(
) (
int, error,
) {
results, err := t.Ipc.Call("TsIpcApi", "Div", a, b)
results, err := t.Ipc.Call("TsIpcApi.Div", a, b)
if err != nil {
return 0, fmt.Errorf("call to TsIpcApi.Div failed: %w", err)
}
_ = results
return results[0].(int), nil
}

View File

@ -1,13 +1,15 @@
// Code generated by kitcom. DO NOT EDIT.
import { ParentIPC, ChildIPC } from "kitten-ipc";
export default class IpcApi {
private ipc: ParentIPC | ChildIPC;
protected ipc: ParentIPC | ChildIPC;
constructor(ipc: ParentIPC | ChildIPC) {
this.ipc = ipc;
}
async Div(a: number, b: number): Promise<number> {
const results = await this.ipc.call("Div", a, b);
const results = await this.ipc.call("IpcApi.Div", a, b);
return results[0] as number;
}
}

View File

@ -13,12 +13,35 @@ import (
var decorComment = regexp.MustCompile(`^//\s?kittenipc:api$`)
type GoApiParser struct {
files []string
}
func (g *GoApiParser) Parse(sourceFile string) (*api.Api, error) {
func (g *GoApiParser) AddFile(path string) {
g.files = append(g.files, path)
}
func (g *GoApiParser) Parse() (*api.Api, error) {
var apis api.Api
for _, f := range g.files {
endpoints, err := g.parseFile(f)
if err != nil {
return nil, fmt.Errorf("parse file: %w", err)
}
apis.Endpoints = append(apis.Endpoints, endpoints...)
}
if len(apis.Endpoints) == 0 {
return nil, fmt.Errorf("no endpoints found")
}
return &apis, nil
}
func (g *GoApiParser) parseFile(sourceFile string) ([]api.Endpoint, error) {
var endpoints []api.Endpoint
fileSet := token.NewFileSet()
astFile, err := parser.ParseFile(fileSet, sourceFile, nil, parser.ParseComments|parser.SkipObjectResolution)
if err != nil {
@ -52,13 +75,13 @@ func (g *GoApiParser) Parse(sourceFile string) (*api.Api, error) {
continue
}
apis.Endpoints = append(apis.Endpoints, api.Endpoint{
endpoints = append(endpoints, api.Endpoint{
Name: typeSpec.Name.Name,
})
}
if len(apis.Endpoints) == 0 {
return nil, fmt.Errorf("no api struct found")
if len(endpoints) == 0 {
return nil, nil
}
for _, decl := range astFile.Decls {
@ -88,7 +111,7 @@ func (g *GoApiParser) Parse(sourceFile string) (*api.Api, error) {
continue
}
for i, endpoint := range apis.Endpoints {
for i, endpoint := range endpoints {
if recvIdent.Name == endpoint.Name {
var apiMethod api.Method
apiMethod.Name = funcDecl.Name.Name
@ -96,8 +119,8 @@ func (g *GoApiParser) Parse(sourceFile string) (*api.Api, error) {
var apiPar api.Val
ident := param.Type.(*ast.Ident)
switch ident.Name {
//case "int":
// apiPar.Type = api.TInt
case "int":
apiPar.Type = api.TInt
case "string":
apiPar.Type = api.TString
case "bool":
@ -132,10 +155,9 @@ func (g *GoApiParser) Parse(sourceFile string) (*api.Api, error) {
}
apiMethod.Ret = append(apiMethod.Ret, apiRet)
}
apis.Endpoints[i].Methods = append(apis.Endpoints[i].Methods, apiMethod)
endpoints[i].Methods = append(endpoints[i].Methods, apiMethod)
}
}
}
return &apis, nil
return endpoints, nil
}

View File

@ -4,6 +4,7 @@ import (
"flag"
"fmt"
"go/token"
"io/fs"
"log"
"os"
"path"
@ -15,7 +16,8 @@ import (
)
type ApiParser interface {
Parse(sourceFile string) (*api.Api, error)
AddFile(path string)
Parse() (*api.Api, error)
}
type ApiGenerator interface {
@ -23,13 +25,7 @@ type ApiGenerator interface {
}
func main() {
// todo support go:generate
//goFile := os.Getenv("GOFILE")
//if goFile == "" {
// log.Panic("GOFILE must be set")
//}
src := flag.String("src", "", "Source file")
src := flag.String("src", "", "Source file/dir")
dest := flag.String("dest", "", "Dest file")
pkgName := flag.String("pkgname", "", "Package name (for go)")
flag.Parse()
@ -48,42 +44,79 @@ func main() {
log.Panic(err)
}
if err := checkIsFile(srcAbs); err != nil {
log.Panic(err)
}
apiParser, err := apiParserByExt(srcAbs)
apiParser, err := apiParserByPath(srcAbs)
if err != nil {
log.Panic(err)
}
api, err := apiParser.Parse(srcAbs)
apis, err := apiParser.Parse()
if err != nil {
log.Panic(err)
}
apiGenerator, err := apiGeneratorByExt(destAbs, *pkgName)
apiGenerator, err := apiGeneratorByPath(destAbs, *pkgName)
if err != nil {
log.Panic(err)
}
if err := apiGenerator.Generate(api, destAbs); err != nil {
if err := apiGenerator.Generate(apis, destAbs); err != nil {
log.Panic(err)
}
}
func checkIsFile(src string) error {
info, err := os.Stat(src)
func apiParserByPath(src string) (ApiParser, error) {
s, err := os.Stat(src)
if err != nil {
return fmt.Errorf("stat file: %w", err)
return nil, fmt.Errorf("stat src: %w", err)
}
if info.IsDir() {
return fmt.Errorf("%s is a directory; directories are not supported yet", src)
var parser ApiParser
var ext string
if s.IsDir() {
if err := filepath.Walk(src, func(curPath string, i fs.FileInfo, err error) error {
if err != nil {
return err
}
if i.IsDir() {
return nil
}
p, err := apiParserByFilePath(i.Name())
if err == nil {
if parser != nil {
if path.Ext(i.Name()) == ext {
parser.AddFile(curPath)
return nil
}
return fmt.Errorf("path contain multiple supported filetypes")
} else {
ext = path.Ext(i.Name())
parser = p
parser.AddFile(curPath)
}
}
return nil
}); err != nil {
return nil, fmt.Errorf("walk dir: %w", err)
}
} else {
parser, err = apiParserByFilePath(src)
if err != nil {
return nil, err
}
parser.AddFile(src)
}
if parser == nil {
return nil, fmt.Errorf("could not find supported files in %s", src)
}
return parser, nil
}
func apiParserByExt(src string) (ApiParser, error) {
func apiParserByFilePath(src string) (ApiParser, error) {
switch path.Ext(src) {
case ".go":
return &golang.GoApiParser{}, nil
@ -98,7 +131,7 @@ func apiParserByExt(src string) (ApiParser, error) {
}
}
func apiGeneratorByExt(dest string, pkgName string) (ApiGenerator, error) {
func apiGeneratorByPath(dest string, pkgName string) (ApiGenerator, error) {
switch path.Ext(dest) {
case ".go":
if pkgName == "" {

View File

@ -17,9 +17,34 @@ const TagName = "kittenipc"
const TagComment = "api"
type TypescriptApiParser struct {
files []string
}
func (t *TypescriptApiParser) Parse(sourceFilePath string) (*api.Api, error) {
func (t *TypescriptApiParser) AddFile(path string) {
t.files = append(t.files, path)
}
func (t *TypescriptApiParser) Parse() (*api.Api, error) {
var apis api.Api
for _, f := range t.files {
endpoints, err := t.parseFile(f)
if err != nil {
return nil, fmt.Errorf("parse file: %w", err)
}
apis.Endpoints = append(apis.Endpoints, endpoints...)
}
if len(apis.Endpoints) == 0 {
return nil, fmt.Errorf("no endpoints found")
}
return &apis, nil
}
func (t *TypescriptApiParser) parseFile(sourceFilePath string) ([]api.Endpoint, error) {
var endpoints []api.Endpoint
f, err := os.Open(sourceFilePath)
if err != nil {
@ -41,8 +66,6 @@ func (t *TypescriptApiParser) Parse(sourceFilePath string) (*api.Api, error) {
}, string(fileContents), core.ScriptKindTS)
_ = sourceFile
var apis api.Api
sourceFile.ForEachChild(func(node *ast.Node) bool {
if node.Kind != ast.KindClassDeclaration {
return false
@ -107,8 +130,8 @@ func (t *TypescriptApiParser) Parse(sourceFilePath string) (*api.Api, error) {
if method.Type != nil {
var apiRet api.Val
switch method.Type.Kind {
//case ast.KindNumberKeyword:
// apiRet.Type = api.TInt
case ast.KindNumberKeyword:
apiRet.Type = api.TInt
case ast.KindStringKeyword:
apiRet.Type = api.TString
case ast.KindBooleanKeyword:
@ -122,7 +145,7 @@ func (t *TypescriptApiParser) Parse(sourceFilePath string) (*api.Api, error) {
endpoint.Methods = append(endpoint.Methods, apiMethod)
}
apis.Endpoints = append(apis.Endpoints, endpoint)
endpoints = append(endpoints, endpoint)
return false
})
@ -131,9 +154,5 @@ func (t *TypescriptApiParser) Parse(sourceFilePath string) (*api.Api, error) {
return nil, err
}
if len(apis.Endpoints) == 0 {
return nil, fmt.Errorf("no api class found")
}
return &apis, nil
return endpoints, nil
}