Skip to content

Add [GeneratedCustomPropertyProvider] generator and analyzers#2160

Open
Sergio0694 wants to merge 95 commits intostaging/3.0from
user/sergiopedri/bindable-custom-property2
Open

Add [GeneratedCustomPropertyProvider] generator and analyzers#2160
Sergio0694 wants to merge 95 commits intostaging/3.0from
user/sergiopedri/bindable-custom-property2

Conversation

@Sergio0694
Copy link
Member

@Sergio0694 Sergio0694 commented Dec 17, 2025

Title. This doesn't need any special casing at all in CsWinRT 3.0, thanks to 'cswinrtgen'.

Copy link

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.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@Sergio0694 Sergio0694 requested a review from Copilot December 17, 2025 19:16
Copy link

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

Copilot reviewed 38 out of 38 changed files in this pull request and generated 8 comments.


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

@Sergio0694 Sergio0694 force-pushed the user/sergiopedri/bindable-custom-property2 branch 2 times, most recently from 03b0d31 to 4aea9d1 Compare February 15, 2026 05:02
@Sergio0694 Sergio0694 force-pushed the user/sergiopedri/bindable-custom-property2 branch 4 times, most recently from 232eb11 to a48ddc5 Compare February 24, 2026 06:50
@Sergio0694 Sergio0694 force-pushed the user/sergiopedri/bindable-custom-property2 branch 3 times, most recently from 0027c3a to 1ee568d Compare March 11, 2026 17:36
@Sergio0694 Sergio0694 marked this pull request as ready for review March 12, 2026 02:19
@Sergio0694 Sergio0694 force-pushed the user/sergiopedri/bindable-custom-property2 branch from 9fc55bc to ae9d7d5 Compare March 12, 2026 23:31
Introduces the GeneratedCustomPropertyProviderAttribute for marking bindable properties in XAML scenarios. Supports specifying property names and indexer types for binding code generation via ICustomPropertyProvider interfaces.
Introduces a new SyntaxExtensions class providing extension methods for SyntaxNode and SyntaxTokenList. These methods allow checking if a node or token list matches any of the specified SyntaxKind values, improving code readability and reuse in Roslyn-based source generators.
Introduces IncrementalGeneratorInitializationContextExtensions with a method to combine attribute-based syntax analysis and analyzer config options. Also adds a struct to encapsulate both GeneratorAttributeSyntaxContext and AnalyzerConfigOptions for use in source generators.
Introduces extension methods to determine if a member declaration is partial and if it resides within a hierarchy of partial type declarations. This aids in analyzing and generating code for partial types in the source generator.
Introduces ObjectPool<T> to efficiently manage reusable objects with a fixed pool size. This class is ported from Roslyn and provides thread-safe allocation and freeing of objects to reduce allocations and improve performance.
Introduces PooledArrayBuilder<T>, a ref struct for efficiently building sequences of values using pooled buffers. This utility provides methods for adding, inserting, and enumerating items, and is ported from ComputeSharp to support high-performance source generation scenarios.
Introduces IndentedTextWriter, a helper for writing indented text with pooled buffers, ported from ComputeSharp. Changes PooledArrayBuilder<T> from a ref struct to a struct to support usage in IndentedTextWriter and improve compatibility.
The code responsible for generating bindable custom properties in CustomPropertyProviderGenerator has been commented out, likely to temporarily disable this feature or for refactoring purposes.
Introduces IsDefaultOrEmpty and Length properties to the EquatableArray<T> struct for easier array state inspection. Also replaces <sinheritdoc/> with <inheritdoc/> in documentation comments for improved clarity and consistency.
Introduces ITypeSymbolExtensions with methods to retrieve and append fully qualified metadata names for ITypeSymbol instances. These utilities facilitate working with Roslyn symbols in source generation scenarios.
Sergio0694 and others added 12 commits March 13, 2026 11:17
Select the ICustomPropertyProvider metadata name based on useWindowsUIXamlProjections and perform a single type lookup against the compilation. Replace the previous dual-check with a single retrieval (customPropertyProviderType) and return early if missing. Add a guard to return when the annotated type already implements or inherits any members for ICustomPropertyProvider (HasAnyImplementedMembersForInterface) to avoid generating conflicting implementations; diagnostics are handled elsewhere. Also add an extra cancellation-token check.

Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com>
Introduce GeneratedCustomPropertyProviderExistingMemberImplementationAnalyzer to detect when [GeneratedCustomPropertyProvider] is applied to a type that already has or inherits implementations for ICustomPropertyProvider members (checks both Windows.UI.Xaml and Microsoft.UI.Xaml). Add a new diagnostic descriptor (CSWINRT2003) describing the error and update AnalyzerReleases.Shipped.md to include the new rule. This prevents the generator from producing duplicate member implementations on annotated types.

Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com>
Add Test_GeneratedCustomPropertyProviderExistingMemberImplementationAnalyzer.cs containing unit tests for GeneratedCustomPropertyProviderExistingMemberImplementationAnalyzer. Tests cover class/struct declarations, cases with no interface or no members (no warnings), explicit and implicit ICustomPropertyProvider implementations (complete and incomplete), and inherited implementations; they verify CSWINRT2003 warnings are produced where appropriate.

Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com>
Add an optional ReadOnlySpan<DiagnosticResult> expectedDiagnostics parameter to CSharpAnalyzerTest.VerifyAnalyzerAsync and forward its contents into TestState.ExpectedDiagnostics so tests can supply expected diagnostics programmatically. Update tests to import Microsoft.CodeAnalysis.Testing, add a VerifyCS alias, and pass explicit expected diagnostic arrays for the analyzer cases. Also simplify one parameterized test to a single-class case and adjust using/imports accordingly.
Add comprehensive .editorconfig files for Authoring/WinRT.SourceGenerator2 and Tests/SourceGenerator2Test to enforce consistent C# formatting and .NET coding conventions (indentation, naming, spacing, wrapping, and other rules). Also normalize file endings/EOF presence in several source files (GeneratedCustomPropertyProviderExistingMemberImplementationAnalyzer.cs, IncrementalGeneratorInitializationContextExtensions.cs, IncrementalValuesProviderExtensions.cs, CustomPropertyInfo.cs) — these are non-functional formatting changes to ensure consistent repository style.
Fix three missing semicolons in generated 'using' directives (CodeDom.Compiler,
Diagnostics, Diagnostics.CodeAnalysis) and fix the switch expression closing
brace to emit '};' instead of '}' by replacing WriteBlock with manual
indent management.

