Skip to content

Fix crash in LinqEnumerableCodeFixProvider with conditional access expressions (#216)#240

Open
Copilot wants to merge 3 commits into
masterfrom
copilot/determine-roslyn-or-analyzer-bug
Open

Fix crash in LinqEnumerableCodeFixProvider with conditional access expressions (#216)#240
Copilot wants to merge 3 commits into
masterfrom
copilot/determine-roslyn-or-analyzer-bug

Conversation

Copilot AI commented May 26, 2026

Copy link
Copy Markdown

Summary

Fixes #216 - VS crash when applying WTG3013 code fix on expressions using conditional access (?.).

Root Cause Analysis

The crash is a bug in Roslyn (specifically in SyntaxFactory.FindConditionalAccessNodeForBinding), but triggered by the analyzer's code fix producing a tree that Roslyn's simplifier cannot handle.

When LinqEnumerableCodeFixProvider fixes a .Concat() call that's part of a conditional access chain like:

other.GetItems()?.Where(x => x > 0).Concat(new[] { 42 }).ToArray()

The code fix wraps the receiver expression (.Where(x => x > 0)) in ParenthesizedExpression with Simplifier.Annotation. This disconnects the MemberBindingExpression (.Where) from its parent ConditionalAccessExpression. When Roslyn's simplifier then tries to evaluate whether the parentheses can be removed via speculative semantic analysis, it crashes with a NullReferenceException.

Fix

Added a WrapExpressionIfNeeded helper that skips parenthesization when the expression is an InvocationExpression. Invocation expressions never need parenthesization regardless of their receiver, as they already have clear binding. This avoids the issue with conditional access chains while also being a simpler and faster check.

Changes

  • Added WrapExpressionIfNeeded helper that skips wrapping for InvocationExpression nodes
  • Applied the same fix to both FixConcatWithAppendMethod and FixConcatWithPrependMethod
  • Added a ConditionalAccess test case that reproduces the crash

…pressions

When the code fix wraps an expression containing a MemberBindingExpression
(from conditional access ?.) in parentheses with Simplifier.Annotation,
Roslyn's speculative semantic model crashes with NullReferenceException
in FindConditionalAccessNodeForBinding.

The fix skips parenthesization when the expression contains a
MemberBindingExpression, which avoids triggering the Roslyn bug.

Fixes #216

Agent-Logs-Url: https://github.com/WiseTechGlobal/WTG.Analyzers/sessions/d974a4ba-43c4-4b13-acca-e9ccb83f1f8f

Co-authored-by: brian-reichle <18721383+brian-reichle@users.noreply.github.com>
Comment thread src/WTG.Analyzers/Analyzers/LinqEnumerable/LinqEnumerableCodeFixProvider.cs Outdated
Replace ContainsMemberBinding descendant traversal with a simple
IsKind(SyntaxKind.InvocationExpression) check, since invocation
expressions never need parenthesization regardless of their receiver.

Agent-Logs-Url: https://github.com/WiseTechGlobal/WTG.Analyzers/sessions/fc763f58-f56a-4811-a94b-2fe440b3eb00

Co-authored-by: brian-reichle <18721383+brian-reichle@users.noreply.github.com>
Comment thread src/WTG.Analyzers/Analyzers/LinqEnumerable/LinqEnumerableCodeFixProvider.cs Outdated
Copilot AI requested a review from brian-reichle May 26, 2026 06:02
@brian-reichle brian-reichle marked this pull request as ready for review May 26, 2026 06:51
@brian-reichle brian-reichle requested a review from yaakov-h as a code owner May 26, 2026 06:51
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.

VS17.8.0 crash in LinqEnumerableCodeFixProvider

2 participants