dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
19.05k stars 4.04k forks source link

Source Generator is not reloaded since SDK 7.0.200 - .NET Host cache issue? #67388

Closed PawelGerr closed 1 year ago

PawelGerr commented 1 year ago

Since 7.0.200 the CLI behaves incorrect on build (dotnet build --no-incremental --force). If the source generator is referenced via project reference by another (console) project then CLI seem to keep using the source generator from the very first build. I can change the code generation as often as I want but the changes are not reflected in the generated code. Even if I delete obj and bin folders, still, the the dotnet build --no-incremental --force doesn't pick up the current state of the source generator.

If I lock the SDK with global.json to 7.0.103 or 7.0.104, then everything is working correctly.

Does the build server (.NET Host), which keeps running in the background after a build, caches the source generator and doesn't invalidate the cache? If I kill the host, then a rebuild works as expected, once.

Version Used: Issue arises when building with SDKs 7.0.200 and 7.0.202. No issues with older versions and with 7.0.103 and 7.0.104

I was able to reproduce the issue on 2 different machines (win-10 x64). One of them was a non-dev PC, so it wasn't poluted with SDKs and stuff like mine.

Steps to Reproduce

  1. Create a solution with 2 projects

Project 1

SourceGen.csproj

<Project Sdk="Microsoft.NET.Sdk">

   <PropertyGroup>
      <TargetFramework>netstandard2.0</TargetFramework>
      <ImplicitUsings>enable</ImplicitUsings>
      <Nullable>enable</Nullable>
      <LangVersion>latest</LangVersion>
   </PropertyGroup>

   <ItemGroup>
      <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.4.0" PrivateAssets="all" />
   </ItemGroup>

</Project>

DemoSourceGenerator.cs

using Microsoft.CodeAnalysis;

namespace SourceGen;

[Generator]
public class DemoSourceGenerator : IIncrementalGenerator
{
   public void Initialize(IncrementalGeneratorInitializationContext context)
   {
      context.RegisterPostInitializationOutput(initializationContext =>
                                               {
                                                  initializationContext.AddSource("PostInit.cs", @"
namespace Demo;

public class Test
{
}");
                                               });
   }
}

Project 2

ConsoleApp.csproj

<Project Sdk="Microsoft.NET.Sdk">

   <PropertyGroup>
      <OutputType>Exe</OutputType>
      <TargetFramework>net7.0</TargetFramework>
      <ImplicitUsings>enable</ImplicitUsings>
      <Nullable>enable</Nullable>
   </PropertyGroup>

   <ItemGroup>
      <ProjectReference Include="..\SourceGen\SourceGen.csproj" ReferenceOutputAssembly="false" OutputItemType="Analyzer" />
   </ItemGroup>

</Project>

Program.cs

using Demo;

var test = new Test();

Console.WriteLine("Hello, World!");
  1. Build the solution with dotnet build. There should be no errors.
  2. Change DemoSourceGenerator.cs so it doesn't generate public class Test but public class Test2.
  3. Rebuild the solution with dotnet build --no-incremental --force

Expected Behavior: The compiler raises an error in Program.cs because there is no class new Test(); Actual Behavior: No error

jcouv commented 1 year ago

From your description, it's not clear that there is a compiler issue as opposed to an issue somewhere else. I suggest you build with the binary log options (-bl) and confirm whether the correct files are passed to the compiler. If they are but the compiler is not processing them correctly then feel free to re-open this issue.

IDjinn commented 1 year ago

I'd same issue here. People on c# discord said you must use Testing to develop source generators to do not keep first generation even if you build it again. Otherwise you will need reload VS.

Does it a bug, or a feature? I thought every time you do build the source generator restart, and do the new build, not the first one.

Code https://github.com/IDjinn/DTO.Generator

ypyl commented 1 year ago

I had the same issue and found an explanation here. To solve the issue need to run dotnet build-server shutdown; dotnet clean; dotnet run.