[SourceGen] Don't emit INPC handlers for static type references in C# XAML expressions#35922
[SourceGen] Don't emit INPC handlers for static type references in C# XAML expressions#35922StephaneDelcroix wants to merge 1 commit into
Conversation
… XAML expressions Fixes #35900 The XAML C# expression source generator was extracting binding handlers for every MemberAccess chain in an expression, including chains rooted at static type names like 'Colors.Goldenrod', 'DateTime.Now' or 'Math.Max(...)'. Top-level handlers were filtered out when the root identifier wasn't a member of the x:DataType, but nested handlers in the chain were always kept. That produced invalid getter lambdas such as 'static __source => __source.Colors' which broke compilation with 'CS1061: <DataType> does not contain a definition for Colors'. Per the XamlCSharpExpressions spec step 4 (Static Invocation), an identifier that doesn't resolve as a BindingContext member, code-behind member, or local lambda parameter must fall through to a static type reference - it must not subscribe to a non-existent property on the DataType. The fix tightens the handler filter in ExpressionAnalyzer.Analyze so a nested handler is kept only when the root identifier of its parent expression (after the source parameter prefix) is an actual member of the DataType. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 35922Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 35922" |
|
NEEDS_DISCUSSION (confidence: high) — multi-model review (2 LGTM, 2 ND); code unanimously judged correct, 0 actionable findings. The source-gen fix is correct and minimal: it tightens the handler filter so a nested member-access handler is kept only when its chain-root identifier is a real property/field of the The only reason this isn't a clean LGTM: a required CI leg ( Multi-model review (gpt-5.5 · opus-4.8 · opus-4.6 · gemini-3.1-pro). Comments only — not a formal approval. |
Note
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!
Description of Change
Fixes #35900.
The XAML C# expression source generator was emitting INPC subscription handlers for every
MemberAccesschain in an expression, including chains rooted at a static type reachable viaglobal usingsuch asColors.Goldenrod,DateTime.Now, orMath.Max(...).The existing filter in
ExpressionAnalyzer.Analyzecorrectly dropped the top-level handler when the root identifier (Colors,DateTime,Math) was not a member of thex:DataType, but it always kept the nested handlers for the same chain. That produced invalid getter lambdas like:…which then failed compilation with
CS1061: 'MainViewModel' does not contain a definition for 'Colors'(and similar forDateTime/Math). This is step 4 of the XamlCSharpExpressions name-resolution spec: an identifier that doesn't resolve as aBindingContextmember, code-behind member, or lambda parameter must fall through to a static type reference — it must never produce an INPC subscription against a non-existent member of the DataType.The fix tightens the handler filter so a nested handler is kept only when the root identifier of its parent expression (after the
__source.prefix) is an actual member of the DataType. The getter-body rewriter (TransformRootIdentifiers) already handled the static-type case correctly, so the lambda body — e.g.__source => (__source.IsVip ? Colors.Goldenrod : Colors.Gray, true)— compiles unchanged once the handler array is clean.Issues Fixed
Fixes #35900
Tests
Added a parameterized test in
CSharpExpressionDiagnosticsTeststhat exercises all four scenarios from the issue report:TextColor="{IsVip ? Colors.Goldenrod : Colors.Gray}"Text="{$'Now: {DateTime.Now:t}'}"Text="{$'Max = {Math.Max(Price, Quantity):F2}'}"Text="{$'{Name} - {DateTime.Now:d}'}"The test asserts the generated
.xsg.cscontains no__source.Colors/__source.DateTime/__source.Mathhandler subscriptions and that the resulting compilation has no errors. All 205 existingSourceGen.UnitTestscontinue to pass.