4545using  System . Diagnostics . CodeAnalysis ; 
4646using  System . Text ; 
4747
48- namespace  Stravaig . Extensions . Logging . Diagnostics . ExternalHelpers 
48+ namespace  Stravaig . Extensions . Logging . Diagnostics . ExternalHelpers ; 
49+ 
50+ [ ExcludeFromCodeCoverage ] 
51+ internal  static   class  TypeNameHelper 
4952{ 
50-     internal  static   class  TypeNameHelper 
51-     { 
52-         private  const  char  DefaultNestedTypeDelimiter  =  '+' ; 
53+     private  const  char  DefaultNestedTypeDelimiter  =  '+' ; 
5354
54-          private  static   readonly  Dictionary < Type ,  string >  _builtInTypeNames  =  new   Dictionary < Type ,   string > 
55-          { 
56-              {  typeof ( void ) ,  "void"  } , 
57-              {  typeof ( bool ) ,  "bool"  } , 
58-              {  typeof ( byte ) ,  "byte"  } , 
59-              {  typeof ( char ) ,  "char"  } , 
60-              {  typeof ( decimal ) ,  "decimal"  } , 
61-              {  typeof ( double ) ,  "double"  } , 
62-              {  typeof ( float ) ,  "float"  } , 
63-              {  typeof ( int ) ,  "int"  } , 
64-              {  typeof ( long ) ,  "long"  } , 
65-              {  typeof ( object ) ,  "object"  } , 
66-              {  typeof ( sbyte ) ,  "sbyte"  } , 
67-              {  typeof ( short ) ,  "short"  } , 
68-              {  typeof ( string ) ,  "string"  } , 
69-              {  typeof ( uint ) ,  "uint"  } , 
70-              {  typeof ( ulong ) ,  "ulong"  } , 
71-              {  typeof ( ushort ) ,  "ushort"  } 
72-          } ; 
73- 
74-          #if NET7_0_OR_GREATER 
55+     private  static   readonly  Dictionary < Type ,  string >  _builtInTypeNames  =  new ( ) 
56+     { 
57+         {  typeof ( void ) ,  "void"  } , 
58+         {  typeof ( bool ) ,  "bool"  } , 
59+         {  typeof ( byte ) ,  "byte"  } , 
60+         {  typeof ( char ) ,  "char"  } , 
61+         {  typeof ( decimal ) ,  "decimal"  } , 
62+         {  typeof ( double ) ,  "double"  } , 
63+         {  typeof ( float ) ,  "float"  } , 
64+         {  typeof ( int ) ,  "int"  } , 
65+         {  typeof ( long ) ,  "long"  } , 
66+         {  typeof ( object ) ,  "object"  } , 
67+         {  typeof ( sbyte ) ,  "sbyte"  } , 
68+         {  typeof ( short ) ,  "short"  } , 
69+         {  typeof ( string ) ,  "string"  } , 
70+         {  typeof ( uint ) ,  "uint"  } , 
71+         {  typeof ( ulong ) ,  "ulong"  } , 
72+         {  typeof ( ushort ) ,  "ushort"  } 
73+     } ; 
74+ 
75+ #if NET7_0_OR_GREATER 
7576        [ return :  NotNullIfNotNull ( nameof ( item ) ) ] 
76-         #else
77-         [ return :  NotNullIfNotNull ( "item" ) ] 
78-         #endif
79-         public  static   string ?  GetTypeDisplayName ( object ?  item ,  bool  fullName  =  true ) 
77+ #else
78+     [ return :  NotNullIfNotNull ( "item" ) ] 
79+ #endif
80+     public  static   string ?  GetTypeDisplayName ( object ?  item ,  bool  fullName  =  true ) 
81+     { 
82+         return  item  ==  null  ?  null  :  GetTypeDisplayName ( item . GetType ( ) ,  fullName ) ; 
83+     } 
84+ 
85+     /// <summary> 
86+     /// Pretty print a type name. 
87+     /// </summary> 
88+     /// <param name="type">The <see cref="Type"/>.</param> 
89+     /// <param name="fullName"><c>true</c> to print a fully qualified name.</param> 
90+     /// <param name="includeGenericParameterNames"><c>true</c> to include generic parameter names.</param> 
91+     /// <param name="includeGenericParameters"><c>true</c> to include generic parameters.</param> 
92+     /// <param name="nestedTypeDelimiter">Character to use as a delimiter in nested type names</param> 
93+     /// <returns>The pretty printed type name.</returns> 
94+     public  static   string  GetTypeDisplayName ( Type  type ,  bool  fullName  =  true ,  bool  includeGenericParameterNames  =  false ,  bool  includeGenericParameters  =  true ,  char  nestedTypeDelimiter  =  DefaultNestedTypeDelimiter ) 
95+     { 
96+         StringBuilder ?  builder  =  null ; 
97+         string ?  name  =  ProcessType ( ref  builder ,  type ,  new  DisplayNameOptions ( fullName ,  includeGenericParameterNames ,  includeGenericParameters ,  nestedTypeDelimiter ) ) ; 
98+         return  name  ??  builder ? . ToString ( )  ??  string . Empty ; 
99+     } 
100+ 
101+     private  static   string ?  ProcessType ( ref  StringBuilder ?  builder ,  Type  type ,  in  DisplayNameOptions  options ) 
102+     { 
103+         if  ( type . IsGenericType ) 
80104        { 
81-             return  item  ==  null  ?  null  :  GetTypeDisplayName ( item . GetType ( ) ,  fullName ) ; 
105+             Type [ ]  genericArguments  =  type . GetGenericArguments ( ) ; 
106+             builder  ??=  new  StringBuilder ( ) ; 
107+             ProcessGenericType ( builder ,  type ,  genericArguments ,  genericArguments . Length ,  options ) ; 
82108        } 
83- 
84-         /// <summary> 
85-         /// Pretty print a type name. 
86-         /// </summary> 
87-         /// <param name="type">The <see cref="Type"/>.</param> 
88-         /// <param name="fullName"><c>true</c> to print a fully qualified name.</param> 
89-         /// <param name="includeGenericParameterNames"><c>true</c> to include generic parameter names.</param> 
90-         /// <param name="includeGenericParameters"><c>true</c> to include generic parameters.</param> 
91-         /// <param name="nestedTypeDelimiter">Character to use as a delimiter in nested type names</param> 
92-         /// <returns>The pretty printed type name.</returns> 
93-         public  static   string  GetTypeDisplayName ( Type  type ,  bool  fullName  =  true ,  bool  includeGenericParameterNames  =  false ,  bool  includeGenericParameters  =  true ,  char  nestedTypeDelimiter  =  DefaultNestedTypeDelimiter ) 
109+         else  if  ( type . IsArray ) 
94110        { 
95-             StringBuilder ?  builder  =  null ; 
96-             string ?  name  =  ProcessType ( ref  builder ,  type ,  new  DisplayNameOptions ( fullName ,  includeGenericParameterNames ,  includeGenericParameters ,  nestedTypeDelimiter ) ) ; 
97-             return  name  ??  builder ? . ToString ( )  ??  string . Empty ; 
111+             builder  ??=  new  StringBuilder ( ) ; 
112+             ProcessArrayType ( builder ,  type ,  options ) ; 
98113        } 
114+         else  if  ( _builtInTypeNames . TryGetValue ( type ,  out  string ?  builtInName ) ) 
115+         { 
116+             if  ( builder  is  null )  return  builtInName ; 
99117
100-         private  static   string ?  ProcessType ( ref  StringBuilder ?  builder ,  Type  type ,  in  DisplayNameOptions  options ) 
118+             builder . Append ( builtInName ) ; 
119+         } 
120+         else  if  ( type . IsGenericParameter ) 
101121        { 
102-             if  ( type . IsGenericType ) 
103-             { 
104-                 Type [ ]  genericArguments  =  type . GetGenericArguments ( ) ; 
105-                 builder  ??=  new  StringBuilder ( ) ; 
106-                 ProcessGenericType ( builder ,  type ,  genericArguments ,  genericArguments . Length ,  options ) ; 
107-             } 
108-             else  if  ( type . IsArray ) 
109-             { 
110-                 builder  ??=  new  StringBuilder ( ) ; 
111-                 ProcessArrayType ( builder ,  type ,  options ) ; 
112-             } 
113-             else  if  ( _builtInTypeNames . TryGetValue ( type ,  out  string ?  builtInName ) ) 
122+             if  ( options . IncludeGenericParameterNames ) 
114123            { 
115-                 if  ( builder  is  null )  return  builtInName ; 
124+                 if  ( builder  is  null )  return  type . Name ; 
116125
117-                 builder . Append ( builtInName ) ; 
126+                 builder . Append ( type . Name ) ; 
118127            } 
119-             else  if  ( type . IsGenericParameter ) 
120-             { 
121-                 if  ( options . IncludeGenericParameterNames ) 
122-                 { 
123-                     if  ( builder  is  null )  return  type . Name ; 
128+         } 
129+         else 
130+         { 
131+             string  name  =  options . FullName  ?  type . FullName !  :  type . Name ; 
124132
125-                     builder . Append ( type . Name ) ; 
126-                 } 
127-             } 
128-             else 
133+             if  ( builder  is  null ) 
129134            { 
130-                 string  name  =  options . FullName  ?  type . FullName !  :  type . Name ; 
131- 
132-                 if  ( builder  is  null ) 
133-                 { 
134-                     if  ( options . NestedTypeDelimiter  !=  DefaultNestedTypeDelimiter ) 
135-                     { 
136-                         return  name . Replace ( DefaultNestedTypeDelimiter ,  options . NestedTypeDelimiter ) ; 
137-                     } 
138- 
139-                     return  name ; 
140-                 } 
141- 
142-                 builder . Append ( name ) ; 
143135                if  ( options . NestedTypeDelimiter  !=  DefaultNestedTypeDelimiter ) 
144136                { 
145-                     builder . Replace ( DefaultNestedTypeDelimiter ,  options . NestedTypeDelimiter ,   builder . Length   -   name . Length ,   name . Length ) ; 
137+                     return   name . Replace ( DefaultNestedTypeDelimiter ,  options . NestedTypeDelimiter ) ; 
146138                } 
139+ 
140+                 return  name ; 
147141            } 
148142
149-             return  null ; 
143+             builder . Append ( name ) ; 
144+             if  ( options . NestedTypeDelimiter  !=  DefaultNestedTypeDelimiter ) 
145+             { 
146+                 builder . Replace ( DefaultNestedTypeDelimiter ,  options . NestedTypeDelimiter ,  builder . Length  -  name . Length ,  name . Length ) ; 
147+             } 
150148        } 
151149
152-         private  static   void  ProcessArrayType ( StringBuilder  builder ,  Type  type ,  in  DisplayNameOptions  options ) 
150+         return  null ; 
151+     } 
152+ 
153+     private  static   void  ProcessArrayType ( StringBuilder  builder ,  Type  type ,  in  DisplayNameOptions  options ) 
154+     { 
155+         Type  innerType  =  type ; 
156+         while  ( innerType . IsArray ) 
153157        { 
154-             Type  innerType  =  type ; 
155-             while  ( innerType . IsArray ) 
156-             { 
157-                 innerType  =  innerType . GetElementType ( ) ! ; 
158-             } 
158+             innerType  =  innerType . GetElementType ( ) ! ; 
159+         } 
159160
160-              ProcessType ( ref  builder ! ,  innerType ,  options ) ; 
161+         ProcessType ( ref  builder ! ,  innerType ,  options ) ; 
161162
162-             while  ( type . IsArray ) 
163-             { 
164-                 builder . Append ( '[' ) ; 
165-                 builder . Append ( ',' ,  type . GetArrayRank ( )  -  1 ) ; 
166-                 builder . Append ( ']' ) ; 
167-                 type  =  type . GetElementType ( ) ! ; 
168-             } 
163+         while  ( type . IsArray ) 
164+         { 
165+             builder . Append ( '[' ) ; 
166+             builder . Append ( ',' ,  type . GetArrayRank ( )  -  1 ) ; 
167+             builder . Append ( ']' ) ; 
168+             type  =  type . GetElementType ( ) ! ; 
169169        } 
170+     } 
170171
171-         private  static   void  ProcessGenericType ( StringBuilder  builder ,  Type  type ,  Type [ ]  genericArguments ,  int  length ,  in  DisplayNameOptions  options ) 
172+     private  static   void  ProcessGenericType ( StringBuilder  builder ,  Type  type ,  Type [ ]  genericArguments ,  int  length ,  in  DisplayNameOptions  options ) 
173+     { 
174+         int  offset  =  0 ; 
175+         if  ( type . IsNested ) 
176+         { 
177+             offset  =  type . DeclaringType ! . GetGenericArguments ( ) . Length ; 
178+         } 
179+ 
180+         if  ( options . FullName ) 
172181        { 
173-             int  offset  =  0 ; 
174182            if  ( type . IsNested ) 
175183            { 
176-                 offset  =  type . DeclaringType ! . GetGenericArguments ( ) . Length ; 
184+                 ProcessGenericType ( builder ,  type . DeclaringType ! ,  genericArguments ,  offset ,  options ) ; 
185+                 builder . Append ( options . NestedTypeDelimiter ) ; 
177186            } 
178- 
179-             if  ( options . FullName ) 
187+             else  if  ( ! string . IsNullOrEmpty ( type . Namespace ) ) 
180188            { 
181-                 if  ( type . IsNested ) 
182-                 { 
183-                     ProcessGenericType ( builder ,  type . DeclaringType ! ,  genericArguments ,  offset ,  options ) ; 
184-                     builder . Append ( options . NestedTypeDelimiter ) ; 
185-                 } 
186-                 else  if  ( ! string . IsNullOrEmpty ( type . Namespace ) ) 
187-                 { 
188-                     builder . Append ( type . Namespace ) ; 
189-                     builder . Append ( '.' ) ; 
190-                 } 
189+                 builder . Append ( type . Namespace ) ; 
190+                 builder . Append ( '.' ) ; 
191191            } 
192+         } 
192193
193-              int  genericPartIndex  =  type . Name . IndexOf ( '`' ) ; 
194-              if  ( genericPartIndex  <=  0 ) 
195-              { 
196-                  builder . Append ( type . Name ) ; 
197-                  return ; 
198-              } 
194+         int  genericPartIndex  =  type . Name . IndexOf ( '`' ) ; 
195+         if  ( genericPartIndex  <=  0 ) 
196+         { 
197+             builder . Append ( type . Name ) ; 
198+             return ; 
199+         } 
199200
200-              builder . Append ( type . Name ,  0 ,  genericPartIndex ) ; 
201+         builder . Append ( type . Name ,  0 ,  genericPartIndex ) ; 
201202
202-             if  ( options . IncludeGenericParameters ) 
203+         if  ( options . IncludeGenericParameters ) 
204+         { 
205+             builder . Append ( '<' ) ; 
206+             for  ( int  i  =  offset ;  i  <  length ;  i ++ ) 
203207            { 
204-                 builder . Append ( '<' ) ; 
205-                 for   ( int   i   =   offset ;   i   <   length ;   i ++ ) 
208+                 ProcessType ( ref   builder ! ,   genericArguments [ i ] ,   options ) ; 
209+                 if   ( i   +   1   ==   length ) 
206210                { 
207-                     ProcessType ( ref  builder ! ,  genericArguments [ i ] ,  options ) ; 
208-                     if  ( i  +  1  ==  length ) 
209-                     { 
210-                         continue ; 
211-                     } 
212- 
213-                     builder . Append ( ',' ) ; 
214-                     if  ( options . IncludeGenericParameterNames  ||  ! genericArguments [ i  +  1 ] . IsGenericParameter ) 
215-                     { 
216-                         builder . Append ( ' ' ) ; 
217-                     } 
211+                     continue ; 
212+                 } 
213+ 
214+                 builder . Append ( ',' ) ; 
215+                 if  ( options . IncludeGenericParameterNames  ||  ! genericArguments [ i  +  1 ] . IsGenericParameter ) 
216+                 { 
217+                     builder . Append ( ' ' ) ; 
218218                } 
219-                 builder . Append ( '>' ) ; 
220219            } 
220+             builder . Append ( '>' ) ; 
221221        } 
222+     } 
222223
223-         private  readonly  struct  DisplayNameOptions 
224+     private  readonly  struct  DisplayNameOptions 
225+     { 
226+         public  DisplayNameOptions ( bool  fullName ,  bool  includeGenericParameterNames ,  bool  includeGenericParameters ,  char  nestedTypeDelimiter ) 
224227        { 
225-             public  DisplayNameOptions ( bool  fullName ,  bool  includeGenericParameterNames ,  bool  includeGenericParameters ,  char  nestedTypeDelimiter ) 
226-             { 
227-                 FullName  =  fullName ; 
228-                 IncludeGenericParameters  =  includeGenericParameters ; 
229-                 IncludeGenericParameterNames  =  includeGenericParameterNames ; 
230-                 NestedTypeDelimiter  =  nestedTypeDelimiter ; 
231-             } 
228+             FullName  =  fullName ; 
229+             IncludeGenericParameters  =  includeGenericParameters ; 
230+             IncludeGenericParameterNames  =  includeGenericParameterNames ; 
231+             NestedTypeDelimiter  =  nestedTypeDelimiter ; 
232+         } 
232233
233-              public  bool  FullName  {  get ;  } 
234+         public  bool  FullName  {  get ;  } 
234235
235-              public  bool  IncludeGenericParameters  {  get ;  } 
236+         public  bool  IncludeGenericParameters  {  get ;  } 
236237
237-              public  bool  IncludeGenericParameterNames  {  get ;  } 
238+         public  bool  IncludeGenericParameterNames  {  get ;  } 
238239
239-             public  char  NestedTypeDelimiter  {  get ;  } 
240-         } 
240+         public  char  NestedTypeDelimiter  {  get ;  } 
241241    } 
242- } 
242+ } 
0 commit comments