Skip to content

Fix #4079: make stable Roslyn restorable from the solution directory - #4081

Merged
siegfriedpammer merged 1 commit into
masterfrom
fix/4079-vs-nuget-source-mapping
Aug 30, 2026
Merged

siegfriedpammer merged 1 commit into
masterfrom
fix/4079-vs-nuget-source-mapping

Conversation

@siegfriedpammer

@siegfriedpammer siegfriedpammer commented Aug 29, 2026

Copy link
Copy Markdown
Member

Fixes #4079 (and the earlier, closed-as-unreproducible #3835).

Root cause. ICSharpCode.Decompiler.Generators pins a stable Microsoft.CodeAnalysis.CSharp 5.0.0 (a source generator must not reference a Roslyn newer than the host compiler) and ILSpy.AddIn.VS2022 pins a stable 4.0.1. Stable Roslyn lives only on nuget.org, but the root NuGet.config mapped Microsoft.CodeAnalysis.* exclusively to the dotnet-tools feed, which carries only prerelease builds. Both projects worked around that with a per-project NuGet.config -- which dotnet restore honors (settings are computed per project directory), but Visual Studio starts NuGet.config discovery at the solution directory and never sees it. So the first restore in VS on a machine with a cold NuGet cache fails with NU1103 exactly as reported. Once any successful restore lands the stable package in the global packages folder, source mapping is satisfied from the cache and the problem never reappears on that machine -- which is why it looked unreproducible for everyone who had built ILSpy before.

Fix. Map Microsoft.CodeAnalysis.* to nuget.org as well as to dotnet-tools. NuGet consults every source that declares the longest pattern matching a package id, so with the same pattern on both feeds the stable versions resolve from nuget.org and the prerelease $(RoslynVersion) from dotnet-tools. Both per-project NuGet.configs are then redundant and removed.

Verification (each with an empty NUGET_PACKAGES and --configfile NuGet.config, i.e. the root config as the only config, simulating VS's solution-dir discovery):

  • old config: reproduces the reported NU1103 verbatim;
  • new config: ICSharpCode.Decompiler.Generators restores (5.0.0 from nuget.org);
  • new config: ICSharpCode.Decompiler.Tests restores (5.10.0-1.x from dotnet-tools);
  • new config: ILSpy.AddIn.VS2022 restores (4.0.1 plus its Workspaces/VisualBasic/Features dependencies from nuget.org);
  • restore.ps1 over the full solution: clean, no packages.lock.json changes.

The reporter's git rev-parse HEAD^^{commit} exit code 9009 is unrelated: git is not on their PATH (fresh Windows with only VS's private git). That Exec is ContinueOnError=true and update-assemblyinfo.ps1 has a no-git fallback, so it is a cosmetic warning only.

This PR was authored by an AI agent (Claude Code) operating under the account owner's direction.

ICSharpCode.Decompiler.Generators pins a stable Microsoft.CodeAnalysis.CSharp
(a source generator must not reference a Roslyn newer than the host compiler)
and ILSpy.AddIn.VS2022 pins a stable 4.0.1. Stable Roslyn lives only on
nuget.org, but the repo-root NuGet.config mapped Microsoft.CodeAnalysis.*
exclusively to the dotnet-tools feed, which carries only prerelease builds.
Both projects worked around that with a per-project NuGet.config. dotnet
restore honors it, since settings are computed per project directory, but
Visual Studio starts NuGet.config discovery at the solution directory and
never sees it: the first restore in VS on a machine with a cold NuGet cache
fails with NU1103 exactly as reported. Once any successful restore has put
the stable package into the global packages folder, source mapping is
satisfied from the cache and the problem never reappears on that machine,
which is why #3835 was closed as unreproducible.

NuGet consults every source that declares the longest pattern matching a
package id, so mapping Microsoft.CodeAnalysis.* to nuget.org as well as to
dotnet-tools makes both feeds available for the whole family: the stable
versions resolve from nuget.org and the prerelease $(RoslynVersion) from
dotnet-tools. Both per-project configs are then redundant and removed.

Verified with an empty NUGET_PACKAGES and the root config forced as the only
config (simulating VS's discovery): the old config reproduces the reported
NU1103; with the new config the generator, the decompiler tests (prerelease
Roslyn) and the VS add-in (stable 4.0.1 with its Workspaces dependencies)
all restore; restore.ps1 over ILSpy.sln leaves the lock files unchanged.

Assisted-by: Claude:claude-fable-5:Claude Code
@siegfriedpammer
siegfriedpammer force-pushed the fix/4079-vs-nuget-source-mapping branch from 9262ad3 to cd10506 Compare August 30, 2026 08:37
@siegfriedpammer siegfriedpammer changed the title Fix #4079: make the stable Roslyn for the source generator restorable in Visual Studio Fix #4079: make stable Roslyn restorable from the solution directory Aug 30, 2026
@siegfriedpammer
siegfriedpammer merged commit a189b83 into master Aug 30, 2026
15 checks passed
@siegfriedpammer
siegfriedpammer deleted the fix/4079-vs-nuget-source-mapping branch August 30, 2026 09:38
@siegfriedpammer
siegfriedpammer restored the fix/4079-vs-nuget-source-mapping branch August 30, 2026 09:39
@siegfriedpammer
siegfriedpammer deleted the fix/4079-vs-nuget-source-mapping branch August 30, 2026 09:39
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.

Can't build

2 participants