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

System.InvalidOperationException with 2 complicated global alias's in a row #71502

Closed ThadHouse closed 9 months ago

ThadHouse commented 9 months ago

Having a file with the following contents

global using unsafe DataLogHandle = void*;
global using unsafe DataLogWriteFunc = delegate* unmanaged[Cdecl]<void*, byte*, nuint, void>;

and the following .editorconfig

[*.{cs,vb}]
dotnet_sort_system_directives_first = true

Fails to format with the following error.

Unhandled exception: System.InvalidOperationException: Failed to compare two elements in the array.
 ---> System.InvalidOperationException: Unexpected null - line 128
   at Roslyn.Utilities.Contract.Fail(String message, Int32 lineNumber)
   at Microsoft.CodeAnalysis.CSharp.Utilities.UsingsAndExternAliasesDirectiveComparer.Compare(SyntaxNode directive1, SyntaxNode directive2)
   at System.Linq.EnumerableSorter`2.CompareAnyKeys(Int32 index1, Int32 index2)
   at System.Collections.Generic.ArraySortHelper`1.SwapIfGreater(Span`1 keys, Comparison`1 comparer, Int32 i, Int32 j)
   at System.Collections.Generic.ArraySortHelper`1.IntroSort(Span`1 keys, Int32 depthLimit, Comparison`1 comparer)
   at System.Collections.Generic.ArraySortHelper`1.IntrospectiveSort(Span`1 keys, Comparison`1 comparer)
   at System.Collections.Generic.ArraySortHelper`1.Sort(Span`1 keys, Comparison`1 comparer)
   --- End of inner exception stack trace ---
   at System.Collections.Generic.ArraySortHelper`1.Sort(Span`1 keys, Comparison`1 comparer)
   at System.Linq.EnumerableSorter`2.QuickSort(Int32[] keys, Int32 lo, Int32 hi)
   at System.Linq.EnumerableSorter`1.Sort(TElement[] elements, Int32 count)
   at System.Linq.OrderedEnumerable`1.Fill(Buffer`1 buffer, Span`1 destination)
   at System.Linq.OrderedEnumerable`1.ToList()
   at Microsoft.CodeAnalysis.CSharp.Utilities.UsingsAndExternAliasesOrganizer.OrganizeWorker(SyntaxList`1 externAliasList, SyntaxList`1 usingList, Boolean placeSystemNamespaceFirst, SyntaxTrivia newLineTrivia, SyntaxList`1& organizedExternAliasList, SyntaxList`1& organizedUsingList)
   at Microsoft.CodeAnalysis.CSharp.Utilities.UsingsAndExternAliasesOrganizer.Organize(SyntaxList`1 externAliasList, SyntaxList`1 usingList, Boolean placeSystemNamespaceFirst, Boolean separateGroups, SyntaxTrivia newLineTrivia, SyntaxList`1& organizedExternAliasList, SyntaxList`1& organizedUsingList)
   at Microsoft.CodeAnalysis.CSharp.OrganizeImports.CSharpOrganizeImportsService.Rewriter.VisitCompilationUnit(CompilationUnitSyntax node)
   at Microsoft.CodeAnalysis.CSharp.Syntax.CompilationUnitSyntax.Accept[TResult](CSharpSyntaxVisitor`1 visitor)
   at Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.Visit(SyntaxNode node)
   at Microsoft.CodeAnalysis.CSharp.OrganizeImports.CSharpOrganizeImportsService.OrganizeImportsAsync(Document document, OrganizeImportsOptions options, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Formatting.Formatter.OrganizeImportsAsync(Document document, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Tools.Formatters.OrganizeImportsFormatter.FormatFileAsync(Document document, SourceText sourceText, OptionSet optionSet, AnalyzerConfigOptions analyzerConfigOptions, FormatOptions formatOptions, ILogger logger, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Tools.Formatters.DocumentFormatter.GetFormattedSourceTextAsync(Document document, OptionSet optionSet, AnalyzerConfigOptions analyzerConfigOptions, FormatOptions formatOptions, ILogger logger, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Tools.Formatters.DocumentFormatter.<>c__DisplayClass8_1.<<FormatFiles>b__0>d.MoveNext()
--- End of stack trace from previous location ---
   at Microsoft.CodeAnalysis.Tools.Formatters.DocumentFormatter.ApplyFileChangesAsync(Solution solution, ImmutableArray`1 formattedDocuments, FormatOptions formatOptions, ILogger logger, List`1 formattedFiles, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Tools.Formatters.DocumentFormatter.FormatAsync(Workspace workspace, Solution solution, ImmutableArray`1 formattableDocuments, FormatOptions formatOptions, ILogger logger, List`1 formattedFiles, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Tools.CodeFormatter.RunCodeFormattersAsync(Workspace workspace, Solution solution, ImmutableArray`1 formattableDocuments, FormatOptions formatOptions, ILogger logger, List`1 formattedFiles, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Tools.CodeFormatter.FormatWorkspaceAsync(FormatOptions formatOptions, ILogger logger, CancellationToken cancellationToken, String binaryLogPath)
   at Microsoft.CodeAnalysis.Tools.FormatCommandCommon.FormatAsync(FormatOptions formatOptions, ILogger`1 logger, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Tools.Commands.RootFormatCommand.FormatCommandDefaultHandler.InvokeAsync(ParseResult parseResult, CancellationToken cancellationToken)
   at System.CommandLine.Invocation.InvocationPipeline.InvokeAsync(ParseResult parseResult, CancellationToken cancellationToken)

Pretty much any 2 global alias's there cause an issue, they don't have to explicitly be a void* and a function pointer.

Attached is a minimal self contained project to reproduce this. Reproduces with dotnet format version 8.0.453106+2651752953c0d41c8c7b8d661cf2237151af33d0

DotNetBuilds.zip

CyrusNajmabadi commented 9 months ago

This is an issue in roslyn. moving.