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

Exception from Visual Studio while coding #72076

Open ArchieCoder opened 4 months ago

ArchieCoder commented 4 months ago

Latest VS version. Exception happens while coding.

System.NullReferenceException : Object reference not set to an instance of an object.
   at Microsoft.CodeAnalysis.CSharp.SyntaxFactory.FindConditionalAccessNodeForBinding(CSharpSyntaxNode node)
   at Microsoft.CodeAnalysis.CSharp.Binder.GetReceiverForConditionalBinding(ExpressionSyntax binding,BindingDiagnosticBag diagnostics)
   at Microsoft.CodeAnalysis.CSharp.Binder.BindMemberBindingExpression(MemberBindingExpressionSyntax node,Boolean invoked,Boolean indexed,BindingDiagnosticBag diagnostics)
   at Microsoft.CodeAnalysis.CSharp.Binder.BindExpressionInternal(ExpressionSyntax node,BindingDiagnosticBag diagnostics,Boolean invoked,Boolean indexed)
   at Microsoft.CodeAnalysis.CSharp.Binder.BindExpression(ExpressionSyntax node,BindingDiagnosticBag diagnostics,Boolean invoked,Boolean indexed)
   at Microsoft.CodeAnalysis.CSharp.Binder.BindPossibleArrayInitializer(ExpressionSyntax node,TypeSymbol destinationType,BindValueKind valueKind,BindingDiagnosticBag diagnostics)
   at Microsoft.CodeAnalysis.CSharp.Binder.BindVariableDeclaration(SourceLocalSymbol localSymbol,LocalDeclarationKind kind,Boolean isVar,VariableDeclaratorSyntax declarator,TypeSyntax typeSyntax,TypeWithAnnotations declTypeOpt,AliasSymbol aliasOpt,BindingDiagnosticBag diagnostics,Boolean includeBoundType,CSharpSyntaxNode associatedSyntaxNode)
   at Microsoft.CodeAnalysis.CSharp.Binder.BindDeclarationStatementParts(LocalDeclarationStatementSyntax node,BindingDiagnosticBag diagnostics)
   at Microsoft.CodeAnalysis.CSharp.Binder.BindLocalDeclarationStatement(LocalDeclarationStatementSyntax node,BindingDiagnosticBag diagnostics)
   at Microsoft.CodeAnalysis.CSharp.Binder.BindStatement(StatementSyntax node,BindingDiagnosticBag diagnostics)
   at Microsoft.CodeAnalysis.CSharp.MemberSemanticModel.IncrementalBinder.BindStatement(StatementSyntax node,BindingDiagnosticBag diagnostics)
   at Microsoft.CodeAnalysis.CSharp.MemberSemanticModel.GetBoundNodes(CSharpSyntaxNode node)
   at Microsoft.CodeAnalysis.CSharp.MemberSemanticModel.GetBoundNodes(CSharpSyntaxNode node,CSharpSyntaxNode& bindableNode,BoundNode& lowestBoundNode,BoundNode& highestBoundNode,BoundNode& boundParent)
   at Microsoft.CodeAnalysis.CSharp.MemberSemanticModel.GetSymbolInfoWorker(CSharpSyntaxNode node,SymbolInfoOptions options,CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.CSharp.SyntaxTreeSemanticModel.GetSymbolInfoWorker(CSharpSyntaxNode node,SymbolInfoOptions options,CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.CSharp.CSharpSemanticModel.GetSymbolInfo(ExpressionSyntax expression,CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.CSharp.CSharpSemanticModel.GetSymbolInfoFromNode(SyntaxNode node,CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.CSharp.CSharpSemanticModel.GetSymbolInfoCore(SyntaxNode node,CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Simplification.SimplificationHelpers.GetOriginalSymbolInfo(SemanticModel semanticModel,SyntaxNode expression)
   at Microsoft.CodeAnalysis.CSharp.Simplification.Simplifiers.NameSimplifier.TrySimplify(NameSyntax name,SemanticModel semanticModel,CSharpSimplifierOptions options,TypeSyntax& replacementNode,TextSpan& issueSpan,CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.CSharp.Simplification.Simplifiers.ExpressionSimplifier.TryReduceExplicitName(ExpressionSyntax expression,SemanticModel semanticModel,TypeSyntax& replacementNode,TextSpan& issueSpan,CSharpSimplifierOptions options,CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.CSharp.Simplification.Simplifiers.ExpressionSimplifier.TrySimplify(ExpressionSyntax expression,SemanticModel semanticModel,CSharpSimplifierOptions options,ExpressionSyntax& replacementNode,TextSpan& issueSpan,CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.CSharp.Simplification.CSharpNameReducer.SimplifyName(SyntaxNode node,SemanticModel semanticModel,CSharpSimplifierOptions options,CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.CSharp.Simplification.AbstractCSharpReducer.AbstractReductionRewriter.SimplifyNode[TNode](TNode node,SyntaxNode newNode,Func`5 simplifier)
   at Microsoft.CodeAnalysis.CSharp.Simplification.CSharpNameReducer.Rewriter.VisitIdentifierName(IdentifierNameSyntax node)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitAliasQualifiedName(AliasQualifiedNameSyntax node)
   at Microsoft.CodeAnalysis.CSharp.Simplification.CSharpNameReducer.Rewriter.VisitAliasQualifiedName(AliasQualifiedNameSyntax node)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitQualifiedName(QualifiedNameSyntax node)
   at Microsoft.CodeAnalysis.CSharp.Simplification.CSharpNameReducer.Rewriter.VisitQualifiedName(QualifiedNameSyntax node)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitQualifiedName(QualifiedNameSyntax node)
   at Microsoft.CodeAnalysis.CSharp.Simplification.CSharpNameReducer.Rewriter.VisitQualifiedName(QualifiedNameSyntax node)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitQualifiedName(QualifiedNameSyntax node)
   at Microsoft.CodeAnalysis.CSharp.Simplification.CSharpNameReducer.Rewriter.VisitQualifiedName(QualifiedNameSyntax node)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitQualifiedName(QualifiedNameSyntax node)
   at Microsoft.CodeAnalysis.CSharp.Simplification.CSharpNameReducer.Rewriter.VisitQualifiedName(QualifiedNameSyntax node)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitQualifiedName(QualifiedNameSyntax node)
   at Microsoft.CodeAnalysis.CSharp.Simplification.CSharpNameReducer.Rewriter.VisitQualifiedName(QualifiedNameSyntax node)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitVariableDeclaration(VariableDeclarationSyntax node)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitLocalDeclarationStatement(LocalDeclarationStatementSyntax node)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
   at Microsoft.CodeAnalysis.CSharp.Simplification.AbstractCSharpReducer.AbstractReductionRewriter.VisitNodeOrToken(SyntaxNodeOrToken nodeOrToken,SemanticModel semanticModel,Boolean simplifyAllDescendants)
   at async Microsoft.CodeAnalysis.Simplification.AbstractSimplificationService`3.<>c__DisplayClass15_1.<ReduceAsync>b__0[TExpressionSyntax,TStatementSyntax,TCrefSyntax](<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.Simplification.AbstractSimplificationService`3.ReduceAsync[TExpressionSyntax,TStatementSyntax,TCrefSyntax](<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.Simplification.AbstractSimplificationService`3.ReduceCoreAsync[TExpressionSyntax,TStatementSyntax,TCrefSyntax](<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.Simplification.AbstractSimplificationService`3.ReduceAsync[TExpressionSyntax,TStatementSyntax,TCrefSyntax](<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.Simplification.Simplifier.ReduceAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.IntroduceVariable.AbstractIntroduceVariableService`6.AbstractIntroduceVariableCodeAction.GetChangedDocumentAsync[TService,TExpressionSyntax,TTypeSyntax,TTypeDeclarationSyntax,TQueryExpressionSyntax,TNameSyntax](<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.CodeActions.CodeAction.GetChangedSolutionAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.CodeActions.CodeAction.ComputeOperationsAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.CodeActions.CodeAction.GetPreviewOperationsAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.Editor.Implementation.Suggestions.SuggestedAction.GetPreviewResultAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.Editor.Implementation.Suggestions.SuggestedActionWithNestedFlavors.PreviewChangesSuggestedAction.CreateAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.Editor.Implementation.Suggestions.SuggestedActionWithNestedFlavors.GetPreviewChangesFlavorAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.Editor.Implementation.Suggestions.SuggestedActionWithNestedFlavors.CreateAllFlavorsAsync(<Unknown Parameters>)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at async Microsoft.CodeAnalysis.Extensions.IExtensionManagerExtensions.PerformFunctionAsync[T](<Unknown Parameters>)
jaredpar commented 4 months ago

Do you have any memory of what code was being typed when this happened or a dump when it happened? Based on the stack alone this likely can't be tracked down. That code is pretty straight forward and only a violation of some fairly core assumptions in our model could produce it. That is likely what is happening but need a code sample to get us pointed in the right direction.

ArchieCoder commented 4 months ago

@jaredpar I get ~10-15 exceptions per day.

Here is a screenshot earlier this morning. I was only replacing a word after duplicating a line.

https://github.com/dotnet/roslyn/issues/72074#issuecomment-1941770433

jaredpar commented 4 months ago

@ArchieCoder

Do you have any of the dumps for those exceptions though? The stack alone here is not going to be enough for us to root cause the problem.

This particular exception is part of conditional access binding ?., if you have any cases of that in the code that you're editing that would be a good start.

ArchieCoder commented 4 months ago

How do I enable VS to have a dump when this is happening?

sharwell commented 4 months ago

I suspect this issue will be heavily mitigated in 17.10 Preview 1 by #68214

sharwell commented 4 months ago

@ArchieCoder I'm not sure we have a way to collect a dump directly at the point of failure, but if you have a way to reproduce this in a standalone file it should be easy to identify the cause once we can reproduce it.

ArchieCoder commented 4 months ago

Video and 3 stack traces: https://github.com/dotnet/roslyn/assets/1608424/96c7a574-0698-4ae8-a542-281239f0aeb1 https://github.com/dotnet/roslyn/assets/1608424/5965fc36-87e9-48c9-ac37-093431e58910

jaredpar commented 4 months ago

I can share the source file if you provide me a private way.

If you file a VS feedback bug it will provide a way to privately share files.

image

The fastest way to move this forward is to grab a dump of the crash when it happens. The videos don't really help here cause without the entire solution it's not providing much more information than a stack trace. I'm skeptical a single source file is going to help here.

ArchieCoder commented 4 months ago

@jaredpar Ok, I did the steps you suggested, the dump should be included now: https://developercommunity.visualstudio.com/t/Exceptions-happens-when-duplicating-a-li/10584059

Your colleague above was not aware about the recorder (and I also forgot).

CyrusNajmabadi commented 4 months ago

@jaredpar given:

System.NullReferenceException : Object reference not set to an instance of an object.
   at Microsoft.CodeAnalysis.CSharp.SyntaxFactory.FindConditionalAccessNodeForBinding(CSharpSyntaxNode node)
   at Microsoft.CodeAnalysis.CSharp.Binder.GetReceiverForConditionalBinding(ExpressionSyntax binding,BindingDiagnosticBag diagnostics)
   at Microsoft.CodeAnalysis.CSharp.Binder.BindMemberBindingExpression(MemberBindingExpressionSyntax node,Boolean invoked,Boolean indexed,BindingDiagnosticBag diagnostics)
   at Microsoft.CodeAnalysis.CSharp.Binder.BindExpressionInternal(ExpressionSyntax node,BindingDiagnosticBag diagnostics,Boolean invoked,Boolean indexed)

and that this is within an IDE rewrite, it's pretty likely we're producing an invalid tree that is breaking you. 'Binding' nodes (?., ?[, ...) in particular are very easy to get wrong in a rewrite. So i would not be surprised if we made some simple assumptions about tree shape that don't hold here.

sharwell commented 4 months ago

@ArchieCoder The recorder captures the state, but not at a point in time where the context leading to the exception is available. By the time you see the gold bar appear, the context information is already discarded. A standalone project would be extremely helpful in narrowing this down if there is any way you can create it. Otherwise, we may be able to identify the source of the issue by looking at the source code if it's attached to the issue you opened yesterday.

ArchieCoder commented 4 months ago

I was able to do a sample solution.

BugRename.zip

sharwell commented 4 months ago

I reduced the sample solution to the following. Pressing Ctrl+. on the assignment to IsDetailsPanelShown and selecting "Introduce parameter for 'IsDetailsPanelShown'" will result in an exception.

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

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
  </ItemGroup>

</Project>
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

namespace NMaxDashboard.Core.ViewModels;

public abstract partial class BaseDatePageViewModel : ObservableObject
{
    [RelayCommand]
    public virtual async Task Load()
    {
    }
}

public partial class PowerDataPageViewModel : BaseDatePageViewModel
{
    [ObservableProperty] private bool _isDetailsPanelShown;

    public override async Task Load()
    {
        IsDetailsPanelShown = true;
    }
}
sharwell commented 4 months ago

I was able to further simplify this to reproduce without any use of source generators. The source of the bug in Introduce Parameter is the method group reference to Load. This may be a slightly different exception than the one at the start of this issue though.

using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;

namespace NMaxDashboard.Core.ViewModels;

public abstract partial class BaseDatePageViewModel : ObservableObject
{
    private AsyncRelayCommand? loadCommand;
    public IAsyncRelayCommand LoadCommand => loadCommand ??= new AsyncRelayCommand(new Func<Task>(Load));

    public virtual async Task Load()
    {
    }
}

public partial class PowerDataPageViewModel : BaseDatePageViewModel
{
    private bool IsDetailsPanelShown;

    public override async Task Load()
    {
        IsDetailsPanelShown = true;
    }
}
sharwell commented 4 months ago

@CyrusNajmabadi I think the following three changes would work:

  1. Update Introduce Parameter to either fix the method group reference or report a warning that it cannot be fixed
  2. Update Rename tracking code fix to not try to rename items defined in generated code
  3. Update both Introduce Parameter and Rename Tracking to avoid making changes to source generated code, and if such a change would be needed present a warning in the preview that the result might not be correct
CyrusNajmabadi commented 4 months ago

@akhera99 for intro-param issues.

Update Rename tracking code fix to not try to rename items defined in generated code

taht seems fine with me.

if such a change would be needed present a warning in the preview that the result might not be correct

The last time this was discussed, we said that we should not give warnings for generated code. Because the presumption is that the generated code will just regen based on the changes actually made. And if we trust generators to be good, they should get the code back to a good state. In otehr words, it doesn't make sense to give warning against a change, when teh part we're warning about is stale code.