Skip to content

Fix XamlC to respect ObsoleteAttribute message and isError parameter#32946

Merged
StephaneDelcroix merged 14 commits intonet11.0from
fix/23961-obsolete-attribute-handling
Mar 31, 2026
Merged

Fix XamlC to respect ObsoleteAttribute message and isError parameter#32946
StephaneDelcroix merged 14 commits intonet11.0from
fix/23961-obsolete-attribute-handling

Conversation

@StephaneDelcroix
Copy link
Copy Markdown
Contributor

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

Fixes #23961

This PR fixes XamlC to properly handle the ObsoleteAttribute by:

  1. Extracting and displaying the custom message from [Obsolete("message")] instead of a generic deprecation message
  2. Respecting the isError parameter - when [Obsolete("message", error: true)] is used, XamlC now emits an error (XC0619) instead of a warning (XC0618)
  3. Adding obsolete type detection for classes marked with [Obsolete] when used in XAML

Changes

  • ErrorMessages.resx: Updated ObsoleteProperty message format to include the custom message: "{0}" is deprecated: {1}
  • BuildException.cs: Added XC0619 (ObsoletePropertyError) for error cases when isError=true
  • SetPropertiesVisitor.cs:
    • Added TryGetObsoleteAttribute() helper to extract message and isError from the attribute
    • Added LogObsoleteWarningOrError() helper that logs the appropriate warning or error based on the attribute
    • Updated property/field obsolete checking to use these helpers
  • CreateObjectVisitor.cs: Added obsolete type detection when XAML elements are created

Before

XamlC warning XC0618: Property, Property setter or BindableProperty "MyProperty" is deprecated.

After

XamlC warning XC0618: "MyProperty" is deprecated: Use NewProperty instead.
XamlC error XC0619: "MyProperty" is obsolete: This property will be removed in the next version.

Testing

  • Added Maui23961.xaml / .cs - tests for warnings with error: false
  • Added Maui23961Error.rt.xaml / .cs - tests for errors with error: true
  • All 1780+ existing Xaml.UnitTests pass
  • Samples build successfully

Copilot AI review requested due to automatic review settings December 1, 2025 20:11
@StephaneDelcroix StephaneDelcroix added the area-xaml XAML, CSS, Triggers, Behaviors label Dec 1, 2025
@StephaneDelcroix StephaneDelcroix added this to the .NET 10.0 SR3 milestone Dec 1, 2025
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 enhances XamlC to properly handle the ObsoleteAttribute by extracting and displaying custom messages and respecting the isError parameter to differentiate between warnings (XC0618) and errors (XC0619).

  • Adds helper methods TryGetObsoleteAttribute() and LogObsoleteWarningOrError() to extract obsolete attribute information and log appropriate diagnostics
  • Updates error message resources to include custom messages from ObsoleteAttribute
  • Extends obsolete checking to types in addition to properties, fields, and bindable properties

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/Controls/tests/Xaml.UnitTests/Issues/Maui23961Error.xaml.cs Test code for obsolete attributes with error: true parameter
src/Controls/tests/Xaml.UnitTests/Issues/Maui23961Error.rt.xaml XAML test file for obsolete error cases
src/Controls/tests/Xaml.UnitTests/Issues/Maui23961.xaml.cs Test code for obsolete attributes with error: false parameter (warnings)
src/Controls/tests/Xaml.UnitTests/Issues/Maui23961.xaml XAML test file for obsolete warning cases
src/Controls/tests/Xaml.UnitTests/Controls.Xaml.UnitTests.csproj Adds XC0619 to WarningsNotAsErrors to allow compilation of test files with obsolete errors
src/Controls/src/Build.Tasks/SetPropertiesVisitor.cs Implements obsolete attribute extraction logic and refactors obsolete checking to use new helper methods
src/Controls/src/Build.Tasks/ErrorMessages.resx Updates error messages for obsolete warnings and errors to include custom messages
src/Controls/src/Build.Tasks/CreateObjectVisitor.cs Adds obsolete type checking when XAML elements are created
src/Controls/src/Build.Tasks/BuildException.cs Adds XC0619 error code for obsolete errors

