Skip to content

Implement support for throw expressions in expression trees#19

Merged
koenbeuk merged 2 commits intomainfrom
feat/throw-expressions
Apr 6, 2026
Merged

Implement support for throw expressions in expression trees#19
koenbeuk merged 2 commits intomainfrom
feat/throw-expressions

Conversation

@koenbeuk
Copy link
Copy Markdown
Collaborator

@koenbeuk koenbeuk commented Apr 4, 2026

Add support for throw expressions in expression trees, enabling their use in null-coalescing and other scenarios. Include tests to verify correct behavior and ensure compatibility with LINQ providers. Update related components to handle throw expressions appropriately.

Copilot AI review requested due to automatic review settings April 4, 2026 01:00
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 4, 2026

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds end-to-end support for C# throw expressions in ExpressiveSharp-generated expression trees, including emission, EF Core compatibility behavior, and test/docs updates.

Changes:

  • Added generator emission for IThrowOperation (including typed Expression.Throw(exception, typeof(T))) and updated block-body handling to allow throws.
  • Added an EF Core-facing transformer (ReplaceThrowWithDefault) and an EF configuration switch to preserve throws instead of replacing them.
  • Added/updated unit, generator snapshot, and integration tests plus documentation to cover throw-expression scenarios.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tests/ExpressiveSharp.Tests/Transformers/ReplaceThrowWithDefaultTests.cs Adds unit tests validating throw→default rewriting behavior.
tests/ExpressiveSharp.IntegrationTests/Scenarios/Store/Models/Order.cs Adds [Expressive] property using ?? throw as a real scenario.
tests/ExpressiveSharp.IntegrationTests/Scenarios/Common/Tests/ThrowExpressionTests.cs Adds scenario tests for SafeTag expansion behavior.
tests/ExpressiveSharp.IntegrationTests.ExpressionCompile/Tests/Common/ThrowExpressionTests.cs Wires the scenario tests into the ExpressionCompile runner.
tests/ExpressiveSharp.Generator.Tests/ExpressiveGenerator/ThrowExpressionTests.cs Adds generator tests for throw in coalesce/conditional/switch arm.
tests/ExpressiveSharp.Generator.Tests/ExpressiveGenerator/*.verified.txt Snapshot outputs for new throw-expression generator cases.
tests/ExpressiveSharp.Generator.Tests/ExpressiveGenerator/DiagnosticTests.cs Removes prior “throw is unsupported” diagnostic test.
tests/ExpressiveSharp.Generator.Tests/ExpressiveGenerator/BlockBodyTests.cs + verified Updates expectations: throw in block bodies is now emitted, not warned.
src/ExpressiveSharp/Transformers/ReplaceThrowWithDefault.cs Introduces the transformer used to remove throw nodes for provider compatibility.
src/ExpressiveSharp.Generator/Interpretation/ExpressiveInterpreter.BodyProcessors.cs Stops flagging IThrowOperation as unsupported in block bodies.
src/ExpressiveSharp.Generator/Emitter/ExpressionTreeEmitter.cs Implements throw emission and conversion special-casing for throw operands.
src/ExpressiveSharp.EntityFrameworkCore/.../ExpressiveOptionsExtension.cs Adds default throw-stripping behavior for EF Core, plus opt-out.
src/ExpressiveSharp.EntityFrameworkCore/Extensions/DbContextOptionsExtensions.cs Passes the new preserve-throws option into the EF extension.
src/ExpressiveSharp.EntityFrameworkCore/ExpressiveOptionsBuilder.cs Adds PreserveThrowExpressions() option for EF integration configuration.
docs/advanced/ioperation-mapping.md Documents IThrowOperation mapping and EF compatibility behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +14 to +21
Expression<Func<Order, string>> expr = o => o.SafeTag;
var expanded = (Expression<Func<Order, string>>)expr.ExpandExpressives();

// Compile and invoke directly — non-null Tag should return the value
var compiled = expanded.Compile();
var order = new Order { Tag = "RUSH" };
Assert.AreEqual("RUSH", compiled(order));
}
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These integration tests compile/invoke the expanded expression directly instead of executing it via Runner (like other scenario tests do). As a result, they don’t actually validate behavior across integration runners / LINQ providers and won’t catch translation-time issues.

Copilot uses AI. Check for mistakes.
Comment on lines +5 to +8
[TestClass]
public class ThrowExpressionTests : Scenarios.Common.Tests.ThrowExpressionTests
{
protected override IIntegrationTestRunner CreateRunner() => new ExpressionCompileTestRunner();
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This adds the scenario test to the ExpressionCompile runner, but there’s no corresponding derived test in ExpressiveSharp.IntegrationTests.EntityFrameworkCore (search shows no ThrowExpressionTests there). To validate provider compatibility as described in the PR, add the EF Core runner variant as well.

Copilot uses AI. Check for mistakes.
@koenbeuk koenbeuk merged commit eae33b5 into main Apr 6, 2026
5 of 7 checks passed
@koenbeuk koenbeuk deleted the feat/throw-expressions branch April 6, 2026 01:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants