Skip to content

Commit 1147aef

Browse files
committed
Updating implementation to use a configuration action rather than a supplied object / Tweaking documentation and naming / Adding test
1 parent 73ab4d1 commit 1147aef

File tree

7 files changed

+81
-35
lines changed

7 files changed

+81
-35
lines changed

ReadableExpressions.UnitTests/WhenTranslatingMemberAccesses.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,16 @@ public void ShouldTranslateAMethodCallWithoutGenericArgumentIncluded()
278278
Assert.AreEqual("ip.SetFirst(str)", translated);
279279
}
280280

281+
[TestMethod]
282+
public void ShouldTranslateAMethodCallWithRequestedGenericArgumentsIncluded()
283+
{
284+
Expression<Action<IndexedProperty, string>> setFirstItem = (ip, str) => ip.SetFirst(str);
285+
286+
var translated = setFirstItem.Body.ToReadableString(c => c.UseExplicitGenericParameters);
287+
288+
Assert.AreEqual("ip.SetFirst<string>(str)", translated);
289+
}
290+
281291
[TestMethod]
282292
public void ShouldTranslateAnOutParameterMethodCallWithoutGenericArgumentIncluded()
283293
{

ReadableExpressions/ExpressionExtensions.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
namespace AgileObjects.ReadableExpressions
22
{
3+
using System;
34
using System.Linq.Expressions;
45

56
/// <summary>
@@ -13,12 +14,14 @@ public static class ExpressionExtensions
1314
/// Translates the given <paramref name="expression"/> to source-code string.
1415
/// </summary>
1516
/// <param name="expression">The Expression to translate.</param>
16-
/// <param name="settings">Configuration options for the translation</param>
17+
/// <param name="configuration">The configuration to use for the translation, if required.</param>
1718
/// <returns>The translated <paramref name="expression"/>.</returns>
18-
public static string ToReadableString(this Expression expression, ReadableStringSettings settings = null)
19+
public static string ToReadableString(
20+
this Expression expression,
21+
Func<TranslationSettings, TranslationSettings> configuration = null)
1922
{
2023
return _translatorRegistry
21-
.Translate(expression, settings ?? new ReadableStringSettings())?
24+
.Translate(expression, configuration)?
2225
.WithoutUnindents();
2326
}
2427
}

ReadableExpressions/ExpressionTranslatorRegistry.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
namespace AgileObjects.ReadableExpressions
22
{
3+
using System;
34
using System.Collections.Generic;
45
using System.Linq;
56
using System.Linq.Expressions;
@@ -61,10 +62,12 @@ public ExpressionTranslatorRegistry()
6162
.ToDictionary(t => t.NodeType, t => t.Translator);
6263
}
6364

64-
public string Translate(Expression expression, ReadableStringSettings settings)
65+
public string Translate(
66+
Expression expression,
67+
Func<TranslationSettings, TranslationSettings> configuration)
6568
{
6669
var context = (expression != null)
67-
? TranslationContext.For(expression, Translate, settings)
70+
? TranslationContext.For(expression, Translate, configuration)
6871
: null;
6972

7073
return Translate(expression, context);

ReadableExpressions/ReadableStringSettings.cs

Lines changed: 0 additions & 13 deletions
This file was deleted.

ReadableExpressions/TranslationContext.cs

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,15 @@ public class TranslationContext
1515
{
1616
private readonly ExpressionAnalysisVisitor _analyzer;
1717
private readonly Translator _globalTranslator;
18-
private readonly ReadableStringSettings _settings;
1918

20-
private TranslationContext(ExpressionAnalysisVisitor analyzer, Translator globalTranslator, ReadableStringSettings settings)
19+
private TranslationContext(
20+
ExpressionAnalysisVisitor analyzer,
21+
Translator globalTranslator,
22+
TranslationSettings settings)
2123
{
2224
_analyzer = analyzer;
2325
_globalTranslator = globalTranslator;
24-
_settings = settings;
26+
Settings = settings;
2527
}
2628

2729
/// <summary>
@@ -34,11 +36,23 @@ private TranslationContext(ExpressionAnalysisVisitor analyzer, Translator global
3436
/// <param name="globalTranslator">
3537
/// A global <see cref="Translator"/> delegate with which to perform translations.
3638
/// </param>
37-
/// <param name="settings">Configuration for the translation</param>
39+
/// <param name="configuration">The configuration to use for the translation, if required.</param>
3840
/// <returns>A <see cref="TranslationContext"/> for the given<paramref name="expression"/>.</returns>
39-
public static TranslationContext For(Expression expression, Translator globalTranslator, ReadableStringSettings settings)
41+
public static TranslationContext For(
42+
Expression expression,
43+
Translator globalTranslator,
44+
Func<TranslationSettings, TranslationSettings> configuration = null)
4045
{
41-
return new TranslationContext(ExpressionAnalysisVisitor.Analyse(expression), globalTranslator, settings);
46+
var analyzer = ExpressionAnalysisVisitor.Analyse(expression);
47+
var settings = GetTranslationSettings(configuration);
48+
49+
return new TranslationContext(analyzer, globalTranslator, settings);
50+
}
51+
52+
private static TranslationSettings GetTranslationSettings(
53+
Func<TranslationSettings, TranslationSettings> configuration)
54+
{
55+
return configuration?.Invoke(new TranslationSettings()) ?? TranslationSettings.Default;
4256
}
4357

4458
/// <summary>
@@ -50,7 +64,7 @@ public static TranslationContext For(Expression expression, Translator globalTra
5064
/// <summary>
5165
/// Configuration for translation in this context
5266
/// </summary>
53-
public ReadableStringSettings Settings { get => _settings; }
67+
public TranslationSettings Settings { get; }
5468

5569
/// <summary>
5670
/// Translates the given <paramref name="expression"/> to readable source code.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
namespace AgileObjects.ReadableExpressions
2+
{
3+
/// <summary>
4+
/// Provides configuration options to control aspects of source-code string generation.
5+
/// </summary>
6+
public class TranslationSettings
7+
{
8+
internal static readonly TranslationSettings Default = new TranslationSettings();
9+
10+
internal TranslationSettings()
11+
{
12+
UseImplicitGenericParameters = true;
13+
}
14+
15+
/// <summary>
16+
/// Always specify generic parameter arguments explicitly in &lt;pointy braces&gt;
17+
/// </summary>
18+
public TranslationSettings UseExplicitGenericParameters
19+
{
20+
get
21+
{
22+
UseImplicitGenericParameters = false;
23+
return this;
24+
}
25+
}
26+
27+
internal bool UseImplicitGenericParameters { get; private set; }
28+
}
29+
}

ReadableExpressions/Translators/MethodCallExpressionTranslator.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,12 @@ internal string GetMethodCall(
120120
TranslationContext context)
121121
{
122122
var parametersString = context.TranslateParameters(arguments, method).WithParentheses();
123-
var genericArguments = GetGenericArgumentsIfNecessary(method, context.Settings.AlwaysUseExplicitGenericParameters);
123+
var genericArguments = GetGenericArgumentsIfNecessary(method, context);
124124

125125
return method.Name + genericArguments + parametersString;
126126
}
127127

128-
private static string GetGenericArgumentsIfNecessary(IMethodInfo method, bool alwaysExplicit)
128+
private static string GetGenericArgumentsIfNecessary(IMethodInfo method, TranslationContext context)
129129
{
130130
if (!method.IsGenericMethod)
131131
{
@@ -135,12 +135,12 @@ private static string GetGenericArgumentsIfNecessary(IMethodInfo method, bool al
135135
var methodGenericDefinition = method.GetGenericMethodDefinition();
136136
var genericParameterTypes = methodGenericDefinition.GetGenericArguments().ToList();
137137

138-
if (!alwaysExplicit)
139-
{
140-
RemoveSpecifiedGenericTypeParameters(
141-
methodGenericDefinition.GetParameters().Select(p => p.ParameterType),
142-
genericParameterTypes);
143-
}
138+
if (context.Settings.UseImplicitGenericParameters)
139+
{
140+
RemoveSuppliedGenericTypeParameters(
141+
methodGenericDefinition.GetParameters().Select(p => p.ParameterType),
142+
genericParameterTypes);
143+
}
144144

145145
if (!genericParameterTypes.Any())
146146
{
@@ -161,7 +161,7 @@ private static string GetGenericArgumentsIfNecessary(IMethodInfo method, bool al
161161
return $"<{string.Join(", ", argumentNames)}>";
162162
}
163163

164-
private static void RemoveSpecifiedGenericTypeParameters(
164+
private static void RemoveSuppliedGenericTypeParameters(
165165
IEnumerable<Type> types,
166166
ICollection<Type> genericParameterTypes)
167167
{
@@ -174,7 +174,7 @@ private static void RemoveSpecifiedGenericTypeParameters(
174174

175175
if (type.IsGenericType())
176176
{
177-
RemoveSpecifiedGenericTypeParameters(type.GetGenericArguments(), genericParameterTypes);
177+
RemoveSuppliedGenericTypeParameters(type.GetGenericArguments(), genericParameterTypes);
178178
}
179179
}
180180
}

0 commit comments

Comments
 (0)