Skip to content

Commit 67e0b91

Browse files
committed
Writing type names to buffer during translation
1 parent f11c3fd commit 67e0b91

File tree

6 files changed

+222
-115
lines changed

6 files changed

+222
-115
lines changed
Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,45 @@
1-
namespace AgileObjects.ReadableExpressions.Extensions
1+
using System.Linq;
2+
3+
namespace AgileObjects.ReadableExpressions.Extensions
24
{
5+
using System;
36
using System.Collections.Generic;
47

58
internal static class InternalTypeExtensions
69
{
7-
private static readonly Dictionary<string, string> _typeNameSubstitutions = new Dictionary<string, string>
10+
private static readonly Dictionary<Type, string> _typeNameSubstitutions = new Dictionary<Type, string>
811
{
9-
{ typeof(byte).FullName, "byte" },
10-
{ typeof(sbyte).FullName, "sbyte" },
11-
{ typeof(char).FullName, "char" },
12-
{ typeof(bool).FullName, "bool" },
13-
{ typeof(short).FullName, "short" },
14-
{ typeof(ushort).FullName, "ushort" },
15-
{ typeof(int).FullName, "int" },
16-
{ typeof(uint).FullName, "uint" },
17-
{ typeof(long).FullName, "long" },
18-
{ typeof(ulong).FullName, "ulong" },
19-
{ typeof(float).FullName, "float" },
20-
{ typeof(decimal).FullName, "decimal" },
21-
{ typeof(double).FullName, "double" },
22-
{ typeof(string).FullName, "string" },
23-
{ typeof(object).FullName, "object" },
12+
{ typeof(string), "string" },
13+
{ typeof(int), "int" },
14+
{ typeof(bool), "bool" },
15+
{ typeof(decimal), "decimal" },
16+
{ typeof(long), "long" },
17+
{ typeof(double), "double" },
18+
{ typeof(object), "object" },
19+
{ typeof(byte), "byte" },
20+
{ typeof(short), "short" },
21+
{ typeof(float), "float" },
22+
{ typeof(char), "char" },
23+
{ typeof(uint), "uint" },
24+
{ typeof(ulong), "ulong" },
25+
{ typeof(sbyte), "sbyte" },
26+
{ typeof(ushort), "ushort" },
2427
};
2528

2629
internal static ICollection<string> TypeNames => _typeNameSubstitutions.Values;
2730

28-
public static string GetSubstitutionOrNull(this string typeFullName)
31+
public static string GetSubstitutionOrNull(this Type type)
2932
{
30-
return _typeNameSubstitutions.TryGetValue(typeFullName, out var substitutedName)
33+
return _typeNameSubstitutions.TryGetValue(type, out var substitutedName)
3134
? substitutedName : null;
3235
}
36+
37+
public static string GetSubstitutionOrNull(this string typeFullName)
38+
{
39+
var matchingType = _typeNameSubstitutions
40+
.FirstOrDefault(kvp => kvp.Key.FullName == typeFullName);
41+
42+
return matchingType.Value;
43+
}
3344
}
3445
}

ReadableExpressions/Extensions/PublicTypeExtensions.cs

Lines changed: 147 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
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

Comments
 (0)