else
{
// Runtime doesn't check for obsolete at compile time
var page = new Maui23961Error(inflator);
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

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

The constructor call new Maui23961Error(inflator) will fail because the class only has a parameterless constructor public Maui23961Error() => InitializeComponent(); (line 14). This parameterized constructor pattern with XamlInflator is not defined for this class.

Looking at other test files, the XamlInflator parameter constructor is typically auto-generated for regular XAML files (not .rt.xaml). However, this is a .rt.xaml file (runtime-only), which means the auto-generated XamlInflator constructor won't exist.

The test logic on lines 46-56 appears to have incorrect branching. For the XamlInflator.SourceGen case, it correctly recognizes that .rt.xaml files aren't processed, but the else block (line 51-56) attempts to use a non-existent constructor.

Consider revising the test to either:

  1. Use the parameterless constructor: var page = new Maui23961Error();
  2. Skip the runtime test path entirely for .rt.xaml files since they're meant for runtime-only processing
Suggested change
var page = new Maui23961Error(inflator);
var page = new Maui23961Error();

Copilot uses AI. Check for mistakes.
</data>
<data name="ObsoleteProperty" xml:space="preserve">
<value>Property, Property setter or BindableProperty "{0}" is deprecated.</value>
<value>"{0}" is deprecated: {1}</value>
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

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

The error message uses "is obsolete" while the warning message uses "is deprecated". For consistency with C# compiler behavior, both should use the same terminology. The C# compiler uses "is obsolete" for both warnings (CS0618) and errors (CS0619).

Consider changing the warning message from "{0}" is deprecated: {1} to "{0}" is obsolete: {1} to match standard C# compiler terminology and maintain consistency with the error message.

Suggested change
<value>"{0}" is deprecated: {1}</value>
<value>"{0}" is obsolete: {1}</value>

Copilot uses AI. Check for mistakes.
}

