Skip to content

Commit f5b928c

Browse files
committed
Enforce banned-API checks for reference assembly
Add banned API analyzer and rule list to prevent leaking implementation-only types into the published reference assembly. - Add Microsoft.CodeAnalysis.BannedApiAnalyzers package to Directory.Packages.props - Add src/WinRT.Runtime2/BannedSymbols.txt listing the WindowsRuntimeImplementationOnlyMember attribute as banned for reference builds - Update WinRT.Runtime.csproj to enable ProduceReferenceAssembly=false for implementation builds and to define WINDOWS_RUNTIME_IMPLEMENTATION_ASSEMBLY / WINDOWS_RUNTIME_REFERENCE_ASSEMBLY appropriately - Treat the banned-API diagnostic (RS0030) as an error for both implementation and reference assembly build configurations - Wire the banned symbols file into AdditionalFiles and add the analyzer package as a PrivateAssets dependency when building the reference assembly This ensures implementation-only types cannot be accidentally exposed in the public API surface of WinRT.Runtime.
1 parent 1f1f78d commit f5b928c

3 files changed

Lines changed: 39 additions & 14 deletions

File tree

src/Directory.Packages.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<PackageVersion Include="coverlet.collector" Version="1.3.0" />
1414
<PackageVersion Include="MarkdownLog.NS20" Version="0.10.1" />
1515
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" />
16+
<PackageVersion Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" Version="4.14.0" />
1617
<PackageVersion Include="Microsoft.CodeAnalysis.Common" Version="5.0.0" />
1718
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="5.0.0" />
1819
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Analyzer.Testing" Version="1.1.2" />
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# We use the '[WindowsRuntimeImplementationOnlyMember]' attribute to mark
2+
# all implementation-only types in 'WinRT.Runtime.dll'. These types are
3+
# only included when building the implementation assembly, while entirely
4+
# skipped when producing the reference assembly. This list of banned
5+
# symbols is only included when building the reference assembly, which
6+
# ensures that we never accidentally leak any of them in the public API.
7+
T:WindowsRuntime.WindowsRuntimeImplementationOnlyMemberAttribute

src/WinRT.Runtime2/WinRT.Runtime.csproj

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -79,28 +79,33 @@
7979
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
8080
</PropertyGroup>
8181

82-
<!--
83-
Disable the default 'ProduceReferenceAssembly' behavior. WinRT.Runtime provides its own custom
84-
reference assembly (built with 'CsWinRTBuildReferenceAssembly=true') that strips private implementation
85-
detail types via '#if WINDOWS_RUNTIME_IMPLEMENTATION_ASSEMBLY'. The SDK-generated ref assembly would
86-
include those types (since 'WINDOWS_RUNTIME_REFERENCE_ASSEMBLY' is not defined in normal builds), which
87-
would leak abstract members to downstream ProjectReference consumers and break reference projections.
88-
-->
82+
<!-- Settings for the implementation assembly -->
8983
<PropertyGroup Condition="'$(CsWinRTBuildReferenceAssembly)' != 'true'">
84+
85+
<!--
86+
Disable the default 'ProduceReferenceAssembly' behavior. WinRT.Runtime provides its own custom
87+
reference assembly (built with 'CsWinRTBuildReferenceAssembly=true') that strips private implementation
88+
detail types via '#if WINDOWS_RUNTIME_IMPLEMENTATION_ASSEMBLY'. The SDK-generated ref assembly would
89+
include those types (since 'WINDOWS_RUNTIME_REFERENCE_ASSEMBLY' is not defined in normal builds), which
90+
would leak abstract members to downstream ProjectReference consumers and break reference projections.
91+
-->
9092
<ProduceReferenceAssembly>false</ProduceReferenceAssembly>
9193

9294
<!-- Build constant to simplify '#ifdef'-s, so they don't need negation expressions -->
9395
<DefineConstants>$(DefineConstants);WINDOWS_RUNTIME_IMPLEMENTATION_ASSEMBLY</DefineConstants>
96+
<WarningsAsErrors>$(WarningsAsErrors);RS0030</WarningsAsErrors>
9497
</PropertyGroup>
9598

96-
<!--
97-
When producing a reference assembly for packaging, define 'WINDOWS_RUNTIME_REFERENCE_ASSEMBLY'. This is used
98-
to completely strip out the private implementation detail types from the reference assembly, so they're
99-
further hidden. This is conditioned on 'CsWinRTBuildReferenceAssembly' (and NOT 'ProduceReferenceAssembly'),
100-
because 'ProduceReferenceAssembly' is set to 'true' by default by the .NET SDK for library projects. The
101-
stripping should only happen during the explicit reference assembly build step for NuGet packaging.
102-
-->
99+
<!-- Settings for the reference assembly -->
103100
<PropertyGroup Condition="'$(CsWinRTBuildReferenceAssembly)' == 'true'">
101+
102+
<!--
103+
When producing a reference assembly for packaging, define 'WINDOWS_RUNTIME_REFERENCE_ASSEMBLY'. This is used
104+
to completely strip out the private implementation detail types from the reference assembly, so they're
105+
further hidden. This is conditioned on 'CsWinRTBuildReferenceAssembly' (and NOT 'ProduceReferenceAssembly'),
106+
because 'ProduceReferenceAssembly' is set to 'true' by default by the .NET SDK for library projects. The
107+
stripping should only happen during the explicit reference assembly build step for NuGet packaging.
108+
-->
104109
<DefineConstants>$(DefineConstants);WINDOWS_RUNTIME_REFERENCE_ASSEMBLY</DefineConstants>
105110

106111
<!--
@@ -111,7 +116,19 @@
111116
- IDE0380: 'unsafe' modifier is unnecessary (some types have 'unsafe' for excluded members).
112117
-->
113118
<NoWarn>$(NoWarn);CS8597;IDE0005;IDE0380</NoWarn>
119+
120+
<!-- Always make the banned API analyzer warnings errors, since these should always be blocking -->
121+
<WarningsAsErrors>$(WarningsAsErrors);RS0030</WarningsAsErrors>
114122
</PropertyGroup>
123+
<ItemGroup Condition="'$(CsWinRTBuildReferenceAssembly)' == 'true'">
124+
125+
<!-- Include the banned API list, for the implementation-only marker attribute -->
126+
<None Remove="BannedSymbols.txt" />
127+
<AdditionalFiles Include="BannedSymbols.txt" />
128+
129+
<!-- Include the banned API analyzer, which we use to block implementation-only types in the reference assembly -->
130+
<PackageReference Include="Microsoft.CodeAnalysis.BannedApiAnalyzers" PrivateAssets="all" />
131+
</ItemGroup>
115132

116133
<!--
117134
Strip all files whose top-level type is annotated with '[WindowsRuntimeImplementationOnlyMember]'

0 commit comments

Comments
 (0)