Skip to content

Commit 59fc220

Browse files
committed
ToCsharpCode: format block inside expression in {}
It's not valid C# code, but neither was it valid before this change. This makes the code eaiser to read (IMHO), since the block scope is clearly visible.
1 parent 3835ddf commit 59fc220

File tree

3 files changed

+48
-10
lines changed

3 files changed

+48
-10
lines changed

src/FastExpressionCompiler/FastExpressionCompiler.cs

+16-8
Original file line numberDiff line numberDiff line change
@@ -6281,7 +6281,7 @@ internal static StringBuilder ToCSharpString(this Expression e, StringBuilder sb
62816281
{
62826282
var x = (ConstantExpression)e;
62836283
if (x.Value == null)
6284-
return x.Type != null
6284+
return x.Type != null && x.Type.IsValueType
62856285
? sb.Append("default(").Append(x.Type.ToCode(stripNamespace, printType)).Append(')')
62866286
: sb.Append("null");
62876287

@@ -6468,7 +6468,7 @@ internal static StringBuilder ToCSharpString(this Expression e, StringBuilder sb
64686468
sb.NewLineIdentCs(body, lineIdent, stripNamespace, printType, identSpaces, notRecognizedToCode);
64696469
else
64706470
{
6471-
sb.NewLine(lineIdent, identSpaces).Append('{');
6471+
sb.NewLineIdent(lineIdent).Append('{');
64726472

64736473
// Body handles `;` itself
64746474
if (body is BlockExpression bb)
@@ -6479,7 +6479,7 @@ internal static StringBuilder ToCSharpString(this Expression e, StringBuilder sb
64796479
if (isBodyExpression)
64806480
sb.AddSemicolonIfFits();
64816481
}
6482-
sb.NewLine(lineIdent, identSpaces).Append('}');
6482+
sb.NewLineIdent(lineIdent).Append('}');
64836483
}
64846484
return sb.Append(')');
64856485
}
@@ -6533,7 +6533,14 @@ internal static StringBuilder ToCSharpString(this Expression e, StringBuilder sb
65336533
}
65346534
case ExpressionType.Block:
65356535
{
6536-
return BlockToCSharpString((BlockExpression)e, sb, lineIdent, stripNamespace, printType, identSpaces, notRecognizedToCode: notRecognizedToCode);
6536+
if (enclosedIn == EnclosedIn.Block)
6537+
return BlockToCSharpString((BlockExpression)e, sb, lineIdent, stripNamespace, printType, identSpaces, notRecognizedToCode: notRecognizedToCode);
6538+
else
6539+
{
6540+
sb.Append('{');
6541+
BlockToCSharpString((BlockExpression)e, sb, lineIdent + identSpaces, stripNamespace, printType, identSpaces, notRecognizedToCode: notRecognizedToCode);
6542+
return sb.AddSemicolonIfFits().NewLineIdent(lineIdent).Append('}');
6543+
}
65376544
}
65386545
case ExpressionType.Loop:
65396546
{
@@ -6684,11 +6691,12 @@ void PrintPart(Expression part)
66846691
}
66856692
case ExpressionType.Default:
66866693
{
6687-
return e.Type == typeof(void) ? sb // `default(void)` does not make sense in the C#
6688-
: sb.Append("default(").Append(e.Type.ToCode(stripNamespace, printType)).Append(')');
6694+
return e.Type == typeof(void) ? sb : // `default(void)` does not make sense in the C#
6695+
!e.Type.IsValueType && !e.Type.IsGenericParameter ? sb.Append("null") :
6696+
sb.Append("default(").Append(e.Type.ToCode(stripNamespace, printType)).Append(')');
66896697
}
66906698
case ExpressionType.TypeIs:
6691-
case ExpressionType.TypeEqual:
6699+
case ExpressionType.TypeEqual: // TODO: type equal
66926700
{
66936701
var x = (TypeBinaryExpression)e;
66946702
sb.Append('(');
@@ -7598,4 +7606,4 @@ public static IReadOnlyList<PE> ToReadOnlyList(this IParameterProvider source)
75987606
public static IReadOnlyList<PE> ToReadOnlyList(this IReadOnlyList<PE> source) => source;
75997607
#endif
76007608
}
7601-
}
7609+
}

test/FastExpressionCompiler.UnitTests/FastExpressionCompiler.UnitTests.csproj

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
3-
<TargetFrameworks>net472;netcoreapp3.1</TargetFrameworks>
3+
<TargetFrameworks>net472;net6.0</TargetFrameworks>
4+
<LangVersion>11</LangVersion>
45
</PropertyGroup>
56

67
<ItemGroup>

test/FastExpressionCompiler.UnitTests/ToCSharpStringTests.cs

+30-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,35 @@ public void Outputs_closed_generic_type_constant_correctly()
3131
Assert.AreEqual(typeof(A<string>), f());
3232
}
3333

34+
[Test]
35+
public void Outputs_default_reference_type_is_just_null()
36+
{
37+
var cs = Default(typeof(string)).ToCSharpString();
38+
Assert.AreEqual("null;", cs);
39+
40+
cs = Default(typeof(System.Collections.Generic.List<string>)).ToCSharpString();
41+
Assert.AreEqual("null;", cs);
42+
}
43+
44+
[Test]
45+
public void Somehow_handles_block_in_expression()
46+
{
47+
// it's probably not possible to output compilable C# for expressions like this, but at least it can be easy to read
48+
var variable = Parameter(typeof(int), "variable");
49+
var cs = Add(Constant(1), Block(new [] { variable },
50+
Assign(variable, Constant(2)),
51+
variable
52+
)).ToCSharpString();
53+
Assert.AreEqual("""
54+
(1 + {
55+
int variable;
56+
variable = 2;
57+
variable;
58+
});
59+
""", cs);
60+
}
61+
62+
3463
class A<X> {}
3564
}
36-
}
65+
}

0 commit comments

Comments
 (0)