if ( dataTypeNode is ElementNode enode
if (dataTypeNode is ElementNode enode
Copy link

Copilot AI Dec 1, 2025

Choose a reason for hiding this comment

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

[nitpick] This whitespace change (removing spaces after if) is unrelated to the PR's purpose of fixing ObsoleteAttribute handling. The PR should focus only on changes directly related to the obsolete attribute functionality to keep the changes minimal and reviewable.

Consider reverting this whitespace change.

Suggested change
if (dataTypeNode is ElementNode enode
if ( dataTypeNode is ElementNode enode

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Feb 27, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 32946

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 32946"

@StephaneDelcroix StephaneDelcroix force-pushed the fix/23961-obsolete-attribute-handling branch 4 times, most recently from e44fb8a to 65f091e Compare March 3, 2026 16:50
@StephaneDelcroix
Copy link
Copy Markdown
Contributor Author

/azp run maui-pr-devicetests, maui-pr-uitests

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 2 pipeline(s).

@StephaneDelcroix StephaneDelcroix force-pushed the fix/23961-obsolete-attribute-handling branch from fe4328a to 2578ec0 Compare March 6, 2026 12:49
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It appears copilot messed up indentation in this file.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It appears copilot messed up indentation in this file.

@MauiBot
Copy link
Copy Markdown
Collaborator

MauiBot commented Mar 23, 2026

⚠️ Merge Conflict Detected — This PR has merge conflicts with its target branch. Please rebase onto the target branch and resolve the conflicts.

StephaneDelcroix and others added 13 commits March 30, 2026 13:35
Fixes #23961

- Extract and display the custom message from ObsoleteAttribute
- Respect the isError parameter: when true, emit XC0619 error instead of XC0618 warning
- Add obsolete type detection for classes used in XAML
- Add XC0619 (ObsoletePropertyError) for error cases
- Update message format to include the attribute's message text
- Add unit tests for both warning and error scenarios
Samples use obsolete types like ListView, ViewCell, etc. which now
trigger XC0618 warnings. Add these codes to WarningsNotAsErrors to
prevent build failures when TreatWarningsAsErrors is enabled.
The TestResultPage.xaml uses Frame which is obsolete.
The ManualTests use obsolete types like TextCell in CollectionView tests.
The test now receives AggregateException when treatWarningsAsErrors is
true because both the obsolete Compatibility.StackLayout type and the
binding without DataType produce errors. Updated test to use Assert.Catch
and verify the expected XC0022 error is present.
- LogObsoleteWarningOrError: call LogError directly when isError=true,
  bypassing LogWarningOrError which ignores error semantics
- Maui23961Error test: assert MockCompiler.Compile throws for [Obsolete(error: true)]
- Maui23989 test: document AggregateException from multiple warnings-as-errors
- HostApp csproj: preserve $(WarningsNotAsErrors) to not clobber XC0618 suppression

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Xaml.UnitTests migrated from NUnit to xUnit on net11.0. Convert
Maui23961.xaml.cs and Maui23961Error.xaml.cs to use xUnit patterns:
[TestFixture] → [Collection], [Test]+[Values] → [Theory]+[XamlInflatorData],
[SetUp]/[TearDown] → constructor/IDisposable, Assert.That → Assert.NotNull.
Also revert Maui23989.xaml.cs to net11.0 version (had NUnit remnants).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add missing Maui23961ObsoleteClass2 type referenced in Maui23961.xaml
- Fix Maui23961Error test to use parameterless ctor (rt.xaml has no XamlInflator ctor)
- Add comments to WarningsNotAsErrors entries clarifying XC0619 behavior

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Maui23961Error.xaml.cs: Use Assert.ThrowsAny<Exception> instead of
  Assert.Throws<Exception> — multiple [Obsolete(error:true)] members
  produce an AggregateException, not a bare Exception. ThrowsAny handles
  both BuildException (single error) and AggregateException (multiple).

- CreateObjectVisitor.cs: Guard LogObsoleteWarningOrError behind
  'typedef != null' check to prevent NullReferenceException when a type
  reference cannot be resolved (ResolveCached returns null in that case).

- Add XC0619 explanatory comment to 5 remaining project files
  (TestCases.HostApp, Essentials/samples, ProfiledAot, DeviceTests.Runners,
  ManualTests) for consistency with the other 2 files already commented.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Guard propertySetter.CustomAttributes against NRE when SetMethod is null
  in Set(): CanSet() already gates this path, but the guard makes Set() safe
  to call defensively if that invariant ever changes.
- Document that XC0619 intentionally bypasses <NoWarn>, matching C# CS0619
  behavior: obsolete-as-error cannot be suppressed, users must remove usage.
- Document dual obsolete check: property declaration and setter are each
  checked separately, so both carrying [Obsolete] emits two diagnostics
  (matching C# compiler behavior).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The PR's new ObsoleteAttribute handling in XamlC now correctly emits
XC0618 when XAML uses deprecated types. Maui23989.xaml was using
Compatibility.StackLayout which carries [Obsolete], causing XC0618 to
be emitted alongside XC0022. With treatWarningsAsErrors:true, both
errors wrapped in AggregateException instead of the expected single
BuildException, failing the test.

Replace <cmp:StackLayout> with the standard <StackLayout> so XamlC
only sees the expected XC0022 warning in the test scenario.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Change XC0618 message from 'deprecated' to 'obsolete' to match C# CS0618
- Add MockCompiler.Compile overload that exposes logged warnings
- Assert ObsoleteWarningIncludesMessage verifies custom message text is present
- Assert ObsoleteErrorProducesCompilationError verifies XC0619 code in exception

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… number

- Add StringComparison.Ordinal to string.Contains and Assert.Contains calls
  to satisfy CA1307 analyzer rule
- Update Maui23989 expected error line from 12 to 11 after removing the
  cmp:StackLayout namespace prefix line from the XAML

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@StephaneDelcroix StephaneDelcroix force-pushed the fix/23961-obsolete-attribute-handling branch from a57ab80 to a17d19a Compare March 30, 2026 12:13
@StephaneDelcroix
Copy link
Copy Markdown
Contributor Author

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 3 pipeline(s).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-project-automation github-project-automation bot moved this from Todo to Approved in MAUI SDK Ongoing Mar 31, 2026
@StephaneDelcroix StephaneDelcroix merged commit fc266e3 into net11.0 Mar 31, 2026
31 of 36 checks passed
@StephaneDelcroix StephaneDelcroix deleted the fix/23961-obsolete-attribute-handling branch March 31, 2026 20:00
@github-project-automation github-project-automation bot moved this from Approved to Done in MAUI SDK Ongoing Mar 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-xaml XAML, CSS, Triggers, Behaviors

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

XamlC ignores isError option in ObsoleteAttribute

5 participants