Skip to content

Add authoring analyzers for [ApiContract] and [ContractVersion]#2407

Open
Sergio0694 wants to merge 25 commits intostaging/3.0from
user/sergiopedri/authoring-analyzers
Open

Add authoring analyzers for [ApiContract] and [ContractVersion]#2407
Sergio0694 wants to merge 25 commits intostaging/3.0from
user/sergiopedri/authoring-analyzers

Conversation

@Sergio0694
Copy link
Copy Markdown
Member

@Sergio0694 Sergio0694 commented Apr 24, 2026

Summary

Adds a set of new Roslyn diagnostic analyzers in the WinRT.SourceGenerator2 project that validate Windows Runtime component authoring usage of [ApiContract], [ContractVersion], and [Version]. Also introduces small reusable extension helpers and refines the public surface of ContractVersionAttribute.

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 .winmd that fails (or worse, succeeds with wrong metadata) downstream.

Changes

New diagnostics (CSWINRT2010CSWINRT2017)

  • CSWINRT2010ValidApiContractEnumTypeAnalyzer (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 / CSWINRT2013ValidContractVersionAttributeAnalyzer (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: the Type argument of the (Type, uint) constructor must itself be a valid API contract type.
  • CSWINRT2014ApiContractTypeRequiresContractVersionAnalyzer (Warning): every [ApiContract] enum must declare its contract version using a version-only constructor of [ContractVersion].
  • CSWINRT2015PublicTypeRequiresVersioningAnalyzer (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 by CSWINRT2014) and types that already have either attribute applied.
  • CSWINRT2016PublicTypeRequiresContractVersionAnalyzer (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.
  • CSWINRT2017PublicTypeMixedVersioningAttributesAnalyzer (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 analyzers ValidApiContractEnumTypeAnalyzer, ValidContractVersionAttributeAnalyzer, ApiContractTypeRequiresContractVersionAnalyzer, PublicTypeRequiresVersioningAnalyzer, PublicTypeRequiresContractVersionAnalyzer, PublicTypeMixedVersioningAttributesAnalyzer.
  • src/Authoring/WinRT.SourceGenerator2/Diagnostics/DiagnosticDescriptors.cs: descriptors for CSWINRT2010CSWINRT2017.
  • src/Authoring/WinRT.SourceGenerator2/AnalyzerReleases.Shipped.md: release tracking entries for the new diagnostics.
  • src/Authoring/WinRT.SourceGenerator2/Extensions/AttributeDataExtensions.cs: new AttributeData.GetLocation(...) and AttributeData.GetArgumentLocation(int, ...) extensions, factored out of the analyzer code.
  • src/Authoring/WinRT.SourceGenerator2/Extensions/ISymbolExtensions.cs: new ISymbol.GetAttributes(INamedTypeSymbol) overload that yields only attributes of the specified type, eliminating the manual foreach + SymbolEqualityComparer filter 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: extended VerifyAnalyzerAsync with an isCsWinRTComponent parameter that injects a .globalconfig setting build_property.CsWinRTComponent = true so the gated analyzers actually run under test.

Sergio0694 and others added 16 commits April 24, 2026 11:38
…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>
@Sergio0694 Sergio0694 added enhancement New feature or request authoring Related to authoring feature work CsWinRT 3.0 labels Apr 24, 2026
@Sergio0694 Sergio0694 requested a review from manodasanW April 24, 2026 19:55
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.
@Sergio0694 Sergio0694 enabled auto-merge (squash) April 29, 2026 21:17
Sergio0694 and others added 5 commits May 6, 2026 13:36
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>
Sergio0694 and others added 3 commits May 6, 2026 13:40
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

authoring Related to authoring feature work CsWinRT 3.0 enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants