Skip to content

Commit b726387

Browse files
committed
preorder child list -> postorder traversal
1 parent 7ef7a02 commit b726387

File tree

5 files changed

+339
-185
lines changed

5 files changed

+339
-185
lines changed

_xtool/internal/parser/parser.go

Lines changed: 30 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -245,39 +245,18 @@ func (ct *Converter) visitTop(cursor, parent clang.Cursor) clang.ChildVisitResul
245245

246246
case clang.CursorClassDecl:
247247
classDecl := ct.ProcessClassDecl(cursor)
248+
// todo(zzy):class need consider nested struct situation
248249
ct.file.Decls = append(ct.file.Decls, classDecl)
249250
// class havent anonymous situation
250251
ct.logln("visitTop: ProcessClassDecl END", classDecl.Name.Name)
251252
case clang.CursorStructDecl:
252-
structDecl := ct.ProcessStructDecl(cursor)
253-
254-
// Add extracted nested struct declarations first
255-
for _, extractedDecl := range ct.extractedDecls {
256-
ct.file.Decls = append(ct.file.Decls, extractedDecl)
257-
}
258-
259-
ct.file.Decls = append(ct.file.Decls, structDecl)
253+
decls := ct.ProcessStructDecl(cursor)
254+
ct.file.Decls = append(ct.file.Decls, decls...)
260255
ct.logf("visitTop: ProcessStructDecl END")
261-
if structDecl.Name != nil {
262-
ct.logln(structDecl.Name.Name)
263-
} else {
264-
ct.logln("ANONY")
265-
}
266256
case clang.CursorUnionDecl:
267-
unionDecl := ct.ProcessUnionDecl(cursor)
268-
269-
// Add extracted nested struct declarations first
270-
for _, extractedDecl := range ct.extractedDecls {
271-
ct.file.Decls = append(ct.file.Decls, extractedDecl)
272-
}
273-
274-
ct.file.Decls = append(ct.file.Decls, unionDecl)
257+
decls := ct.ProcessUnionDecl(cursor)
258+
ct.file.Decls = append(ct.file.Decls, decls...)
275259
ct.logf("visitTop: ProcessUnionDecl END")
276-
if unionDecl.Name != nil {
277-
ct.logln(unionDecl.Name.Name)
278-
} else {
279-
ct.logln("ANONY")
280-
}
281260
case clang.CursorFunctionDecl, clang.CursorCXXMethod, clang.CursorConstructor, clang.CursorDestructor:
282261
// Handle functions and class methods (including out-of-class method)
283262
// Example: void MyClass::myMethod() { ... } out-of-class method
@@ -803,17 +782,32 @@ func (ct *Converter) extractNestedStructs(cursor clang.Cursor) {
803782
})
804783
}
805784

806-
func (ct *Converter) ProcessRecordDecl(cursor clang.Cursor) *ast.TypeDecl {
785+
func (ct *Converter) ProcessRecordDecl(cursor clang.Cursor) []ast.Decl {
786+
var decls []ast.Decl
807787
ct.incIndent()
808788
defer ct.decIndent()
809789
cursorName, cursorKind := getCursorDesc(cursor)
810790
ct.logln("ProcessRecordDecl: CursorName:", cursorName, "CursorKind:", cursorKind)
811791

812-
// Clear extracted decls before processing this record
813-
ct.extractedDecls = ct.extractedDecls[:0]
792+
childs := GetChilds(cursor, func(child, parent clang.Cursor) bool {
793+
return (child.Kind == clang.CursorStructDecl || child.Kind == clang.CursorUnionDecl) && child.IsAnonymous() == 0
794+
})
814795

815-
// Extract nested struct declarations first
816-
ct.extractNestedStructs(cursor)
796+
for _, child := range childs {
797+
798+
// Check if this is a named nested struct/union
799+
typ := ct.ProcessRecordType(child)
800+
// note(zzy):use len(typ.Fields.List) to ensure it has fields not a forward declaration
801+
// but maybe make the forward decl in to AST is also good.
802+
if child.IsAnonymous() == 0 && len(typ.Fields.List) > 0 {
803+
childName := clang.GoString(child.String())
804+
ct.logln("Found named nested struct:", childName, child.Type().Kind)
805+
decls = append(decls, &ast.TypeDecl{
806+
Object: ct.CreateObject(child, &ast.Ident{Name: childName}),
807+
Type: ct.ProcessRecordType(child),
808+
})
809+
}
810+
}
817811

818812
decl := &ast.TypeDecl{
819813
Object: ct.CreateObject(cursor, nil),
@@ -828,14 +822,16 @@ func (ct *Converter) ProcessRecordDecl(cursor clang.Cursor) *ast.TypeDecl {
828822
ct.logln("ProcessRecordDecl: is anonymous")
829823
}
830824

831-
return decl
825+
decls = append(decls, decl)
826+
827+
return decls
832828
}
833829

834-
func (ct *Converter) ProcessStructDecl(cursor clang.Cursor) *ast.TypeDecl {
830+
func (ct *Converter) ProcessStructDecl(cursor clang.Cursor) []ast.Decl {
835831
return ct.ProcessRecordDecl(cursor)
836832
}
837833

838-
func (ct *Converter) ProcessUnionDecl(cursor clang.Cursor) *ast.TypeDecl {
834+
func (ct *Converter) ProcessUnionDecl(cursor clang.Cursor) []ast.Decl {
839835
return ct.ProcessRecordDecl(cursor)
840836
}
841837

_xtool/internal/parser/parser_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,19 @@ import (
1919
"github.com/goplus/llgo/xtool/clang/preprocessor"
2020
)
2121

22-
func TestParser(t *testing.T) {
22+
func TestParserCppMode(t *testing.T) {
2323
cases := []string{"class", "comment", "enum", "func", "scope", "struct", "typedef", "union", "macro", "forwarddecl1", "forwarddecl2", "include", "typeof"}
2424
// https://github.com/goplus/llgo/issues/1114
2525
// todo(zzy):use os.ReadDir
2626
for _, folder := range cases {
2727
t.Run(folder, func(t *testing.T) {
28-
testFrom(t, filepath.Join("testdata", folder), "temp.h", true, true)
28+
testFrom(t, filepath.Join("testdata", folder), "temp.h", true, false)
2929
})
3030
}
3131
}
3232

33-
func TestParserC(t *testing.T) {
34-
cases := []string{"tt"}
33+
func TestParserCMode(t *testing.T) {
34+
cases := []string{"named_nested_struct"}
3535
for _, folder := range cases {
3636
t.Run(folder, func(t *testing.T) {
3737
testFrom(t, filepath.Join("testdata", folder), "temp.h", false, false)
@@ -628,7 +628,7 @@ func compareOutput(t *testing.T, expected, actual string) {
628628
}
629629
}
630630

631-
func TestNest(t *testing.T) {
631+
func TestGetChilds(t *testing.T) {
632632
config := &clangutils.Config{
633633
File: "./testdata/named_nested_struct/temp.h",
634634
Temp: false,

0 commit comments

Comments
 (0)