Skip to content

fix(898): point Analyzer Include at the Meziantou version the manifests declare - #913

Merged
drmoisan merged 1 commit into
mainfrom
bug/meziantou-analyzer-hintpath-skew-898
Sep 20, 2026
Merged

drmoisan merged 1 commit into
mainfrom
bug/meziantou-analyzer-hintpath-skew-898

Conversation

@drmoisan

Copy link
Copy Markdown
Owner

Summary

Fifteen project files reference ..\packages\Meziantou.Analyzer.3.0.203\analyzers\dotnet\roslyn5.0\cs\Meziantou.Analyzer.dll while every packages.config in the repository pins 3.0.235. No manifest declares 3.0.203, so no restore produces it.

main does not build from a clean checkout today. This is not a latent risk; it is the current state for any environment without a warm package cache.

Closes #898.

Evidence

Measured in a clean worktree cut from main at 734112ed2, with a cold restore:

nuget restore TaskMaster.sln          -> EXIT 0, 172 packages installed
                                         packages/Meziantou.Analyzer.3.0.235/  present
                                         packages/Meziantou.Analyzer.3.0.203/  absent

msbuild VBFunctions\VBFunctions.csproj /t:Rebuild ...
  CSC : error CS0006: Metadata file
  '..\packages\Meziantou.Analyzer.3.0.203\analyzers\dotnet\roslyn5.0\cs\Meziantou.Analyzer.dll'
  could not be found

Affected: fresh clones, new git worktrees, and any CI runner after the packages/ cache entry is evicted or its key changes.

Why CI has been green

The build workflows declare a bare-prefix fallback restore-keys: nuget-${{ runner.os }}-, which restores a packages/ tree populated under an older packages.config hash. That tree still contains Meziantou.Analyzer.3.0.203 from before the manifests moved to 3.0.235, so the stale path resolves against a cached artefact no current manifest declares.

The cache comment in those workflows argues that a fallback hit can only contribute "inert orphaned version-folders for packages no longer referenced by any HintPath." That reasoning is sound for <HintPath> and <Reference>, which nuget restore reconciles. It does not hold for <Analyzer Include>, which nothing reconciles — so the orphaned folder is not inert, it is load-bearing.

Secondary consequence

In the warm-cache case the analyzer assembly resolves from the stale package, so those fifteen projects have been running an older Meziantou ruleset than their manifests declare. In the cold case they do not compile at all. Either way the analyzer gate has not been asserting what it appears to assert in those projects.

Scope — only the version segment changes

The roslyn5.0 folder segment is preserved deliberately. Neither analyzer family in this repository selects the highest folder its package ships:

Package Committed segment Package also ships
Meziantou.Analyzer roslyn5.0 (16 items) roslyn4.14, roslyn4.8, roslyn5.6, roslyn5.9
Roslynator.Analyzers roslyn4.7 (64 items) roslyn3.8, roslyn5.0

A "highest folder wins" rule would therefore have rewritten all 80 analyzer items rather than the 15 that are stale, and would have staked the analyzer build on Roslyn versions the installed MSBuild may not support. That segment encodes a toolchain compatibility choice install.ps1 made against the installed Visual Studio, and nothing in this change has the information to re-make it.

Diff: 15 files, 15 insertions, 15 deletions — one <Analyzer Include> line per project.

Verification

All fifteen affected projects rebuilt with /t:Rebuild /p:EnableNETAnalyzers=true /p:EnforceCodeStyleInBuild=true, each at EXIT 0 with zero errors and zero warnings:

VBFunctions, UtilitiesCS, ToDoModel, QuickFiler, Tags, TaskTree, TaskVisualization, VBFunctions.Test, ToDoModel.Test, UtilitiesCS.Test, TaskTree.Test, Tags.Test, TaskVisualization.Test, QuickFiler.Test, TaskMaster.Test.

Advancing the Meziantou ruleset from 3.0.203 to 3.0.235 introduces no new diagnostics in any affected project, including UtilitiesCS, the largest project in the solution.

Note that CI cannot observe the failing condition this change fixes: the restore-keys: prefix fallback structurally prevents a cold-cache build on a runner. The red control above was therefore measured locally and is recorded in the issue.

Relationship to #911

#911 tracks the broader defect this is a symptom of — Dependabot rewrites <Import> and <Error> guards for packages outside a pull request's declared group, and nothing at all rewrites <Analyzer Include>. That is how these fifteen sites became stranded in the first place. This change corrects the existing damage; #911 stops it recurring and adds a verifier for the manifest-to-project-file consistency invariant.

Split out of #911 deliberately: main is unbuildable cold now, and #911 is a large change some distance from completion.

🤖 Generated with Claude Code

…ts declare

Fifteen project files referenced
..\packages\Meziantou.Analyzer.3.0.203\analyzers\dotnet\roslyn5.0\cs\Meziantou.Analyzer.dll
while every packages.config pins 3.0.235. No manifest declares 3.0.203, so
no restore produces it and main does not build from a clean checkout:

  CSC : error CS0006: Metadata file
  '..\packages\Meziantou.Analyzer.3.0.203\...\Meziantou.Analyzer.dll'
  could not be found

CI has been green only because the workflow cache restore-keys prefix
fallback carries the old package forward from before the manifests moved.
That fallback is documented as contributing only inert orphaned folders,
which holds for HintPath and Reference because restore reconciles them, but
not for Analyzer Include, which nothing reconciles.

Only the version segment changes. The roslyn5.0 folder segment is preserved
deliberately: neither analyzer family selects the highest folder its package
ships, so a selection rule would have rewritten all eighty analyzer items
rather than the fifteen that are stale.

Verified: all fifteen affected projects rebuild at exit 0 with zero errors
and zero warnings under EnableNETAnalyzers and EnforceCodeStyleInBuild.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@drmoisan
drmoisan merged commit b562191 into main Sep 20, 2026
6 checks passed
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.

Bug: Bug: Meziantou.Analyzer HintPath skew masked by CI cache restore-keys fallback

1 participant