@@ -79,26 +79,52 @@ file readonly struct UnmanagedWidthCalculator()
7979
8080 private readonly WidthResultCache _cache = new ( ) ;
8181
82- private WidthResult Calc ( ITypeSymbol typeSym )
82+ private WidthResult Calc ( ITypeSymbol typeSym , StringBuilder log )
8383 {
8484 if ( _cache [ typeSym ] is WidthResult cached ) return cached ;
85- if ( ! typeSym . IsValueType ) return _cache . Add ( typeSym , INVALID ) ;
86- if ( typeSym . WidthAsPrimitive ( ) is WidthResult primitive ) return _cache . Add ( typeSym , primitive ) ;
85+ if ( ! typeSym . IsValueType )
86+ {
87+ log . Append ( $ ";{ typeSym . Name } is reference type") ;
88+ return _cache . Add ( typeSym , INVALID ) ;
89+ }
90+ if ( typeSym . WidthAsPrimitive ( ) is WidthResult primitive )
91+ {
92+ log . Append ( $ ";{ typeSym . Name } is primitive { primitive . WidthBytesExpr } ") ;
93+ return _cache . Add ( typeSym , primitive ) ;
94+ }
8795 var fields = typeSym . GetInstanceFields ( ) . ToArray ( ) ;
88- if ( fields . Length <= 1 ) return _cache . Add ( typeSym , fields . Length is 0 ? INVALID : Calc ( fields [ 0 ] . Type ) ) ;
96+ if ( fields . Length <= 1 )
97+ {
98+ if ( fields . Length is 0 )
99+ {
100+ log . Append ( $ ";{ typeSym . Name } has no fields?") ;
101+ return _cache . Add ( typeSym , INVALID ) ;
102+ }
103+ else
104+ {
105+ var single = Calc ( fields [ 0 ] . Type , log ) ;
106+ log . Append ( $ ";{ typeSym . Name } has single field { single . WidthBytesExpr } ") ;
107+ return _cache . Add ( typeSym , single ) ;
108+ }
109+ }
89110 var totalWidth = 0 ;
90111 foreach ( var field in fields )
91112 {
92- var result = Calc ( field . Type ) ;
93- if ( result . WidthBytes < 0 ) return _cache . Add ( typeSym , result ) ;
113+ var result = Calc ( field . Type , log ) ;
114+ if ( result . WidthBytes < 0 )
115+ {
116+ log . Append ( $ ";{ typeSym . Name } has invalid field") ;
117+ return _cache . Add ( typeSym , result ) ;
118+ }
94119 totalWidth += result . WidthBytes ;
95120 }
121+ log . Append ( $ ";{ typeSym . Name } totals { totalWidth } ") ;
96122 return _cache . Add ( typeSym , ( null , totalWidth ) ) ;
97123 }
98124
99- public string For ( ITypeSymbol typeSym )
125+ public string For ( ITypeSymbol typeSym , StringBuilder log )
100126 {
101- var ( widthBytesExpr , widthBytes ) = Calc ( typeSym ) ;
127+ var ( widthBytesExpr , widthBytes ) = Calc ( typeSym , log ) ;
102128 return widthBytesExpr is null ? widthBytes . ToString ( ) : widthBytesExpr ;
103129 }
104130}
@@ -179,7 +205,9 @@ public void Execute(
179205 var isROStruct = sym . IsReadOnly ;
180206 var structName = sym . Name ;
181207 var elemTypeName = elem0Sym . Type . GetCSharpKeywordOrName ( ) ;
182- sb . Append ( $ "\n { indent } [StructLayout(LayoutKind.Sequential, Size = ELEM_COUNT * { sizeCalc . For ( elem0Sym . Type ) } )]\n {
208+ StringBuilder log = new ( ) ;
209+ var widthExpr = sizeCalc . For ( elem0Sym . Type , log ) ;
210+ sb . Append ( $ "\n /*{ log } */\n { indent } [StructLayout(LayoutKind.Sequential, Size = ELEM_COUNT * { widthExpr } )]\n {
183211 indent } [UnsafeValueType]\n {
184212 indent } { sym . GetAccessModifierKeyword ( ) } { ( isROStruct ? "readonly partial struct" : "partial struct" ) } { structName } \n {
185213 indent } {{\n " ) ;
0 commit comments