Also update all corresponding expected outputs in the unit tests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The generator was unconditionally emitting property access code in
GetValue/SetValue/GetIndexedValue/SetIndexedValue regardless of whether
the property supported that operation. This caused CS0200 errors when
a read-only property's generated SetValue tried to assign to it.

Now, when CanRead is false, GetValue/GetIndexedValue emit
'throw new NotSupportedException()' instead of the property/indexer
access. Likewise for CanWrite being false with SetValue/SetIndexedValue.

Updated expected outputs in ReadOnlyProperty, WriteOnlyProperty and
ReadOnlyIndexer unit tests.

Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com>
…mbers

Call WriteGeneratedAttributes with includeNonUserCodeAttributes: false on
each of the four generated explicit interface implementations (Type,
GetCustomProperty, GetIndexedProperty, GetStringRepresentation). This
annotates them with [GeneratedCode] so the analyzer can distinguish
generated implementations from user-authored ones.

Updated all expected outputs in unit tests accordingly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The analyzer was incorrectly firing for types using
[GeneratedCustomPropertyProvider] because it detected the interface
member implementations produced by the generator itself. Now
HasAnyImplementedMembersForInterface accepts an optional
GeneratedCodeAttribute type and generator name: implementations
annotated with [GeneratedCode("CustomPropertyProviderGenerator", ...)]
are excluded from the check.

Also removed the unnecessary explicit ': ICustomPropertyProvider' from
TestCustomPropertyProvider in the functional tests (the generator adds
it via the partial class).

Added two new analyzer tests:
- TypeWithGeneratedExplicitInterfaceImplementation_DoesNotWarn
- TypeWithMixedGeneratedAndUserImplementation_Warns

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Split the monolithic HasAnyImplementedMembersForInterface into:
- EnumerateImplementedMembersForInterface: enumerates all implemented members
- HasAnyImplementedMembersForInterface: simplified to delegate to the enumerator
- AreAllImplementedByGenerator: checks if all symbols in a sequence are generated

