Add authoring analyzers for [ApiContract] and [ContractVersion]#2407
Open
Sergio0694 wants to merge 25 commits intostaging/3.0from
Open
Add authoring analyzers for [ApiContract] and [ContractVersion]#2407Sergio0694 wants to merge 25 commits intostaging/3.0from
Sergio0694 wants to merge 25 commits intostaging/3.0from
Conversation
…m cases Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ractVersion]' usage Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-Authored-By: Copilot <223556219+Copilot@users.noreply.github.com>
Replace AttributeTargets.All with an explicit list of allowed targets and reformat AttributeUsage for clarity. Swap the Type/string constructor signatures and add XML <remarks> to each constructor to clarify when each overload applies (API-contract vs non-API-contract types). Note: the constructor signature order changed, which can be a breaking change for callers and may require code updates.
Iterate and validate each [ContractVersion] attribute instance and report diagnostics per-attribute. Simplifies and corrects the condition for version-only constructors by combining checks (isVersionOnlyConstructor && !isApiContractType) so the diagnostic is raised for each attribute applied to non-API contract types. Also updates minor comment wording.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…'ContractVersionAttribute' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…actVersionAttribute' Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…nalyzers Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Youssef1313
reviewed
Apr 24, 2026
Refactor PublicTypeRequiresContractVersionAnalyzer to combine the cast and accessibility/containing-type checks into a single pattern-matching expression on context.Symbol. Removes a separate INamedTypeSymbol assignment and simplifies the early-return check without changing behavior.
manodasanW
reviewed
May 2, 2026
The 'PublicTypeRequiresContractVersionAnalyzer' analyzer is renamed to 'PublicTypeRequiresVersioningAnalyzer' and now accepts either a '[ContractVersion]' or a '[Version]' attribute as valid version metadata on a public authored type. This matches the WinRT type system, where either attribute is sufficient to declare the version of a type. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…oning Reports when a public type in a Windows Runtime component is missing a '[ContractVersion]' attribute, but at least one other public type in the same component does have one applied. Public types in a component should consistently use either contract versioning or not, to avoid mixing two different versioning schemes across the public API surface. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Implements the consistency check for '[ContractVersion]' usage across the public API surface of a Windows Runtime component. Public types without '[ContractVersion]' are collected during symbol analysis, and diagnostics are reported in the compilation end action only if at least one other public type in the compilation has it applied. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Covers: no public types, single public type with/without contract version, all public types with/without contract version, '[Version]' mixed with '[ContractVersion]', API contract enum exclusion, nested and internal types, and the multiple-warning scenario. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Reports when a public type in a Windows Runtime component has both '[ContractVersion]' and '[Version]' attributes applied. Public types should use only one of the two versioning schemes, and the choice should be applied consistently across the public API surface. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Implements the per-symbol check that flags public types in a Windows Runtime component which have both '[ContractVersion]' and '[Version]' attributes applied. API contract enum types (annotated with '[ApiContract]') are skipped, as those use '[ContractVersion]' with different semantics. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Covers: only '[ContractVersion]' or only '[Version]' applied (no warning), API contract enum with both (skipped), internal/nested types with both (skipped or scoped), the not-a-component case, and the full set of public type kinds (class, interface, struct, enum, delegate) with both attributes applied (warning). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Two of the new authoring analyzers fire on the 'AuthoringTest' project, which intentionally exercises a broad mix of WinRT authoring patterns: - 'CSWINRT2014' fires on 'AnotherNamespaceContract', which is missing a '[ContractVersion]' attribute. This is a real oversight, since the enum is used as the contract argument by other types in the same file. Fix it by adding '[ContractVersion(1u)]'. - 'CSWINRT2016' fires on the 81 public types in the project that lack '[ContractVersion]', because a few other types in the same project do have it. This is the intended state of the test surface, which exercises all the various combinations of versioning attributes (with and without '[ContractVersion]', with '[Version]', mixed, etc.). Suppress the warning in the project file with a comment documenting the rationale. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a set of new Roslyn diagnostic analyzers in the
WinRT.SourceGenerator2project that validate Windows Runtime component authoring usage of[ApiContract],[ContractVersion], and[Version]. Also introduces small reusable extension helpers and refines the public surface ofContractVersionAttribute.All new analyzers are scoped to component-authoring scenarios (
CsWinRTComponent = true) and are skipped otherwise.Motivation
Authoring Windows Runtime components in C# has a number of WinMD-level constraints that are easy to get wrong silently — invalid
[ApiContract]enum cases, mismatched[ContractVersion]constructor usage, missing version metadata, mixed versioning schemes across the public API surface, etc. These analyzers surface those issues at edit/build time with actionable diagnostics, rather than producing a malformed.winmdthat fails (or worse, succeeds with wrong metadata) downstream.Changes
New diagnostics (
CSWINRT2010–CSWINRT2017)CSWINRT2010—ValidApiContractEnumTypeAnalyzer(Warning): warns when an[ApiContract]enum defines enum cases. API contract types are represented as empty struct types in WinRT and any enum cases are ignored when generating the.winmd.CSWINRT2011/CSWINRT2012/CSWINRT2013—ValidContractVersionAttributeAnalyzer(Warning): validates[ContractVersion]applications:2011: the(uint)and(string, uint)constructors must target an API contract type.2012: the(Type, uint)constructor must not target an API contract type.2013: theTypeargument of the(Type, uint)constructor must itself be a valid API contract type.CSWINRT2014—ApiContractTypeRequiresContractVersionAnalyzer(Warning): every[ApiContract]enum must declare its contract version using a version-only constructor of[ContractVersion].CSWINRT2015—PublicTypeRequiresVersioningAnalyzer(Info): public top-level types in a component should declare their version using either[ContractVersion(typeof(SomeContract), version)](to associate with an API contract) or[Version(version)](to specify a Windows Runtime version). Skips API contract enums (covered byCSWINRT2014) and types that already have either attribute applied.CSWINRT2016—PublicTypeRequiresContractVersionAnalyzer(Warning): if at least one public type in the component uses[ContractVersion], then all other public types should also use[ContractVersion]for consistency. Whole-compilation analysis (collects candidates during symbol analysis, then reports during the compilation end action). Skips API contract enums.CSWINRT2017—PublicTypeMixedVersioningAttributesAnalyzer(Warning): public types should not mix[ContractVersion]and[Version]on the same type — pick one versioning scheme and apply it consistently. Skips API contract enums.Files
src/Authoring/WinRT.SourceGenerator2/Diagnostics/Analyzers/: new analyzersValidApiContractEnumTypeAnalyzer,ValidContractVersionAttributeAnalyzer,ApiContractTypeRequiresContractVersionAnalyzer,PublicTypeRequiresVersioningAnalyzer,PublicTypeRequiresContractVersionAnalyzer,PublicTypeMixedVersioningAttributesAnalyzer.src/Authoring/WinRT.SourceGenerator2/Diagnostics/DiagnosticDescriptors.cs: descriptors forCSWINRT2010–CSWINRT2017.src/Authoring/WinRT.SourceGenerator2/AnalyzerReleases.Shipped.md: release tracking entries for the new diagnostics.src/Authoring/WinRT.SourceGenerator2/Extensions/AttributeDataExtensions.cs: newAttributeData.GetLocation(...)andAttributeData.GetArgumentLocation(int, ...)extensions, factored out of the analyzer code.src/Authoring/WinRT.SourceGenerator2/Extensions/ISymbolExtensions.cs: newISymbol.GetAttributes(INamedTypeSymbol)overload that yields only attributes of the specified type, eliminating the manualforeach+SymbolEqualityComparerfilter pattern at call sites.src/WinRT.Runtime2/Windows.Foundation.Metadata/ContractVersionAttribute.cs: small API/doc tweaks aligned with the new analyzer expectations.src/Tests/SourceGenerator2Test/:Test_ValidApiContractEnumTypeAnalyzer.cs,Test_ValidContractVersionAttributeAnalyzer.cs,Test_ApiContractTypeRequiresContractVersionAnalyzer.cs,Test_PublicTypeRequiresVersioningAnalyzer.cs,Test_PublicTypeRequiresContractVersionAnalyzer.cs,Test_PublicTypeMixedVersioningAttributesAnalyzer.cs.Helpers/CSharpAnalyzerTest{TAnalyzer}.cs: extendedVerifyAnalyzerAsyncwith anisCsWinRTComponentparameter that injects a.globalconfigsettingbuild_property.CsWinRTComponent = trueso the gated analyzers actually run under test.