1- namespace AgileObjects . ReadableExpressions . Extensions
1+ using AgileObjects . ReadableExpressions . Translations ;
2+
3+ namespace AgileObjects . ReadableExpressions . Extensions
24{
35 using System ;
46 using System . Collections ;
@@ -29,59 +31,120 @@ internal static string GetFriendlyName(this Type type, TranslationSettings trans
2931 return null ;
3032 }
3133
34+ var buffer = new TranslationBuffer ( type . FullName . Length ) ;
35+
36+ buffer . WriteFriendlyName ( type , translationSettings ) ;
37+
38+ return buffer . GetContent ( ) ;
39+ }
40+
41+ internal static void WriteFriendlyName (
42+ this TranslationBuffer buffer ,
43+ Type type ,
44+ TranslationSettings settings )
45+ {
46+ if ( type . FullName == null )
47+ {
48+ // An open generic parameter Type:
49+ return ;
50+ }
51+
3252 if ( type . IsArray )
3353 {
34- return type . GetElementType ( ) . GetFriendlyName ( translationSettings ) + "[]" ;
54+ buffer . WriteFriendlyName ( type . GetElementType ( ) , settings ) ;
55+ buffer . WriteToTranslation ( "[]" ) ;
56+ return ;
3557 }
3658
3759 if ( ! type . IsGenericType ( ) )
3860 {
39- var substitutedTypeName = type . FullName . GetSubstitutionOrNull ( ) ;
40- var qualifiedTypeName = substitutedTypeName ?? type . Name ;
61+ var substitutedTypeName = type . GetSubstitutionOrNull ( ) ;
4162
4263 if ( type . IsNested )
4364 {
44- return type . DeclaringType . GetFriendlyName ( translationSettings ) + "." + qualifiedTypeName ;
65+ buffer . WriteFriendlyName ( type . DeclaringType , settings ) ;
66+ buffer . WriteToTranslation ( '.' ) ;
67+ buffer . WriteToTranslation ( substitutedTypeName ?? type . Name ) ;
68+ return ;
69+ }
70+
71+ if ( substitutedTypeName != null )
72+ {
73+ buffer . WriteToTranslation ( substitutedTypeName ) ;
74+ return ;
4575 }
4676
47- return ( substitutedTypeName == null )
48- ? GetFinalisedTypeName ( type , qualifiedTypeName , translationSettings )
49- : qualifiedTypeName ;
77+ buffer . WriteTypeNamespaceIfRequired ( type , settings ) ;
78+ buffer . WriteToTranslation ( type . Name ) ;
79+ return ;
5080 }
5181
5282 Type underlyingNullableType ;
5383
54- if ( ( underlyingNullableType = Nullable . GetUnderlyingType ( type ) ) ! = null )
84+ if ( ( underlyingNullableType = Nullable . GetUnderlyingType ( type ) ) = = null )
5585 {
56- return underlyingNullableType . GetFriendlyName ( translationSettings ) + "?" ;
86+ buffer . WriteGenericTypeName ( type , settings ) ;
87+ return ;
5788 }
5889
59- return GetGenericTypeName ( type , translationSettings ) ;
90+ buffer . WriteFriendlyName ( underlyingNullableType , settings ) ;
91+ buffer . WriteToTranslation ( '?' ) ;
6092 }
6193
62- private static string GetGenericTypeName ( Type genericType , TranslationSettings settings )
94+ private static void WriteTypeNamespaceIfRequired (
95+ this TranslationBuffer buffer ,
96+ Type type ,
97+ TranslationSettings settings )
98+ {
99+ if ( ! settings . FullyQualifyTypeNames || ( type . Namespace == null ) )
100+ {
101+ return ;
102+ }
103+
104+ buffer . WriteToTranslation ( type . Namespace ) ;
105+ buffer . WriteToTranslation ( '.' ) ;
106+ }
107+
108+ private static void WriteGenericTypeName (
109+ this TranslationBuffer buffer ,
110+ Type genericType ,
111+ TranslationSettings settings )
63112 {
64113 var typeGenericTypeArguments = genericType . GetGenericTypeArguments ( ) ;
65- var genericTypeName = GetClosedGenericTypeName ( genericType , ref typeGenericTypeArguments , settings ) ;
66114
67115 if ( ! genericType . IsNested )
68116 {
69- return GetFinalisedTypeName ( genericType , genericTypeName , settings ) ;
117+ buffer . WriteTypeNamespaceIfRequired ( genericType , settings ) ;
118+ buffer . WriteClosedGenericTypeName ( genericType , ref typeGenericTypeArguments , settings ) ;
119+ return ;
70120 }
71121
122+ var types = new List < Type > { genericType } ;
123+
72124 // ReSharper disable once PossibleNullReferenceException
73125 while ( genericType . IsNested )
74126 {
75127 genericType = genericType . DeclaringType ;
76- var parentTypeName = GetClosedGenericTypeName ( genericType , ref typeGenericTypeArguments , settings ) ;
77-
78- genericTypeName = parentTypeName + "." + genericTypeName ;
128+ types . Add ( genericType ) ;
79129 }
80130
81- return GetFinalisedTypeName ( genericType , genericTypeName , settings ) ;
131+ buffer . WriteTypeNamespaceIfRequired ( genericType , settings ) ;
132+
133+ for ( var i = types . Count ; ; )
134+ {
135+ buffer . WriteClosedGenericTypeName ( types [ -- i ] , ref typeGenericTypeArguments , settings ) ;
136+
137+ if ( i == 0 )
138+ {
139+ return ;
140+ }
141+
142+ buffer . WriteToTranslation ( '.' ) ;
143+ }
82144 }
83145
84- private static string GetClosedGenericTypeName (
146+ private static void WriteClosedGenericTypeName (
147+ this TranslationBuffer buffer ,
85148 Type genericType ,
86149 ref Type [ ] typeGenericTypeArguments ,
87150 TranslationSettings settings )
@@ -92,7 +155,8 @@ private static string GetClosedGenericTypeName(
92155
93156 if ( backtickIndex == - 1 )
94157 {
95- return typeName ;
158+ buffer . WriteToTranslation ( typeName ) ;
159+ return ;
96160 }
97161
98162 var numberOfParameters = int . Parse ( typeName . Substring ( backtickIndex + 1 ) ) ;
@@ -102,79 +166,93 @@ private static string GetClosedGenericTypeName(
102166 if ( numberOfParameters == typeGenericTypeArguments . Length )
103167 {
104168 typeArguments = typeGenericTypeArguments ;
169+ goto WriteName ;
105170 }
106- else
171+
172+ switch ( numberOfParameters )
107173 {
108- typeArguments = new Type [ numberOfParameters ] ;
109- var numberOfRemainingTypeArguments = typeGenericTypeArguments . Length - numberOfParameters ;
110- var typeGenericTypeArgumentsSubset = new Type [ numberOfRemainingTypeArguments ] ;
111-
112- Array . Copy (
113- typeGenericTypeArguments ,
114- numberOfRemainingTypeArguments ,
115- typeArguments ,
116- 0 ,
117- numberOfParameters ) ;
118-
119- Array . Copy (
120- typeGenericTypeArguments ,
121- 0 ,
122- typeGenericTypeArgumentsSubset ,
123- 0 ,
124- numberOfRemainingTypeArguments ) ;
125-
126- typeGenericTypeArguments = typeGenericTypeArgumentsSubset ;
174+ case 1 :
175+ typeArguments = new [ ] { typeGenericTypeArguments [ 0 ] } ;
176+ break ;
177+
178+ case 2 :
179+ typeArguments = new [ ] { typeGenericTypeArguments [ 0 ] , typeGenericTypeArguments [ 1 ] } ;
180+ break ;
181+
182+ default :
183+ typeArguments = new Type [ numberOfParameters ] ;
184+
185+ Array . Copy (
186+ typeGenericTypeArguments ,
187+ typeArguments ,
188+ numberOfParameters ) ;
189+
190+ break ;
127191 }
128192
129- return GetGenericTypeName ( genericType , numberOfParameters , typeArguments , settings ) ;
193+ var numberOfRemainingTypeArguments = typeGenericTypeArguments . Length - numberOfParameters ;
194+ var typeGenericTypeArgumentsSubset = new Type [ numberOfRemainingTypeArguments ] ;
195+
196+ Array . Copy (
197+ typeGenericTypeArguments ,
198+ numberOfParameters ,
199+ typeGenericTypeArgumentsSubset ,
200+ 0 ,
201+ numberOfRemainingTypeArguments ) ;
202+
203+ typeGenericTypeArguments = typeGenericTypeArgumentsSubset ;
204+
205+ WriteName :
206+ buffer . WriteGenericTypeName ( genericType , numberOfParameters , typeArguments , settings ) ;
130207 }
131208
132- private static string GetGenericTypeName (
209+ private static void WriteGenericTypeName (
210+ this TranslationBuffer buffer ,
133211 Type type ,
134212 int numberOfParameters ,
135213 IList < Type > typeArguments ,
136214 TranslationSettings settings )
137215 {
138- var anonTypeIndex = 0 ;
139-
140216 var isAnonType =
141217 type . Name . StartsWith ( '<' ) &&
142- ( ( anonTypeIndex = type . Name . IndexOf ( "AnonymousType" , StringComparison . Ordinal ) ) != - 1 ) ;
218+ ( type . Name . IndexOf ( "AnonymousType" , StringComparison . Ordinal ) ) != - 1 ;
143219
144220 if ( isAnonType && ( settings . AnonymousTypeNameFactory != null ) )
145221 {
146- return settings . AnonymousTypeNameFactory . Invoke ( type ) ;
222+ buffer . WriteToTranslation ( settings . AnonymousTypeNameFactory . Invoke ( type ) ) ;
223+ return ;
147224 }
148225
149- var typeName = type . Name ;
226+ string typeName ;
150227
151- var typeGenericTypeArgumentNames = typeArguments
152- . ProjectToArray ( t => GetFriendlyName ( t , settings ) ) ;
153-
154- typeName = typeName . Replace (
155- "`" + numberOfParameters ,
156- "<" + typeGenericTypeArgumentNames . Join ( ", " ) + ">" ) ;
228+ if ( isAnonType )
229+ {
230+ typeName = "AnonymousType" ;
231+ }
232+ else
233+ {
234+ var parameterCountIndex = type . Name . IndexOf ( "`" + numberOfParameters , StringComparison . Ordinal ) ;
235+ typeName = type . Name . Substring ( 0 , parameterCountIndex ) ;
236+ }
157237
158- return isAnonType ? GetAnonymousTypeName ( typeName , anonTypeIndex ) : typeName ;
159- }
238+ buffer . WriteToTranslation ( typeName ) ;
239+ buffer . WriteToTranslation ( '<' ) ;
160240
161- private static string GetAnonymousTypeName ( string typeName , int anonTypeIndex )
162- {
163- typeName = typeName . Substring ( anonTypeIndex ) ;
241+ for ( var i = 0 ; ; )
242+ {
243+ var typeArgument = typeArguments [ i ++ ] ;
164244
165- var trimStartIndex = "AnonymousType" . Length ;
166- var argumentsStartIndex = typeName . IndexOf ( '<' ) ;
245+ buffer . WriteFriendlyName ( typeArgument , settings ) ;
167246
168- typeName = typeName . Remove ( trimStartIndex , argumentsStartIndex - trimStartIndex ) ;
247+ if ( i == typeArguments . Count )
248+ {
249+ break ;
250+ }
169251
170- return typeName ;
171- }
252+ buffer . WriteToTranslation ( ", " ) ;
253+ }
172254
173- private static string GetFinalisedTypeName ( Type type , string typeName , TranslationSettings settings )
174- {
175- return settings . FullyQualifyTypeNames && ( type . Namespace != null )
176- ? type . Namespace + "." + typeName
177- : typeName ;
255+ buffer . WriteToTranslation ( '>' ) ;
178256 }
179257
180258 /// <summary>
@@ -198,7 +276,7 @@ internal static string GetVariableNameInCamelCase(this Type type, TranslationSet
198276 public static string GetVariableNameInPascalCase ( this Type type , Func < TranslationSettings , TranslationSettings > configuration = null )
199277 => GetVariableNameInPascalCase ( type , GetTranslationSettings ( configuration ) ) ;
200278
201- internal static string GetVariableNameInPascalCase ( this Type type , TranslationSettings settings )
279+ private static string GetVariableNameInPascalCase ( this Type type , TranslationSettings settings )
202280 => GetVariableName ( type , settings ) . ToPascalCase ( ) ;
203281
204282 private static string GetVariableName ( Type type , TranslationSettings settings )
0 commit comments