Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,33 @@ dotnet_style_require_accessibility_modifiers = omit_if_default:silent

[tests/**/*.cs]
dotnet_naming_rule.private_fields_should_be_camel_case.severity = suggestion

####################################################################
## Public API analyzer (Microsoft.CodeAnalysis.PublicApiAnalyzers)
####################################################################
# Only active on the assemblies opted in via _FalloutPublicApiAssemblies in
# Directory.Build.props. RS0016/RS0017 are the guard: adding public surface not
# recorded in PublicAPI.Unshipped.txt, or renaming/removing surface still listed
# in PublicAPI.Shipped.txt, fails the build. The remaining rules are opinionated
# API-design/nullability lint that would only add noise to a mature surface.
# Guard severities are set globally: RS0016 anchors to the .cs declaration site,
# but RS0017 (a tracked API entry no longer found in the code — the rename/removal
# guard) anchors to the PublicAPI text file, not a .cs file. A [*.cs] scope would
# leave RS0017 a non-blocking warning, so both are elevated under [*]. These rules
# only fire where the analyzer is wired (the opted-in assemblies), so a global
# scope is harmless everywhere else.
[*]
dotnet_diagnostic.RS0016.severity = error # public symbol missing from the API files
dotnet_diagnostic.RS0017.severity = error # tracked API entry no longer in the code (rename/removal)
dotnet_diagnostic.RS0026.severity = none # avoid optional params on public methods (advisory)
dotnet_diagnostic.RS0027.severity = none # public API with optional params should not add overloads (advisory)
dotnet_diagnostic.RS0036.severity = none # nullability recording (baseline is oblivious)
dotnet_diagnostic.RS0037.severity = none # enable #nullable in API files (baseline is oblivious)

# Generated tool wrappers are regenerated from the *.json specs and guarded by the
# SourceGenerators Verify snapshots — exclude them from public-API tracking so a
# GenerateTools regen doesn't churn the baselines. Ordered after the [*] block so
# last-match-wins turns the guard off for these files.
[*.Generated.cs]
dotnet_diagnostic.RS0016.severity = none
dotnet_diagnostic.RS0017.severity = none
39 changes: 39 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,43 @@
<Compile Include="$(MSBuildThisFileDirectory)AssemblyInfo.cs" />
</ItemGroup>

<!-- ── Public API surface tracking ─────────────────────────────────────────
Consumer-facing assemblies opt in below. For each listed assembly the
Roslyn Public API analyzer tracks the declared public surface against the
committed PublicAPI.Shipped.txt / PublicAPI.Unshipped.txt: renaming or
removing tracked API fails the build (RS0017), and adding public surface
fails (RS0016) until it is recorded in PublicAPI.Unshipped.txt. This is the
guard that would have flagged the #257 SolutionModel -> Solution rename.

Generated tool wrappers (*.Generated.cs) are excluded via .editorconfig -
that surface is regenerated deterministically from the *.json specs and is
already contract-guarded by the SourceGenerators Verify snapshots.

Rollout is phased: mid-size assemblies (Fallout.Build, Fallout.Tooling,
Fallout.Utilities) are tracked in a follow-up. Keep the list sorted. -->
<PropertyGroup>
<_FalloutPublicApiAssemblies>;Fallout.Build.Shared;Fallout.Common;Fallout.Components;Fallout.Core;Fallout.ProjectModel;Fallout.Solution;Fallout.Utilities.IO.Compression;Fallout.Utilities.IO.Globbing;Fallout.Utilities.Net;Fallout.Utilities.Text.Json;Fallout.Utilities.Text.Yaml;</_FalloutPublicApiAssemblies>
<_IsFalloutPublicApiAssembly Condition="$(_FalloutPublicApiAssemblies.Contains(';$(MSBuildProjectName);'))">true</_IsFalloutPublicApiAssembly>
</PropertyGroup>

<!-- Promote the removal/rename guard (RS0017) to build-breaking. RS0017 anchors to
the PublicAPI.*.txt additional file, where per-file .editorconfig severity does
not reach it, so it is promoted here at the MSBuild level (anchor-agnostic).
RS0016 is deliberately NOT listed: it is elevated to error via .editorconfig,
which also lets [*.Generated.cs] switch it off for the generated tool wrappers.
A command-line /warnaserror:RS0016 would outrank that per-file suppression and
re-promote the entire generated surface — exactly what we exclude. -->
<PropertyGroup Condition="'$(_IsFalloutPublicApiAssembly)' == 'true'">
<WarningsAsErrors>$(WarningsAsErrors);RS0017</WarningsAsErrors>
</PropertyGroup>

<ItemGroup Condition="'$(_IsFalloutPublicApiAssembly)' == 'true'">
<PackageReference Include="Microsoft.CodeAnalysis.PublicApiAnalyzers">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<AdditionalFiles Include="$(MSBuildProjectDirectory)\PublicAPI.Shipped.txt" />
<AdditionalFiles Include="$(MSBuildProjectDirectory)\PublicAPI.Unshipped.txt" />
</ItemGroup>

</Project>
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
<!-- Roslyn (Fallout.SourceGenerator + Fallout.Cli + Fallout.Migrate.Analyzers) -->
<ItemGroup>
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="5.6.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.12.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.12.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.12.0" />
Expand Down
4 changes: 4 additions & 0 deletions src/Fallout.Build.Shared/PublicAPI.Shipped.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Fallout.Common.Utilities.CompletionUtility
static Fallout.Common.Utilities.CompletionUtility.GetItemsFromSchema(Fallout.Common.IO.AbsolutePath schemaFile, System.Collections.Generic.IEnumerable<string> profileNames = null, System.Func<System.Text.Json.JsonProperty, bool> filter = null) -> System.Collections.Generic.IReadOnlyDictionary<string, string[]>
static Fallout.Common.Utilities.CompletionUtility.GetItemsFromSchema(System.Text.Json.JsonDocument schema, System.Collections.Generic.IEnumerable<string> profileNames = null, System.Func<System.Text.Json.JsonProperty, bool> filter = null) -> System.Collections.Generic.IReadOnlyDictionary<string, string[]>
static Fallout.Common.Utilities.CompletionUtility.GetRelevantItems(string words, System.Collections.Generic.IReadOnlyDictionary<string, string[]> completionItems) -> System.Collections.Generic.IEnumerable<string>
Empty file.
Loading
Loading