Skip to content

Commit ecbbbc3

Browse files
committed
Including a return keyword and statement terminator when returning an object init from a block
1 parent 941ee9d commit ecbbbc3

File tree

3 files changed

+86
-11
lines changed

3 files changed

+86
-11
lines changed

ReadableExpressions.UnitTests/WhenTranslatingBlocks.cs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,38 @@ public void ShouldIncludeAReturnKeywordForANewObjectStatement()
389389
Assert.AreEqual(EXPECTED.TrimStart(), translated);
390390
}
391391

392+
[TestMethod]
393+
public void ShouldIncludeAReturnKeywordForAnObjectInitStatement()
394+
{
395+
var exception = Expression.Variable(typeof(Exception), "ex");
396+
var newAddress = Expression.New(typeof(Address).GetConstructors().First());
397+
var line1Property = newAddress.Type.GetMember("Line1").First();
398+
var line1Value = Expression.Constant("Over here");
399+
var line1Init = Expression.Bind(line1Property, line1Value);
400+
var addressInit = Expression.MemberInit(newAddress, line1Init);
401+
var rethrow = Expression.Rethrow(newAddress.Type);
402+
var globalCatchAndRethrow = Expression.Catch(exception, rethrow);
403+
var tryCatch = Expression.TryCatch(addressInit, globalCatchAndRethrow);
404+
405+
var tryCatchBlock = Expression.Block(tryCatch);
406+
407+
var translated = tryCatchBlock.ToReadableString();
408+
409+
const string EXPECTED = @"
410+
try
411+
{
412+
return new WhenTranslatingBlocks.Address
413+
{
414+
Line1 = ""Over here""
415+
};
416+
}
417+
catch
418+
{
419+
throw;
420+
}";
421+
Assert.AreEqual(EXPECTED.TrimStart(), translated);
422+
}
423+
392424
[TestMethod]
393425
public void ShouldIncludeAReturnKeywordForANewListInitStatement()
394426
{
@@ -469,5 +501,15 @@ public void ShouldIncludeAReturnKeywordForANewArrayInitStatement()
469501
}";
470502
Assert.AreEqual(EXPECTED.TrimStart(), translated);
471503
}
504+
505+
#region Helper Classes
506+
507+
private class Address
508+
{
509+
// ReSharper disable once UnusedMember.Local
510+
public string Line1 { get; set; }
511+
}
512+
513+
#endregion
472514
}
473515
}

ReadableExpressions/Extensions/InternalExpressionExtensions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ public static bool IsReturnable(this Expression expression)
3434
case ExpressionType.Invoke:
3535
case ExpressionType.ListInit:
3636
case ExpressionType.MemberAccess:
37+
case ExpressionType.MemberInit:
3738
case ExpressionType.Multiply:
3839
case ExpressionType.MultiplyChecked:
3940
case ExpressionType.New:

ReadableExpressions/Translators/Formatting/CodeBlock.cs

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,21 @@ public static bool IsSingleStatement(IList<string> blockLines)
3434

3535
var numberOfNonIndentedLines = blockLines[0]
3636
.SplitToLines()
37-
.Count(line => line.IsNotIndented() && !line.StartsWith('{') && !line.StartsWith('}'));
37+
.Count(RelevantNonIndentedLine);
3838

3939
return numberOfNonIndentedLines == 1;
4040
}
4141

42+
private CodeBlock(
43+
Expression expression,
44+
string[] blockLines,
45+
bool isASingleStatement)
46+
{
47+
_expression = expression;
48+
_blockLines = blockLines;
49+
IsASingleStatement = isASingleStatement;
50+
}
51+
4252
public bool IsASingleStatement { get; }
4353

4454
public string AsExpressionBody()
@@ -59,19 +69,26 @@ public CodeBlock Indented()
5969

6070
return new CodeBlock(
6171
_expression,
62-
_blockLines.Select(line => line.Indented()).ToArray());
72+
_blockLines.Select(line => line.Indented()).ToArray(),
73+
IsASingleStatement);
6374
}
6475

6576
public CodeBlock Insert(params string[] lines)
6677
{
67-
return new CodeBlock(_expression, lines.Concat(_blockLines).ToArray());
78+
return new CodeBlock(
79+
_expression,
80+
lines.Concat(_blockLines).ToArray(),
81+
isASingleStatement: false);
6882
}
6983

7084
public CodeBlock Append(params string[] lines)
7185
{
7286
AddSemiColonIfRequired();
7387

74-
return new CodeBlock(_expression, _blockLines.Concat(lines).ToArray());
88+
return new CodeBlock(
89+
_expression,
90+
_blockLines.Concat(lines).ToArray(),
91+
isASingleStatement: false);
7592
}
7693

7794
public string WithCurlyBracesIfMultiStatement()
@@ -100,9 +117,7 @@ private static bool ExpressionHasReturn(Expression expression)
100117
{
101118
while (true)
102119
{
103-
var block = expression as BlockExpression;
104-
105-
if (block == null)
120+
if (!(expression is BlockExpression block))
106121
{
107122
return expression.NodeType == ExpressionType.Goto;
108123
}
@@ -140,7 +155,10 @@ private CodeBlock WithReturn()
140155
return this;
141156
}
142157

143-
return new CodeBlock(_expression, GetBlockLinesWithReturnKeyword(_blockLines));
158+
return new CodeBlock(
159+
_expression,
160+
GetBlockLinesWithReturnKeyword(_blockLines),
161+
IsASingleStatement);
144162
}
145163

146164
public static string InsertReturnKeyword(string multiLineStatement)
@@ -166,10 +184,24 @@ private string GetCodeBlock()
166184

167185
private void AddSemiColonIfRequired()
168186
{
169-
if (IsASingleStatement && !_blockLines[0].IsTerminated())
187+
if (!IsASingleStatement)
170188
{
171-
_blockLines[0] += ";";
189+
return;
172190
}
191+
192+
var block = (_blockLines.Length == 1)
193+
? _blockLines[0]
194+
: string.Join(" ", _blockLines);
195+
196+
if (!block.IsTerminated())
197+
{
198+
_blockLines[_blockLines.Length - 1] += ";";
199+
}
200+
}
201+
202+
private static bool RelevantNonIndentedLine(string line)
203+
{
204+
return line.IsNotIndented() && !line.StartsWith('{') && !line.StartsWith('}');
173205
}
174206

175207
private class BlockInfo
@@ -185,7 +217,7 @@ public BlockInfo(string[] blockLines)
185217
_lastNonIndentedStatement = blockLines.Last(line => line.IsNotIndented());
186218

187219
_lastStatementLines = _lastNonIndentedStatement.SplitToLines();
188-
_lastNonIndentedLine = _lastStatementLines.Last(line => line.IsNotIndented());
220+
_lastNonIndentedLine = _lastStatementLines.Last(RelevantNonIndentedLine);
189221
}
190222

191223
public bool LastLineHasReturnKeyword =>

0 commit comments

Comments
 (0)