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
18.74k stars 3.99k forks source link

EmitCompilerGeneratedFiles does not correctly overwrite previous version of the file #49125

Closed svick closed 3 years ago

svick commented 3 years ago

Version Used: 3.8.0-5.final

Steps to Reproduce:

  1. Clone dotnet/roslyn-sdk.
  2. In eng\Versions.props, change <MicrosoftNetCompilersToolsetVersion> to 3.8.0-5.final.
  3. In samples\CSharp\SourceGenerators\GeneratedDemo\GeneratedDemo.csproj, add <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>.
  4. Build the SourceGenerators solution.
  5. Comment out private int _amount = 5; in samples\CSharp\SourceGenerators\GeneratedDemo\UseAutoNotifyGenerator.cs.
  6. Build again. (This build fails, because of the missing Count property, but that's irrelevant.)

Expected Behavior:

The file artifacts\obj\GeneratedDemo\Debug\netcoreapp3.1\generated\SourceGeneratorSamples\SourceGeneratorSamples.AutoNotifyGenerator\ExampleViewModel_autoNotify.cs contains source code used in the last build.

Actual Behavior:

The file contains a broken mix of code from the last two builds:


namespace GeneratedDemo
{
    public partial class ExampleViewModel : System.ComponentModel.INotifyPropertyChanged
    {
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
public string Text
{
    get 
    {
        return this._text;
    }

    set
    {
        this._text = value;
        this.PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(nameof(Text)));
    }
}

} }ublic int Count
{
    get 
    {
        return this._amount;
    }

    set
    {
        this._amount = value;
        this.PropertyChanged?.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(nameof(Count)));
    }
}

} }

It seems that when the new code is shorter than that old code, the file is not properly overwritten.

As far as I can tell, this happens because the following line uses FileMode.OpenOrCreate, when it should be using FileMode.Create:

https://github.com/dotnet/roslyn/blob/a6f654bb03596c2c3392bb16f082cc1615fac425/src/Compilers/Core/Portable/CommandLine/CommonCompiler.cs#L1000

nagya commented 3 years ago

Pretty annoying bug, makes it much more difficult to work around the lack of generator support in 3rd party IDEs. I'm wondering why the fix was not included in the 5.0.1 release today?