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.02k stars 4.03k forks source link

CSharpUsePrimaryConstructorCodeFixProvider threw an exception #70898

Closed grosch-intl closed 10 months ago

grosch-intl commented 11 months ago

Version Used:

Steps to Reproduce:

I upgraded my project to .NET 8 and got a code fix, so I told it to run, and it threw the exception shown below. This is what the class has for the constructor:

[DatabaseWrapper, RegisteredInterface]
public sealed partial class ActionsRequiredDatabase {
    public DateTime OneYearAgo { get; }
    private readonly int _wwid;

    public ActionsRequiredDatabase(IDbContextFactory<LampContext> contextFactory, ICaller caller) {
        OneYearAgo = DateTime.UtcNow.AddYears(-1);
        _context = contextFactory.CreateDbContext();
        _wwid = caller.Wwid;
    }

Those two attributes are custom code generator flags. Not sure if the failure relates to that at all or not, but wanted to point that out. The generator just creates an IActionsRequiredDatabase interface, and applies that interface to the class in the generated code, plus defines some methods. However, neither generator defines any constructors.

Diagnostic Id:

IDE0290 Use primary constructor

Expected Behavior:

Actual Behavior:

System.ArgumentNullException : Value cannot be null. Parameter name: document at async Microsoft.CodeAnalysis.Editing.DocumentEditor.CreateAsync() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at async Microsoft.CodeAnalysis.Editing.SolutionEditor.GetDocumentEditorAsync() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at async Microsoft.CodeAnalysis.CSharp.UsePrimaryConstructor.CSharpUsePrimaryConstructorCodeFixProvider.<>c__DisplayClass17_0.g__ProcessAssignmentAsync|8() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at async Microsoft.CodeAnalysis.CSharp.UsePrimaryConstructor.CSharpUsePrimaryConstructorCodeFixProvider.UsePrimaryConstructorAsync() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at async Microsoft.CodeAnalysis.CSharp.UsePrimaryConstructor.CSharpUsePrimaryConstructorCodeFixProvider.UsePrimaryConstructorAsync() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at async Microsoft.CodeAnalysis.CodeActions.CodeAction.ComputeOperationsAsync() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at async Microsoft.CodeAnalysis.CodeActions.CodeAction.GetPreviewOperationsAsync() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at async Microsoft.CodeAnalysis.Editor.Implementation.Suggestions.SuggestedAction.GetPreviewResultAsync() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at async Microsoft.CodeAnalysis.Editor.Implementation.Suggestions.SuggestedActionWithNestedFlavors.PreviewChangesSuggestedAction.CreateAsync() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at async Microsoft.CodeAnalysis.Editor.Implementation.Suggestions.SuggestedActionWithNestedFlavors.GetPreviewChangesFlavorAsync() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at async Microsoft.CodeAnalysis.Editor.Implementation.Suggestions.SuggestedActionWithNestedFlavors.CreateAllFlavorsAsync() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at async Microsoft.CodeAnalysis.Extensions.IExtensionManagerExtensions.PerformFunctionAsync[T]()

grosch-intl commented 11 months ago

OK, it's definitely the fact a generator is associated. The generator also is what declares the _context variable there, so if I remove the attributes and add private readonly LampContext _context; then your CodeFix will run and I end up with this:

public sealed partial class ActionsRequiredDatabase(IDbContextFactory<LampContext> contextFactory, ICaller caller) {
    public DateTime OneYearAgo { get; } = DateTime.UtcNow.AddYears(-1);
    private readonly int _wwid = caller.Wwid;
    private readonly LampContext _context = contextFactory.CreateDbContext();
jasonmalinowski commented 10 months ago

Probably just needs a filter to filter out generated files.

CyrusNajmabadi commented 10 months ago

Fixed with https://github.com/dotnet/roslyn/pull/70718.

grosch-intl commented 9 months ago

@CyrusNajmabadi Thanks for fixing. Do you know what release this will be in?

CyrusNajmabadi commented 9 months ago

The linked pr says 17.9 preview2

grosch-intl commented 4 months ago

Just verified this ran without issue after the release. Thanks so much for fixing.