From 755cdbb238d7abce023ff236e2efcef3d7081873 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Tue, 13 Aug 2024 18:35:33 +0800 Subject: [PATCH] llcppsigfetch:collect func param name --- chore/_xtool/llcppsigfetch/parse/cvt.go | 50 +++- .../parse/cvt_test/decl_test/decl.go | 33 ++- .../parse/cvt_test/decl_test/llgo.expect | 271 ++++++++++++++++-- 3 files changed, 319 insertions(+), 35 deletions(-) diff --git a/chore/_xtool/llcppsigfetch/parse/cvt.go b/chore/_xtool/llcppsigfetch/parse/cvt.go index 94e4ff32..cd9fb2e2 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt.go +++ b/chore/_xtool/llcppsigfetch/parse/cvt.go @@ -142,14 +142,9 @@ func (ct *Converter) ProcessType(t clang.Type) ast.Expr { case clang.TypePointer: expr = &ast.PointerType{X: ct.ProcessType(t.PointeeType())} case clang.TypeFunctionProto: + // function type will only collect return type, params will be collected in ProcessFunc ret := ct.ProcessType(t.ResultType()) - params := &ast.FieldList{} - for i := 0; i < int(t.NumArgTypes()); i++ { - argType := ct.ProcessType(t.ArgType(c.Uint(i))) - params.List = append(params.List, &ast.Field{Type: argType}) - // todo(zzy):field name - } - expr = &ast.FuncType{Params: params, Ret: ret} + expr = &ast.FuncType{Ret: ret} case clang.TypeTypedef: expr = ct.ProcessType(t.CanonicalType()) case clang.TypeConstantArray, clang.TypeVariableArray, clang.TypeIncompleteArray, clang.TypeDependentSizedArray: @@ -164,11 +159,16 @@ func (ct *Converter) ProcessType(t clang.Type) ast.Expr { func (ct *Converter) ProcessFunc(cursor clang.Cursor) { name := cursor.String() defer name.Dispose() + + // function type will only collect return type + // ProcessType can't get the field names,will collect in follows funcType, ok := ct.ProcessType(cursor.Type()).(*ast.FuncType) if !ok { fmt.Println("failed to process function type") return } + params := ct.ProcessFuncParams(cursor) + funcType.Params = params fn := &ast.FuncDecl{ Name: &ast.Ident{Name: c.GoString(name.CStr())}, Type: funcType, @@ -178,6 +178,42 @@ func (ct *Converter) ProcessFunc(cursor clang.Cursor) { // ct.declMap[cursor] = fn } +type visitParamContext struct { + params *ast.FieldList + converter *Converter +} + +// visit top decls (struct,class,function,enum & marco,include) +func visitParamDecl(cursor, parent clang.Cursor, clientData unsafe.Pointer) clang.ChildVisitResult { + ctx := (*visitParamContext)(clientData) + if cursor.Kind == clang.CursorParmDecl { + paramName := cursor.String() + defer paramName.Dispose() + argType := ctx.converter.ProcessType(cursor.Type()) + + // In C language, parameter lists do not have similar parameter grouping in Go. + // func foo(a, b int) + ctx.params.List = append(ctx.params.List, + &ast.Field{ + Type: argType, + Names: []*ast.Ident{ + {Name: c.GoString(paramName.CStr())}, + }, + }) + } + return clang.ChildVisit_Continue +} + +func (ct *Converter) ProcessFuncParams(cursor clang.Cursor) *ast.FieldList { + params := &ast.FieldList{List: []*ast.Field{}} + ctx := &visitParamContext{ + params: params, + converter: ct, + } + clang.VisitChildren(cursor, visitParamDecl, c.Pointer(ctx)) + return params +} + func (ct *Converter) ProcessClass(cursor clang.Cursor) { println("todo: Process class") } diff --git a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/decl.go b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/decl.go index 3302084e..848cdf77 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/decl.go +++ b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/decl.go @@ -10,17 +10,30 @@ func main() { } func TestFuncDecl() { - content := `int foo(int a, int b);` - converter, err := parse.NewConverter(content, true) - if err != nil { - panic(err) + testCases := []string{ + `void foo();`, + `void foo(int a);`, + `float foo(int a,double b);`, + + `void foo(char* str, double x);`, + `float* foo(char* str, double x);`, + `float* foo(char*** str, double x);`, } - defer converter.Dispose() - converter.Convert() - if err != nil { - panic(err) + for i, content := range testCases { + converter, err := parse.NewConverter(content, true) + if err != nil { + panic(err) + } + + _, err = converter.Convert() + if err != nil { + panic(err) + } + + json := converter.GetFilesJSON() + c.Printf(c.Str("Test Case %d:\n%s\n\n"), c.Int(i+1), json.Print()) + + converter.Dispose() } - json := converter.GetFilesJSON() - c.Printf(c.Str("%s\n"), json.Print()) } diff --git a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/llgo.expect b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/llgo.expect index 6300d577..244091c2 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/llgo.expect +++ b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/llgo.expect @@ -1,30 +1,265 @@ #stdout +Test Case 1: { - "Files": { - "temp.h": { - "Path": "temp.h", - "decls": [{ - "Name": "foo", - "Type": { - "Params": [{ - "Kind": 6, - "Flags": 0 + "temp.h": { + "Path": "temp.h", + "decls": [{ + "Loc": null, + "Doc": null, + "Parent": null, + "Name": { + "Name": "foo" + }, + "Type": { + "Params": { + "List": [] + }, + "Ret": { + "Kind": 0, + "Flags": 0 + } + } + }], + "includes": [], + "macros": [] + } +} + +Test Case 2: +{ + "temp.h": { + "Path": "temp.h", + "decls": [{ + "Loc": null, + "Doc": null, + "Parent": null, + "Name": { + "Name": "foo" + }, + "Type": { + "Params": { + "List": [{ + "Type": { + "Kind": 6, + "Flags": 0 + }, + "Doc": null, + "Comment": null, + "Names": [{ + "Name": "a" + }] + }] + }, + "Ret": { + "Kind": 0, + "Flags": 0 + } + } + }], + "includes": [], + "macros": [] + } +} + +Test Case 3: +{ + "temp.h": { + "Path": "temp.h", + "decls": [{ + "Loc": null, + "Doc": null, + "Parent": null, + "Name": { + "Name": "foo" + }, + "Type": { + "Params": { + "List": [{ + "Type": { + "Kind": 6, + "Flags": 0 + }, + "Doc": null, + "Comment": null, + "Names": [{ + "Name": "a" + }] }, { - "Kind": 6, - "Flags": 0 - }], - "Ret": { - "Kind": 6, + "Type": { + "Kind": 8, + "Flags": 16 + }, + "Doc": null, + "Comment": null, + "Names": [{ + "Name": "b" + }] + }] + }, + "Ret": { + "Kind": 8, + "Flags": 0 + } + } + }], + "includes": [], + "macros": [] + } +} + +Test Case 4: +{ + "temp.h": { + "Path": "temp.h", + "decls": [{ + "Loc": null, + "Doc": null, + "Parent": null, + "Name": { + "Name": "foo" + }, + "Type": { + "Params": { + "List": [{ + "Type": { + "X": { + "Kind": 2, + "Flags": 1 + } + }, + "Doc": null, + "Comment": null, + "Names": [{ + "Name": "str" + }] + }, { + "Type": { + "Kind": 8, + "Flags": 16 + }, + "Doc": null, + "Comment": null, + "Names": [{ + "Name": "x" + }] + }] + }, + "Ret": { + "Kind": 0, + "Flags": 0 + } + } + }], + "includes": [], + "macros": [] + } +} + +Test Case 5: +{ + "temp.h": { + "Path": "temp.h", + "decls": [{ + "Loc": null, + "Doc": null, + "Parent": null, + "Name": { + "Name": "foo" + }, + "Type": { + "Params": { + "List": [{ + "Type": { + "X": { + "Kind": 2, + "Flags": 1 + } + }, + "Doc": null, + "Comment": null, + "Names": [{ + "Name": "str" + }] + }, { + "Type": { + "Kind": 8, + "Flags": 16 + }, + "Doc": null, + "Comment": null, + "Names": [{ + "Name": "x" + }] + }] + }, + "Ret": { + "X": { + "Kind": 8, "Flags": 0 } } - }], - "includes": [], - "macros": [] - } + } + }], + "includes": [], + "macros": [] } } +Test Case 6: +{ + "temp.h": { + "Path": "temp.h", + "decls": [{ + "Loc": null, + "Doc": null, + "Parent": null, + "Name": { + "Name": "foo" + }, + "Type": { + "Params": { + "List": [{ + "Type": { + "X": { + "X": { + "X": { + "Kind": 2, + "Flags": 1 + } + } + } + }, + "Doc": null, + "Comment": null, + "Names": [{ + "Name": "str" + }] + }, { + "Type": { + "Kind": 8, + "Flags": 16 + }, + "Doc": null, + "Comment": null, + "Names": [{ + "Name": "x" + }] + }] + }, + "Ret": { + "X": { + "Kind": 8, + "Flags": 0 + } + } + } + }], + "includes": [], + "macros": [] + } +} + + #stderr #exit 0