diff --git a/chore/_xtool/llcppsigfetch/parse/cvt.go b/chore/_xtool/llcppsigfetch/parse/cvt.go index e5d34eb2..a10d4a50 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt.go +++ b/chore/_xtool/llcppsigfetch/parse/cvt.go @@ -230,10 +230,16 @@ func (ct *Converter) Convert() (map[string]*ast.File, error) { } func (ct *Converter) ProcessType(t clang.Type) ast.Expr { - var expr ast.Expr + if t.Kind >= clang.TypeFirstBuiltin && t.Kind <= clang.TypeLastBuiltin { return ct.ProcessBuiltinType(t) } + + if t.Kind == clang.TypeElaborated { + return ct.ProcessElaboratedType(t) + } + + var expr ast.Expr switch t.Kind { case clang.TypePointer: expr = &ast.PointerType{X: ct.ProcessType(t.PointeeType())} @@ -268,21 +274,10 @@ func (ct *Converter) ProcessTypeDef(cursor clang.Cursor) *ast.TypedefDecl { return &ast.TypedefDecl{ DeclBase: ct.CreateDeclBase(cursor), Name: &ast.Ident{Name: c.GoString(name.CStr())}, - Type: ct.ProcessUnderLyingType(cursor), + Type: ct.ProcessType(cursor.TypedefDeclUnderlyingType()), } } -func (ct *Converter) ProcessUnderLyingType(cursor clang.Cursor) ast.Expr { - underlying := cursor.TypedefDeclUnderlyingType() - // enum,union,class,struct,typedef -> elaborated type - if underlying.Kind == clang.TypeElaborated { - return &ast.Ident{ - Name: c.GoString(underlying.String().CStr()), - } - } - return ct.ProcessType(underlying) -} - func (ct *Converter) ProcessFunc(cursor clang.Cursor) *ast.FuncDecl { name := cursor.String() defer name.Dispose() @@ -487,6 +482,36 @@ func (ct *Converter) ProcessClass(cursor clang.Cursor) *ast.TypeDecl { return ct.ProcessRecord(cursor, ast.Class) } +func (ct *Converter) ProcessElaboratedType(t clang.Type) ast.Expr { + name := t.String() + defer name.Dispose() + + typeName := c.GoString(name.CStr()) + + tagMap := map[string]ast.Tag{ + "struct": ast.Struct, + "union": ast.Union, + "enum": ast.Enum, + "class": ast.Class, + } + + // for elaborated type, it could have a tag description + // like struct A, union B, class C, enum D + parts := strings.SplitN(typeName, " ", 2) + if len(parts) == 2 { + if tagValue, ok := tagMap[parts[0]]; ok { + return &ast.TagExpr{ + Tag: tagValue, + Name: &ast.Ident{Name: parts[1]}, + } + } + } + + return &ast.Ident{ + Name: typeName, + } +} + func (ct *Converter) ProcessBuiltinType(t clang.Type) *ast.BuiltinType { kind := ast.Void var flags ast.TypeFlag diff --git a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/typedef_test/llgo.expect b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/typedef_test/llgo.expect index 4eed90e6..fbaed500 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/typedef_test/llgo.expect +++ b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/typedef_test/llgo.expect @@ -194,6 +194,151 @@ TestTypeDefDecl Case 3: } } +TestTypeDefDecl Case 4: +{ + "temp.h": { + "decls": [{ + "Loc": { + "File": "temp.h" + }, + "Doc": { + "List": [] + }, + "Parent": null, + "Name": { + "Name": "StructFoo" + }, + "Type": { + "Tag": 0, + "Fields": { + "List": [] + }, + "Methods": [] + } + }, { + "Loc": { + "File": "temp.h" + }, + "Doc": { + "List": [] + }, + "Parent": null, + "Name": { + "Name": "UnionFoo" + }, + "Type": { + "Tag": 1, + "Fields": { + "List": [] + }, + "Methods": [] + } + }, { + "Loc": { + "File": "temp.h" + }, + "Doc": { + "List": [] + }, + "Parent": { + "Name": "ClassFoo" + }, + "Name": { + "Name": "ClassFoo" + }, + "Type": { + "Tag": 3, + "Fields": { + "List": [] + }, + "Methods": [] + } + }, { + "Loc": { + "File": "temp.h" + }, + "Doc": { + "List": [] + }, + "Parent": null, + "Name": { + "Name": "EnumFoo" + }, + "Items": [] + }, { + "Loc": { + "File": "temp.h" + }, + "Doc": { + "List": [] + }, + "Parent": null, + "Name": { + "Name": "STRUCT_FOO" + }, + "Type": { + "Name": { + "Name": "StructFoo" + }, + "Tag": 0 + } + }, { + "Loc": { + "File": "temp.h" + }, + "Doc": { + "List": [] + }, + "Parent": null, + "Name": { + "Name": "UNION_FOO" + }, + "Type": { + "Name": { + "Name": "UnionFoo" + }, + "Tag": 1 + } + }, { + "Loc": { + "File": "temp.h" + }, + "Doc": { + "List": [] + }, + "Parent": null, + "Name": { + "Name": "CLASS_FOO" + }, + "Type": { + "Name": { + "Name": "ClassFoo" + }, + "Tag": 3 + } + }, { + "Loc": { + "File": "temp.h" + }, + "Doc": { + "List": [] + }, + "Parent": null, + "Name": { + "Name": "ENUM_FOO" + }, + "Type": { + "Name": { + "Name": "EnumFoo" + }, + "Tag": 2 + } + }], + "includes": [], + "macros": [] + } +} + #stderr diff --git a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/typedef_test/typedef.go b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/typedef_test/typedef.go index 81daceca..9c90c6c7 100644 --- a/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/typedef_test/typedef.go +++ b/chore/_xtool/llcppsigfetch/parse/cvt_test/decl_test/typedef_test/typedef.go @@ -10,6 +10,7 @@ func TestTypeDefDecl() { testCases := []string{ `typedef int INT;`, `typedef int INT; + typedef INT STANDARD_INT;`, `struct StructFoo {}; union UnionFoo {}; @@ -19,6 +20,15 @@ func TestTypeDefDecl() { typedef UnionFoo UNION_FOO; typedef ClassFoo CLASS_FOO; typedef EnumFoo ENUM_FOO;`, + + `struct StructFoo {}; + union UnionFoo {}; + class ClassFoo {}; + enum EnumFoo {}; + typedef struct StructFoo STRUCT_FOO; + typedef union UnionFoo UNION_FOO; + typedef class ClassFoo CLASS_FOO; + typedef enum EnumFoo ENUM_FOO;`, } test.RunTest("TestTypeDefDecl", testCases) } diff --git a/chore/_xtool/llcppsigfetch/parse/dump.go b/chore/_xtool/llcppsigfetch/parse/dump.go index 0f8024d0..1acb8c49 100644 --- a/chore/_xtool/llcppsigfetch/parse/dump.go +++ b/chore/_xtool/llcppsigfetch/parse/dump.go @@ -140,6 +140,9 @@ func MarshalASTExpr(t ast.Expr) *cjson.JSON { return cjson.Null() } root.SetItem(c.Str("Name"), cjson.String(c.AllocaCStr(d.Name))) + case *ast.TagExpr: + root.SetItem(c.Str("Name"), MarshalASTExpr(d.Name)) + root.SetItem(c.Str("Tag"), cjson.Number(float64(d.Tag))) case *ast.EnumItem: root.SetItem(c.Str("Name"), MarshalASTExpr(d.Name)) root.SetItem(c.Str("Value"), MarshalASTExpr(d.Value))