Skip to content

Commit c146b50

Browse files
committed
Fix return of lambda within BlockExpression
1 parent fcea3e6 commit c146b50

File tree

5 files changed

+119
-13
lines changed

5 files changed

+119
-13
lines changed

Shared/CSharpCodeWriter.cs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,16 @@ protected override void WriteLambda(LambdaExpression expr) {
213213
Write("{");
214214
Indent();
215215
WriteEOL();
216-
if (expr.Body.Type != typeof(void)) { Write("return "); }
217-
WriteNode("Body", expr.Body, CreateMetadata(CSharpMultilineBlockTypes.Block));
216+
217+
CSharpMultilineBlockTypes blockType = CSharpMultilineBlockTypes.Block;
218+
if (expr.Body.Type != typeof(void)) {
219+
if (expr.Body is BlockExpression bexpr && bexpr.HasMultipleLines()) {
220+
blockType = CSharpMultilineBlockTypes.Return;
221+
} else {
222+
Write("return ");
223+
}
224+
}
225+
WriteNode("Body", expr.Body, CreateMetadata(blockType));
218226
WriteStatementEnd(expr.Body);
219227
WriteEOL(true);
220228
Write("}");
@@ -535,7 +543,7 @@ protected override void WriteIndex(IndexExpression expr) =>
535543
protected override void WriteBlock(BlockExpression expr, object metadata) {
536544
var (blockType, parentIsBlock) = (CSharpBlockMetadata)metadata ?? CreateMetadata(Inline, false);
537545
bool introduceNewBlock;
538-
if (blockType == CSharpMultilineBlockTypes.Block) {
546+
if (blockType.In(CSharpMultilineBlockTypes.Block, CSharpMultilineBlockTypes.Return)) {
539547
introduceNewBlock = expr.Variables.Any() && parentIsBlock;
540548
if (introduceNewBlock) {
541549
Write("{");
@@ -550,7 +558,16 @@ protected override void WriteBlock(BlockExpression expr, object metadata) {
550558
expr.Expressions.ForEach((subexpr, index) => {
551559
if (index > 0) { WriteEOL(); }
552560
if (subexpr is LabelExpression) { TrimEnd(); }
553-
WriteNode($"Expressions[{index}]", subexpr, CreateMetadata(blockType, true));
561+
if (blockType == CSharpMultilineBlockTypes.Return && index == expr.Expressions.Count-1) {
562+
if (subexpr is BlockExpression bexpr && bexpr.HasMultipleLines()) {
563+
WriteNode($"Expressions[{index}]", subexpr, CreateMetadata(CSharpMultilineBlockTypes.Return, true));
564+
} else {
565+
Write("return ");
566+
WriteNode($"Expressions[{index}]", subexpr, CreateMetadata(CSharpMultilineBlockTypes.Block, true));
567+
}
568+
} else {
569+
WriteNode($"Expressions[{index}]", subexpr, CreateMetadata(CSharpMultilineBlockTypes.Block, true));
570+
}
554571
WriteStatementEnd(subexpr);
555572
});
556573
if (introduceNewBlock) {
@@ -712,7 +729,7 @@ protected override void WriteGoto(GotoExpression expr) {
712729
case GotoExpressionKind.Goto:
713730
gotoKeyword = "goto";
714731
break;
715-
case Return:
732+
case GotoExpressionKind.Return:
716733
gotoKeyword = "return";
717734
break;
718735
default:

Shared/CSharpMultilineBlockTypes.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace ExpressionToString {
88
public enum CSharpMultilineBlockTypes {
99
Inline,
1010
Test,
11-
Block
11+
Block,
12+
Return
1213
}
1314
}

Shared/VBCodeWriter.cs

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,16 @@ protected override void WriteLambda(LambdaExpression expr) {
270270

271271
Indent();
272272
WriteEOL();
273-
if (expr.Body.Type != typeof(void)) { Write("Return "); }
274-
WriteNode("Body", expr.Body, CreateMetadata(true, Lambda));
273+
274+
bool returnBlock = false;
275+
if (expr.Body.Type != typeof(void)) {
276+
if (expr.Body is BlockExpression bexpr && bexpr.HasMultipleLines()) {
277+
returnBlock = true;
278+
} else {
279+
Write("Return ");
280+
}
281+
}
282+
WriteNode("Body", expr.Body, CreateMetadata(true, Lambda, returnBlock));
275283
WriteEOL(true);
276284
Write($"End {lambdaKeyword}");
277285
}
@@ -649,7 +657,7 @@ protected override void WriteIndex(IndexExpression expr) =>
649657
WriteIndexerAccess("Object", expr.Object, "Arguments", expr.Arguments);
650658

651659
protected override void WriteBlock(BlockExpression expr, object metadata) {
652-
var (isInMultiline, parentType) = (VBExpressionMetadata)metadata ?? CreateMetadata(false, null);
660+
var (isInMultiline, parentType, returnBlock) = (VBExpressionMetadata)metadata ?? CreateMetadata(false, null, false);
653661
var useBlockConstruct = !isInMultiline ||
654662
(expr.Variables.Any() && parentType == Block);
655663
if (useBlockConstruct) {
@@ -665,7 +673,16 @@ protected override void WriteBlock(BlockExpression expr, object metadata) {
665673
expr.Expressions.ForEach((subexpr, index) => {
666674
if (index > 0 || expr.Variables.Count > 0) { WriteEOL(); }
667675
if (subexpr is LabelExpression) { TrimEnd(); }
668-
WriteNode($"Expressions[{index}]", subexpr, CreateMetadata(true, Block));
676+
677+
var outgoingMetadata = CreateMetadata(true, Block);
678+
if (returnBlock && index == expr.Expressions.Count - 1) {
679+
if (subexpr is BlockExpression bexpr && bexpr.HasMultipleLines()) {
680+
outgoingMetadata = CreateMetadata(true, Block, true);
681+
} else {
682+
Write("Return ");
683+
}
684+
}
685+
WriteNode($"Expressions[{index}]", subexpr, outgoingMetadata);
669686
});
670687
if (useBlockConstruct) {
671688
WriteEOL(true);

Shared/VBExpressionMetadata.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,16 @@ namespace ExpressionToString {
99
internal class VBExpressionMetadata {
1010
internal bool IsInMutiline { get; private set; } = false;
1111
internal ExpressionType? ExpressionType { get; private set; } = null;
12-
internal static VBExpressionMetadata CreateMetadata(bool isInMultiline = false, ExpressionType? expressionType = null) => new VBExpressionMetadata {
12+
internal bool ReturnBkock { get; private set; } = false;
13+
internal static VBExpressionMetadata CreateMetadata(bool isInMultiline = false, ExpressionType? expressionType = null, bool returnBlock = false) => new VBExpressionMetadata {
1314
IsInMutiline = isInMultiline,
14-
ExpressionType = expressionType
15+
ExpressionType = expressionType,
16+
ReturnBkock = returnBlock
1517
};
16-
internal void Deconstruct(out bool isInMultiline, out ExpressionType? expressionType) {
18+
internal void Deconstruct(out bool isInMultiline, out ExpressionType? expressionType, out bool returnBlock) {
1719
isInMultiline = IsInMutiline;
1820
expressionType = ExpressionType;
21+
returnBlock = ReturnBkock;
1922
}
2023
}
2124
}

Tests.Common/Constructed/MakeLambda.cs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,5 +178,73 @@ Return Function(s1 As String, s2 As String) s1 + s2
178178
)
179179
)"
180180
);
181+
182+
[Fact]
183+
[Trait("Category", Lambdas)]
184+
public void LambdaMultilineBlockNonvoidReturn() => RunTest(
185+
Lambda(
186+
Block(
187+
Constant(true),
188+
Constant(true)
189+
)
190+
),
191+
@"() => {
192+
true;
193+
return true;
194+
}",
195+
@"Function()
196+
True
197+
Return True
198+
End Function",
199+
@"Lambda(
200+
Block(
201+
Constant(true),
202+
Constant(true)
203+
)
204+
)"
205+
);
206+
207+
[Fact]
208+
[Trait("Category", Lambdas)]
209+
public void LambdaMultilineNestedBlockNonvoidReturn() => RunTest(
210+
Lambda(
211+
Block(
212+
Constant(true),
213+
Block(
214+
new[] { s1, s2 },
215+
Constant(true),
216+
Constant(true)
217+
)
218+
)
219+
),
220+
@"() => {
221+
true;
222+
{
223+
string s1;
224+
string s2;
225+
true;
226+
return true;
227+
}
228+
}",
229+
@"Function()
230+
True
231+
Block
232+
Dim s1 As String
233+
Dim s2 As String
234+
True
235+
Return True
236+
End Block
237+
End Function",
238+
@"Lambda(
239+
Block(
240+
Constant(true),
241+
Block(new[] { s1, s2 },
242+
Constant(true),
243+
Constant(true)
244+
)
245+
)
246+
)"
247+
);
248+
181249
}
182250
}

0 commit comments

Comments
 (0)