From 9087dac6fe20cdbebd6b7f9dca4b463ae4ac6824 Mon Sep 17 00:00:00 2001 From: luoliwoshang <2643523683@qq.com> Date: Thu, 15 Aug 2024 18:21:09 +0800 Subject: [PATCH] llcppsigfetch:basic class & struct 's process --- chore/_xtool/llcppsigfetch/parse/cvt.go | 90 ++- .../parse/cvt_test/decl_test/decl.go | 76 +++ .../parse/cvt_test/decl_test/llgo.expect | 557 +++++++++++++++++- chore/_xtool/llcppsigfetch/parse/dump.go | 9 + 4 files changed, 691 insertions(+), 41 deletions(-) diff --git a/chore/_xtool/llcppsigfetch/parse/cvt.go b/chore/_xtool/llcppsigfetch/parse/cvt.go index 19169be3..be52e641 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt.go +++ b/chore/_xtool/llcppsigfetch/parse/cvt.go @@ -168,9 +168,9 @@ func visit(cursor, parent clang.Cursor, clientData unsafe.Pointer) clang.ChildVi ct.ProcessClass(cursor) ct.PopScope() case clang.CursorStructDecl: - // todo(zzy) + ct.ProcessStruct(cursor) case clang.CursorFunctionDecl: - ct.ProcessFunc(cursor) + ct.curFile.Decls = append(ct.curFile.Decls, ct.ProcessFunc(cursor)) case clang.CursorNamespace: ct.PushScope(cursor) clang.VisitChildren(cursor, visit, c.Pointer(ct)) @@ -218,45 +218,51 @@ func (ct *Converter) ProcessType(t clang.Type) ast.Expr { return expr } -func (ct *Converter) ProcessFunc(cursor clang.Cursor) { +func (ct *Converter) ProcessFunc(cursor clang.Cursor) *ast.FuncDecl { 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 + return nil } - params := ct.ProcessFuncParams(cursor) + params := ct.ProcessFieldList(cursor) funcType.Params = params fn := &ast.FuncDecl{ DeclBase: ct.CreateDeclBase(cursor), Name: &ast.Ident{Name: c.GoString(name.CStr())}, Type: funcType, } - ct.curFile.Decls = append(ct.curFile.Decls, fn) + return fn } -type visitParamContext struct { +type visitFieldContext 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 { +func visitFieldList(cursor, parent clang.Cursor, clientData unsafe.Pointer) clang.ChildVisitResult { + ctx := (*visitFieldContext)(clientData) + if cursor.Kind == clang.CursorParmDecl || cursor.Kind == clang.CursorFieldDecl { 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) + + // For follows struct, it will also parse to two FieldDecl + // struct A { + // int a, b; + // }; ctx.params.List = append(ctx.params.List, &ast.Field{ - Type: argType, + //todo(zzy): comment & doc + Doc: &ast.CommentGroup{}, + Comment: &ast.CommentGroup{}, + Type: argType, Names: []*ast.Ident{ {Name: c.GoString(paramName.CStr())}, }, @@ -265,18 +271,68 @@ func visitParamDecl(cursor, parent clang.Cursor, clientData unsafe.Pointer) clan return clang.ChildVisit_Continue } -func (ct *Converter) ProcessFuncParams(cursor clang.Cursor) *ast.FieldList { +func (ct *Converter) ProcessFieldList(cursor clang.Cursor) *ast.FieldList { params := &ast.FieldList{List: []*ast.Field{}} - ctx := &visitParamContext{ + ctx := &visitFieldContext{ params: params, converter: ct, } - clang.VisitChildren(cursor, visitParamDecl, c.Pointer(ctx)) + clang.VisitChildren(cursor, visitFieldList, c.Pointer(ctx)) return params } +type visitMethodsContext struct { + methods *[]*ast.FuncDecl + converter *Converter +} + +func visitMethods(cursor, parent clang.Cursor, clientData unsafe.Pointer) clang.ChildVisitResult { + ctx := (*visitMethodsContext)(clientData) + if cursor.Kind == clang.CursorCXXMethod { + method := ctx.converter.ProcessFunc(cursor) + if method != nil { + *ctx.methods = append(*ctx.methods, method) + } + } + return clang.ChildVisit_Continue +} + +func (ct *Converter) ProcessMethods(cursor clang.Cursor) []*ast.FuncDecl { + methods := make([]*ast.FuncDecl, 0) + ctx := &visitMethodsContext{ + methods: &methods, + converter: ct, + } + clang.VisitChildren(cursor, visitMethods, c.Pointer(ctx)) + return methods +} + +func (ct *Converter) ProcessStructOrClass(cursor clang.Cursor, tag ast.Tag) *ast.TypeDecl { + name := cursor.String() + defer name.Dispose() + + fields := ct.ProcessFieldList(cursor) + methods := ct.ProcessMethods(cursor) + + decl := &ast.TypeDecl{ + DeclBase: ct.CreateDeclBase(cursor), + Tag: tag, + Fields: fields, + Methods: methods, + } + + return decl +} + +func (ct *Converter) ProcessStruct(cursor clang.Cursor) { + structDecl := ct.ProcessStructOrClass(cursor, ast.Struct) + ct.curFile.Decls = append(ct.curFile.Decls, structDecl) +} + func (ct *Converter) ProcessClass(cursor clang.Cursor) { - println("todo: Process class") + classDecl := ct.ProcessStructOrClass(cursor, ast.Class) + // other logic for class + ct.curFile.Decls = append(ct.curFile.Decls, classDecl) } func (ct *Converter) ProcessBuiltinType(t clang.Type) *ast.BuiltinType { 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 4decd928..908fcc3e 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/decl.go +++ b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/decl.go @@ -9,6 +9,8 @@ func main() { TestFuncDecl() TestScope() TestComment() + TestStructDecl() + TestClassDecl() } func TestFuncDecl() { @@ -54,6 +56,14 @@ func TestScope() { void foo(); } }`, + `class a { + void foo(); + };`, + `namespace a { + class b { + void foo(); + }; + }`, } for i, content := range testCases { @@ -73,6 +83,7 @@ func TestScope() { converter.Dispose() } } + func TestComment() { testCases := []string{ `// not read comment 1 @@ -118,3 +129,68 @@ void foo();`, converter.Dispose() } } + +func TestStructDecl() { + testCases := []string{ + `struct A { + int a; + int b; + };`, + `struct A { + int a, b; + };`, + `struct A { + int a; + int b; + float foo(int a,double b);; + };`, + } + + 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("TestStructDecl Case %d:\n%s\n\n"), c.Int(i+1), json.Print()) + + converter.Dispose() + } +} + +func TestClassDecl() { + testCases := []string{ + `class A { + int a; + int b; + };`, + `class A { + int a; + int b; + float foo(int a,double b);; + };`, + } + + 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("TestClassDecl Case %d:\n%s\n\n"), c.Int(i+1), json.Print()) + + converter.Dispose() + } +} 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 87b9e634..47e9cb36 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/llgo.expect +++ b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/llgo.expect @@ -51,8 +51,12 @@ TestFuncDecl Case 2: "Kind": 6, "Flags": 0 }, - "Doc": null, - "Comment": null, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, "Names": [{ "Name": "a" }] @@ -91,8 +95,12 @@ TestFuncDecl Case 3: "Kind": 6, "Flags": 0 }, - "Doc": null, - "Comment": null, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, "Names": [{ "Name": "a" }] @@ -101,8 +109,12 @@ TestFuncDecl Case 3: "Kind": 8, "Flags": 16 }, - "Doc": null, - "Comment": null, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, "Names": [{ "Name": "b" }] @@ -143,8 +155,12 @@ TestFuncDecl Case 4: "Flags": 1 } }, - "Doc": null, - "Comment": null, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, "Names": [{ "Name": "str" }] @@ -153,8 +169,12 @@ TestFuncDecl Case 4: "Kind": 8, "Flags": 16 }, - "Doc": null, - "Comment": null, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, "Names": [{ "Name": "x" }] @@ -195,8 +215,12 @@ TestFuncDecl Case 5: "Flags": 1 } }, - "Doc": null, - "Comment": null, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, "Names": [{ "Name": "str" }] @@ -205,8 +229,12 @@ TestFuncDecl Case 5: "Kind": 8, "Flags": 16 }, - "Doc": null, - "Comment": null, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, "Names": [{ "Name": "x" }] @@ -253,8 +281,12 @@ TestFuncDecl Case 6: } } }, - "Doc": null, - "Comment": null, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, "Names": [{ "Name": "str" }] @@ -263,8 +295,12 @@ TestFuncDecl Case 6: "Kind": 8, "Flags": 16 }, - "Doc": null, - "Comment": null, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, "Names": [{ "Name": "x" }] @@ -308,8 +344,12 @@ TestFuncDecl Case 7: }, "Len": null }, - "Doc": null, - "Comment": null, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, "Names": [{ "Name": "str" }] @@ -318,8 +358,12 @@ TestFuncDecl Case 7: "Kind": 8, "Flags": 16 }, - "Doc": null, - "Comment": null, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, "Names": [{ "Name": "x" }] @@ -372,8 +416,12 @@ TestFuncDecl Case 8: "Value": "3" } }, - "Doc": null, - "Comment": null, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, "Names": [{ "Name": "arr" }] @@ -491,6 +539,110 @@ TestScope Case 3: } } +TestScope Case 4: +{ + "temp.h": { + "path": "temp.h", + "decls": [{ + "Loc": { + "File": "temp.h" + }, + "Doc": { + "List": [] + }, + "Parent": { + "Name": "a" + }, + "Tag": 3, + "Fields": { + "List": [] + }, + "Methods": [{ + "Loc": { + "File": "temp.h" + }, + "Doc": { + "List": [] + }, + "Parent": { + "Name": "a" + }, + "Name": { + "Name": "foo" + }, + "Type": { + "Params": { + "List": [] + }, + "Ret": { + "Kind": 0, + "Flags": 0 + } + } + }] + }], + "includes": [], + "macros": [] + } +} + +TestScope Case 5: +{ + "temp.h": { + "path": "temp.h", + "decls": [{ + "Loc": { + "File": "temp.h" + }, + "Doc": { + "List": [] + }, + "Parent": { + "X": { + "Name": "b" + }, + "Parent": { + "Name": "a" + } + }, + "Tag": 3, + "Fields": { + "List": [] + }, + "Methods": [{ + "Loc": { + "File": "temp.h" + }, + "Doc": { + "List": [] + }, + "Parent": { + "X": { + "Name": "b" + }, + "Parent": { + "Name": "a" + } + }, + "Name": { + "Name": "foo" + }, + "Type": { + "Params": { + "List": [] + }, + "Ret": { + "Kind": 0, + "Flags": 0 + } + } + }] + }], + "includes": [], + "macros": [] + } +} + TestComment Case 1: { "temp.h": { @@ -787,6 +939,363 @@ TestComment Case 9: } } +TestStructDecl Case 1: +{ + "temp.h": { + "path": "temp.h", + "decls": [{ + "Loc": { + "File": "temp.h" + }, + "Doc": { + "List": [] + }, + "Parent": null, + "Tag": 0, + "Fields": { + "List": [{ + "Type": { + "Kind": 6, + "Flags": 0 + }, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, + "Names": [{ + "Name": "a" + }] + }, { + "Type": { + "Kind": 6, + "Flags": 0 + }, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, + "Names": [{ + "Name": "b" + }] + }] + }, + "Methods": [] + }], + "includes": [], + "macros": [] + } +} + +TestStructDecl Case 2: +{ + "temp.h": { + "path": "temp.h", + "decls": [{ + "Loc": { + "File": "temp.h" + }, + "Doc": { + "List": [] + }, + "Parent": null, + "Tag": 0, + "Fields": { + "List": [{ + "Type": { + "Kind": 6, + "Flags": 0 + }, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, + "Names": [{ + "Name": "a" + }] + }, { + "Type": { + "Kind": 6, + "Flags": 0 + }, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, + "Names": [{ + "Name": "b" + }] + }] + }, + "Methods": [] + }], + "includes": [], + "macros": [] + } +} + +TestStructDecl Case 3: +{ + "temp.h": { + "path": "temp.h", + "decls": [{ + "Loc": { + "File": "temp.h" + }, + "Doc": { + "List": [] + }, + "Parent": null, + "Tag": 0, + "Fields": { + "List": [{ + "Type": { + "Kind": 6, + "Flags": 0 + }, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, + "Names": [{ + "Name": "a" + }] + }, { + "Type": { + "Kind": 6, + "Flags": 0 + }, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, + "Names": [{ + "Name": "b" + }] + }] + }, + "Methods": [{ + "Loc": { + "File": "temp.h" + }, + "Doc": { + "List": [] + }, + "Parent": null, + "Name": { + "Name": "foo" + }, + "Type": { + "Params": { + "List": [{ + "Type": { + "Kind": 6, + "Flags": 0 + }, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, + "Names": [{ + "Name": "a" + }] + }, { + "Type": { + "Kind": 8, + "Flags": 16 + }, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, + "Names": [{ + "Name": "b" + }] + }] + }, + "Ret": { + "Kind": 8, + "Flags": 0 + } + } + }] + }], + "includes": [], + "macros": [] + } +} + +TestClassDecl Case 1: +{ + "temp.h": { + "path": "temp.h", + "decls": [{ + "Loc": { + "File": "temp.h" + }, + "Doc": { + "List": [] + }, + "Parent": { + "Name": "A" + }, + "Tag": 3, + "Fields": { + "List": [{ + "Type": { + "Kind": 6, + "Flags": 0 + }, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, + "Names": [{ + "Name": "a" + }] + }, { + "Type": { + "Kind": 6, + "Flags": 0 + }, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, + "Names": [{ + "Name": "b" + }] + }] + }, + "Methods": [] + }], + "includes": [], + "macros": [] + } +} + +TestClassDecl Case 2: +{ + "temp.h": { + "path": "temp.h", + "decls": [{ + "Loc": { + "File": "temp.h" + }, + "Doc": { + "List": [] + }, + "Parent": { + "Name": "A" + }, + "Tag": 3, + "Fields": { + "List": [{ + "Type": { + "Kind": 6, + "Flags": 0 + }, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, + "Names": [{ + "Name": "a" + }] + }, { + "Type": { + "Kind": 6, + "Flags": 0 + }, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, + "Names": [{ + "Name": "b" + }] + }] + }, + "Methods": [{ + "Loc": { + "File": "temp.h" + }, + "Doc": { + "List": [] + }, + "Parent": { + "Name": "A" + }, + "Name": { + "Name": "foo" + }, + "Type": { + "Params": { + "List": [{ + "Type": { + "Kind": 6, + "Flags": 0 + }, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, + "Names": [{ + "Name": "a" + }] + }, { + "Type": { + "Kind": 8, + "Flags": 16 + }, + "Doc": { + "List": [] + }, + "Comment": { + "List": [] + }, + "Names": [{ + "Name": "b" + }] + }] + }, + "Ret": { + "Kind": 8, + "Flags": 0 + } + } + }] + }], + "includes": [], + "macros": [] + } +} + #stderr diff --git a/chore/_xtool/llcppsigfetch/parse/dump.go b/chore/_xtool/llcppsigfetch/parse/dump.go index c5eeb004..e36f2617 100644 --- a/chore/_xtool/llcppsigfetch/parse/dump.go +++ b/chore/_xtool/llcppsigfetch/parse/dump.go @@ -41,6 +41,15 @@ func (ct *Converter) DeclJSON(decl ast.Decl) *cjson.JSON { ct.DeclBaseJSON(d.DeclBase, root) root.SetItem(c.Str("Name"), ct.TypeJSON(d.Name)) root.SetItem(c.Str("Type"), ct.TypeJSON(d.Type)) + case *ast.TypeDecl: + ct.DeclBaseJSON(d.DeclBase, root) + root.SetItem(c.Str("Tag"), cjson.Number(float64(d.Tag))) + root.SetItem(c.Str("Fields"), ct.TypeJSON(d.Fields)) + methods := cjson.Array() + for _, m := range d.Methods { + methods.AddItem(ct.DeclJSON(m)) + } + root.SetItem(c.Str("Methods"), methods) } return root }