Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions src/ExpressiveSharp.Generator/Emitter/ExpressionTreeEmitter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2107,8 +2107,12 @@ private string EmitSwitchStatement(ISwitchOperation switchStmt)
return currentVar;
}

/// <summary>Returns the single return operation in a case body, or null if the shape isn't supported.</summary>
private static IReturnOperation? FindCaseReturn(ISwitchCaseOperation switchCase)
/// <summary>
/// Returns the case's return operation, inlining any leading local declarations (their
/// initializer expressions are mapped so the returned value embeds them and evaluation stays
/// inside the arm); null if the shape isn't supported.
/// </summary>
private IReturnOperation? FindCaseReturn(ISwitchCaseOperation switchCase)
{
foreach (var op in switchCase.Body)
{
Expand All @@ -2123,6 +2127,10 @@ private string EmitSwitchStatement(ISwitchOperation switchStmt)
{
return innerRet;
}
if (inner is IVariableDeclarationGroupOperation declGroup && TryInlineCaseLocals(declGroup))
{
continue;
}
return null;
}
return null;
Expand All @@ -2133,6 +2141,24 @@ private string EmitSwitchStatement(ISwitchOperation switchStmt)
return null;
}

private bool TryInlineCaseLocals(IVariableDeclarationGroupOperation declGroup)
{
foreach (var declaration in declGroup.Declarations)
{
foreach (var declarator in declaration.Declarators)
{
if (declarator.Initializer is null)
{
return false;
}

_localToVar[declarator.Symbol] = EmitOperation(declarator.Initializer.Value);
}
}

return true;
}

private string EmitSwitchExpression(ISwitchExpressionOperation switchExpr)
{
var governingVar = EmitOperation(switchExpr.Value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,4 +389,36 @@ public int Foo()

return Verifier.Verify(result.GeneratedTrees[0].ToString());
}

[TestMethod]
public void SwitchCase_LocalBeforeReturn_IsSupported()
{
var compilation = CreateCompilation(
"""
namespace Foo {
class C {
[Expressive(AllowBlockBody = true)]
public static string Label(int x)
{
switch (x)
{
case 1:
{
var y = "one";
return y;
}
default:
return "other";
}
}
}
}
""");

var result = RunExpressiveGenerator(compilation);

Assert.IsFalse(result.Diagnostics.Any(d => d.Id == "EXP0008"),
"A case block with a local before the return should be emitted, not degraded to a " +
"default value via EXP0008. Diagnostics: " + string.Join("; ", result.Diagnostics));
}
}
Loading