Skip to content

Commit

Permalink
ToCsharpCode: format block inside expression in {}
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
exyi committed Dec 29, 2022
1 parent 3835ddf commit 57ff039
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 11 deletions.
24 changes: 16 additions & 8 deletions src/FastExpressionCompiler/FastExpressionCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6281,7 +6281,7 @@ internal static StringBuilder ToCSharpString(this Expression e, StringBuilder sb
{
var x = (ConstantExpression)e;
if (x.Value == null)
return x.Type != null
return x.Type != null && x.Type.IsValueType
? sb.Append("default(").Append(x.Type.ToCode(stripNamespace, printType)).Append(')')
: sb.Append("null");

Expand Down Expand Up @@ -6468,7 +6468,7 @@ internal static StringBuilder ToCSharpString(this Expression e, StringBuilder sb
sb.NewLineIdentCs(body, lineIdent, stripNamespace, printType, identSpaces, notRecognizedToCode);
else
{
sb.NewLine(lineIdent, identSpaces).Append('{');
sb.NewLineIdent(lineIdent).Append('{');

// Body handles `;` itself
if (body is BlockExpression bb)
Expand All @@ -6479,7 +6479,7 @@ internal static StringBuilder ToCSharpString(this Expression e, StringBuilder sb
if (isBodyExpression)
sb.AddSemicolonIfFits();
}
sb.NewLine(lineIdent, identSpaces).Append('}');
sb.NewLineIdent(lineIdent).Append('}');
}
return sb.Append(')');
}
Expand Down Expand Up @@ -6533,7 +6533,14 @@ internal static StringBuilder ToCSharpString(this Expression e, StringBuilder sb
}
case ExpressionType.Block:
{
return BlockToCSharpString((BlockExpression)e, sb, lineIdent, stripNamespace, printType, identSpaces, notRecognizedToCode: notRecognizedToCode);
if (enclosedIn == EnclosedIn.Block)
return BlockToCSharpString((BlockExpression)e, sb, lineIdent, stripNamespace, printType, identSpaces, notRecognizedToCode: notRecognizedToCode);
else
{
sb.Append('{');
BlockToCSharpString((BlockExpression)e, sb, lineIdent + identSpaces, stripNamespace, printType, identSpaces, notRecognizedToCode: notRecognizedToCode);
return sb.AddSemicolonIfFits().NewLineIdent(lineIdent).Append('}');
}
}
case ExpressionType.Loop:
{
Expand Down Expand Up @@ -6684,11 +6691,12 @@ void PrintPart(Expression part)
}
case ExpressionType.Default:
{
return e.Type == typeof(void) ? sb // `default(void)` does not make sense in the C#
: sb.Append("default(").Append(e.Type.ToCode(stripNamespace, printType)).Append(')');
return e.Type == typeof(void) ? sb : // `default(void)` does not make sense in the C#
!e.Type.IsValueType && !e.Type.IsGenericParameter ? sb.Append("null") :
sb.Append("default(").Append(e.Type.ToCode(stripNamespace, printType)).Append(')');
}
case ExpressionType.TypeIs:
case ExpressionType.TypeEqual:
case ExpressionType.TypeEqual: // TODO: type equal
{
var x = (TypeBinaryExpression)e;
sb.Append('(');
Expand Down Expand Up @@ -7598,4 +7606,4 @@ public static IReadOnlyList<PE> ToReadOnlyList(this IParameterProvider source)
public static IReadOnlyList<PE> ToReadOnlyList(this IReadOnlyList<PE> source) => source;
#endif
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net472;net6.0</TargetFrameworks>
<TargetFrameworks>net6.0</TargetFrameworks>
</PropertyGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net472;netcoreapp3.1</TargetFrameworks>
<TargetFrameworks>net472;net6.0</TargetFrameworks>
<LangVersion>11</LangVersion>
</PropertyGroup>

<ItemGroup>
Expand Down
31 changes: 30 additions & 1 deletion test/FastExpressionCompiler.UnitTests/ToCSharpStringTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,35 @@ public void Outputs_closed_generic_type_constant_correctly()
Assert.AreEqual(typeof(A<string>), f());
}

[Test]
public void Outputs_default_reference_type_is_just_null()
{
var cs = Default(typeof(string)).ToCSharpString();
Assert.AreEqual("null;", cs);

cs = Default(typeof(System.Collections.Generic.List<string>)).ToCSharpString();
Assert.AreEqual("null;", cs);
}

[Test]
public void Somehow_handles_block_in_expression()
{
// it's probably not possible to output compilable C# for expressions like this, but at least it can be easy to read
var variable = Parameter(typeof(int), "variable");
var cs = Add(Constant(1), Block(new [] { variable },
Assign(variable, Constant(2)),
variable
)).ToCSharpString();
Assert.AreEqual("""
(1 + {
int variable;
variable = 2;
variable;
});
""", cs);
}


class A<X> {}
}
}
}

0 comments on commit 57ff039

Please sign in to comment.