Update the analyzer to use AreAllImplementedByGenerator, so it no longer warns
when all interface member implementations are produced by our generator.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Improve detection of generated ICustomPropertyProvider implementations and simplify attribute handling. Make GeneratedCodeAttribute resolution non-nullable and add HasNonGeneratedImplementedMembers helper to centralize logic for checking implemented interface members that were not emitted by this generator. Simplify attribute checks in ISymbolExtensions by using TryGetAttributeWithType and validating the constructor argument, and replace manual loop with LINQ.Any in ITypeSymbolExtensions (added System.Linq). Removes duplicate/nullable checks and streamlines the analyzer to avoid false diagnostics for generator-emitted members.
@Sergio0694 Sergio0694 force-pushed the user/sergiopedri/bindable-custom-property2 branch from 3f6cabb to 1a8e582 Compare March 13, 2026 18:17
Sergio0694 and others added 3 commits March 13, 2026 14:11
Add 5 new diagnostic descriptors (CSWINRT2004-CSWINRT2008) for validating
[GeneratedCustomPropertyProvider] attribute arguments:
- CSWINRT2004: Null property name
- CSWINRT2005: Null indexer type
- CSWINRT2006: Property name not found
- CSWINRT2007: Indexer type not found
- CSWINRT2008: Static indexer not supported

Also update AnalyzerReleases.Unshipped.md with the new rules.

Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com>
Add GeneratedCustomPropertyProviderAttributeArgumentAnalyzer that validates
the explicit property names and indexer types passed to the attribute
constructor, replicating the filtering logic from the generator:

- Reports CSWINRT2004 for null property names in the array
- Reports CSWINRT2005 for null indexer types in the array
- Reports CSWINRT2006 when a property name doesn't match any accessible
  public, non-override, non-indexer property on the type
- Reports CSWINRT2007 when an indexer type doesn't match any accessible
  public, non-override, non-static, single-parameter indexer
- Reports CSWINRT2008 when the matching indexer is static

Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com>
Add comprehensive test coverage for
GeneratedCustomPropertyProviderAttributeArgumentAnalyzer with 20 test
cases covering all 5 diagnostics:

No-warning cases (10):
- Default constructor, empty arrays, valid names/types
- Inherited members, multiple valid names, overridden properties

CSWINRT2004 - Null property name (2):
- Single null, null among valid names

CSWINRT2005 - Null indexer type (2):
- Single null, null among valid types

CSWINRT2006 - Property name not found (3):
- Missing name, private property, multiple missing names

CSWINRT2007 - Indexer type not found (4):
- Wrong type, no indexer, multi-parameter indexer, multiple missing

Combined (1):
- Mixed invalid arguments reports all applicable diagnostics

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Sergio0694 Sergio0694 force-pushed the user/sergiopedri/bindable-custom-property2 branch from 090c57a to 76285ec Compare March 13, 2026 21:11
Sergio0694 and others added 4 commits March 13, 2026 15:25
Make detection of generator-produced members more robust. Return false early when the interface type is null and collect implemented members to ensure at least one exists before treating them as "all generated". Enhance AreAllImplementedByGenerator to handle accessor methods by moving to the associated property and to walk parent symbols to find a [GeneratedCode] attribute on the closest containing symbol; also tighten the attribute pattern check and return false for empty symbol sets. These changes prevent false positives when members are inherited/implemented but not actually produced by the generator.
Add a conditional PropertyGroup in src/Tests/FunctionalTests/Directory.Build.props that sets CsWinRTUseWindowsUIXamlProjections to false when it is not already defined, preventing the feature switch below from being considered invalid. Also normalize whitespace in a commented CsWinRTKeepGeneratedSources line in src/Tests/AuthoringWuxTest/AuthoringWuxTest.csproj (formatting-only change).
Add a :sourcegenerator2test block to build.cmd that runs the
SourceGenerator2Test project via dotnet test, following the same
pattern as the existing :sourcegeneratortest block. Includes
platform parameter since the project requires x64/x86.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Update WinRT.SourceGenerator2/.editorconfig to use LF line endings (copy of root file with CRLF replaced by LF) so generated sources use consistent LF endings (helps with multiline string literals and formatting). Remove redundant .editorconfig from Tests/SourceGenerator2Test.
Add GetCsWinRTUseWindowsUIXamlProjections extension to AnalyzerConfigOptionsExtensions and update CustomPropertyProviderGenerator to use it instead of calling GetBooleanProperty directly. This centralizes retrieval of the "CsWinRTUseWindowsUIXamlProjections" analyzer/MSBuild option and keeps option access consistent across the codebase.
Update DiagnosticDescriptors.cs message to suggest referencing 'Microsoft.WindowsAppSDK.WinUI' instead of 'WindowsAppSDK.WinUI', so the diagnostic points users to the correct package/namespace to resolve the missing ICustomPropertyProvider interface.
Update CSharpGeneratorTest to normalize expected text line endings by replacing CRLF with LF when constructing expectedText. Added a comment explaining the change so test files won't fail due to platform line ending differences; assembly version replacement remains unchanged.
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.

3 participants