33using System ;
44using System . Collections . Generic ;
55using System . Diagnostics ;
6+ using System . Runtime . CompilerServices ;
7+ using System . Runtime . InteropServices ;
68using ClangSharp . Interop ;
79
810namespace ClangSharp
911{
1012 [ DebuggerDisplay ( "{Handle.DebuggerDisplayString,nq}" ) ]
1113 public unsafe class Cursor : IEquatable < Cursor >
1214 {
13- private readonly Lazy < IReadOnlyList < Cursor > > _cursorChildren ;
15+ private readonly Lazy < string > _kindSpelling ;
1416 private readonly Lazy < Cursor > _lexicalParentCursor ;
1517 private readonly Lazy < Cursor > _semanticParentCursor ;
18+ private readonly Lazy < string > _spelling ;
1619 private readonly Lazy < TranslationUnit > _translationUnit ;
20+ private List < Cursor > _cursorChildren ;
1721
1822 private protected Cursor ( CXCursor handle , CXCursorKind expectedCursorKind )
1923 {
@@ -23,28 +27,60 @@ private protected Cursor(CXCursor handle, CXCursorKind expectedCursorKind)
2327 }
2428 Handle = handle ;
2529
26- _cursorChildren = new Lazy < IReadOnlyList < Cursor > > ( ( ) => {
27- var cursors = new List < Cursor > ( ) ;
28-
29- _ = Handle . VisitChildren ( ( cursor , parent , clientData ) => {
30- var cursorChild = TranslationUnit . GetOrCreate < Cursor > ( cursor ) ;
31- cursors . Add ( cursorChild ) ;
32- return CXChildVisitResult . CXChildVisit_Continue ;
33- } , clientData : default ) ;
34-
35- return cursors ;
36- } ) ;
37-
30+ _kindSpelling = new Lazy < string > ( ( ) => Handle . KindSpelling . ToString ( ) ) ;
3831 _lexicalParentCursor = new Lazy < Cursor > ( ( ) => TranslationUnit . GetOrCreate < Cursor > ( Handle . LexicalParent ) ) ;
3932 _semanticParentCursor = new Lazy < Cursor > ( ( ) => TranslationUnit . GetOrCreate < Cursor > ( Handle . SemanticParent ) ) ;
33+ _spelling = new Lazy < string > ( ( ) => Handle . Spelling . ToString ( ) ) ;
4034 _translationUnit = new Lazy < TranslationUnit > ( ( ) => TranslationUnit . GetOrCreate ( Handle . TranslationUnit ) ) ;
4135 }
4236
43- public IReadOnlyList < Cursor > CursorChildren => _cursorChildren . Value ;
37+ public IReadOnlyList < Cursor > CursorChildren
38+ {
39+ get
40+ {
41+ if ( _cursorChildren is null )
42+ {
43+ var cursorChildren = GCHandle . Alloc ( new List < Cursor > ( ) ) ;
44+
45+ #if ! NET5_0_OR_GREATER
46+ var visitor = ( CXCursorVisitor ) Visitor ;
47+ var pVisitor = Marshal . GetFunctionPointerForDelegate ( visitor ) ;
48+ #else
49+ var pVisitor = ( delegate * unmanaged[ Cdecl] < CXCursor , CXCursor , nint * , CXChildVisitResult > ) & Visitor ;
50+ #endif
51+
52+ var client_data = stackalloc nint [ 2 ] {
53+ GCHandle . ToIntPtr ( cursorChildren ) ,
54+ TranslationUnit . Handle . Handle
55+ } ;
56+
57+ _ = clang . visitChildren ( Handle , ( IntPtr ) pVisitor , client_data ) ;
58+
59+ _cursorChildren = ( List < Cursor > ) cursorChildren . Target ;
60+ cursorChildren . Free ( ) ;
61+
62+ #if ! NET5_0_OR_GREATER
63+ GC . KeepAlive ( visitor ) ;
64+ #else
65+ [ UnmanagedCallersOnly ( CallConvs = new System . Type [ ] { typeof ( CallConvCdecl ) } ) ]
66+ #endif
67+ static CXChildVisitResult Visitor ( CXCursor cursor , CXCursor parent , void * client_data )
68+ {
69+ var cursorChildren = ( List < Cursor > ) GCHandle . FromIntPtr ( ( ( nint * ) client_data ) [ 0 ] ) . Target ;
70+ var translationUnit = TranslationUnit . GetOrCreate ( ( CXTranslationUnitImpl * ) ( ( nint * ) client_data ) [ 1 ] ) ;
71+
72+ var cursorChild = translationUnit . GetOrCreate < Cursor > ( cursor ) ;
73+ cursorChildren . Add ( cursorChild ) ;
74+ return CXChildVisitResult . CXChildVisit_Continue ;
75+ }
76+ }
77+ return _cursorChildren ;
78+ }
79+ }
4480
45- public CXCursorKind CursorKind => Handle . Kind ;
81+ public CXCursorKind CursorKind => Handle . kind ;
4682
47- public string CursorKindSpelling => Handle . KindSpelling . ToString ( ) ;
83+ public string CursorKindSpelling => _kindSpelling . Value ;
4884
4985 public CXSourceRange Extent => Handle . Extent ;
5086
@@ -56,7 +92,7 @@ private protected Cursor(CXCursor handle, CXCursorKind expectedCursorKind)
5692
5793 public Cursor SemanticParentCursor => _semanticParentCursor . Value ;
5894
59- public string Spelling => Handle . Spelling . ToString ( ) ;
95+ public string Spelling => _spelling . Value ;
6096
6197 public TranslationUnit TranslationUnit => _translationUnit . Value ;
6298
@@ -103,6 +139,6 @@ internal static Cursor Create(CXCursor handle)
103139
104140 public override int GetHashCode ( ) => Handle . GetHashCode ( ) ;
105141
106- public override string ToString ( ) => Handle . ToString ( ) ;
142+ public override string ToString ( ) => Spelling ;
107143 }
108144}
0 commit comments