File: MetaAnalyzers\CompareSymbolsCorrectlyTests.cs
Web Access
Project: src\src\RoslynAnalyzers\Microsoft.CodeAnalysis.Analyzers\UnitTests\Microsoft.CodeAnalysis.Analyzers.UnitTests.csproj (Microsoft.CodeAnalysis.Analyzers.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System.Collections.Immutable;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Testing;
using Test.Utilities;
using Xunit;
using VerifyCS = Test.Utilities.CSharpSecurityCodeFixVerifier<
    Microsoft.CodeAnalysis.Analyzers.MetaAnalyzers.CompareSymbolsCorrectlyAnalyzer,
    Microsoft.CodeAnalysis.CSharp.Analyzers.MetaAnalyzers.Fixers.CSharpCompareSymbolsCorrectlyFix>;
using VerifyVB = Test.Utilities.VisualBasicSecurityCodeFixVerifier<
    Microsoft.CodeAnalysis.Analyzers.MetaAnalyzers.CompareSymbolsCorrectlyAnalyzer,
    Microsoft.CodeAnalysis.VisualBasic.Analyzers.MetaAnalyzers.Fixers.BasicCompareSymbolsCorrectlyFix>;
 
namespace Microsoft.CodeAnalysis.Analyzers.UnitTests.MetaAnalyzers
{
    public class CompareSymbolsCorrectlyTests
    {
        private const string MinimalSymbolImplementationCSharp = @"
using System;
using System.Collections.Immutable;
using System.Globalization;
using System.Threading;
using Microsoft.CodeAnalysis;
 
class Symbol : ISymbol {
    public SymbolKind Kind => throw new NotImplementedException();
    public string Language => throw new NotImplementedException();
    public string Name => throw new NotImplementedException();
    public string MetadataName => throw new NotImplementedException();
    public ISymbol ContainingSymbol => throw new NotImplementedException();
    public IAssemblySymbol ContainingAssembly => throw new NotImplementedException();
    public IModuleSymbol ContainingModule => throw new NotImplementedException();
    public INamedTypeSymbol ContainingType => throw new NotImplementedException();
    public INamespaceSymbol ContainingNamespace => throw new NotImplementedException();
    public bool IsDefinition => throw new NotImplementedException();
    public bool IsStatic => throw new NotImplementedException();
    public bool IsVirtual => throw new NotImplementedException();
    public bool IsOverride => throw new NotImplementedException();
    public bool IsAbstract => throw new NotImplementedException();
    public bool IsSealed => throw new NotImplementedException();
    public bool IsExtern => throw new NotImplementedException();
    public bool IsImplicitlyDeclared => throw new NotImplementedException();
    public bool CanBeReferencedByName => throw new NotImplementedException();
    public ImmutableArray<Location> Locations => throw new NotImplementedException();
    public ImmutableArray<SyntaxReference> DeclaringSyntaxReferences => throw new NotImplementedException();
    public Accessibility DeclaredAccessibility => throw new NotImplementedException();
    public ISymbol OriginalDefinition => throw new NotImplementedException();
    public bool HasUnsupportedMetadata => throw new NotImplementedException();
 
    public void Accept(SymbolVisitor visitor) => throw new NotImplementedException();
    public TResult Accept<TResult>(SymbolVisitor<TResult> visitor) => throw new NotImplementedException();
    public bool Equals(ISymbol other) => throw new NotImplementedException();
    public ImmutableArray<AttributeData> GetAttributes() => throw new NotImplementedException();
    public string GetDocumentationCommentId() => throw new NotImplementedException();
    public string GetDocumentationCommentXml(CultureInfo preferredCulture, bool expandIncludes, CancellationToken cancellationToken) => throw new NotImplementedException();
    public ImmutableArray<SymbolDisplayPart> ToDisplayParts(SymbolDisplayFormat format) => throw new NotImplementedException();
    public string ToDisplayString(SymbolDisplayFormat format) => throw new NotImplementedException();
    public ImmutableArray<SymbolDisplayPart> ToMinimalDisplayParts(SemanticModel semanticModel, int position, SymbolDisplayFormat format) => throw new NotImplementedException();
    public string ToMinimalDisplayString(SemanticModel semanticModel, int position, SymbolDisplayFormat format) => throw new NotImplementedException();
 
    public static bool operator ==(Symbol left, Symbol right) => throw new NotImplementedException();
    public static bool operator !=(Symbol left, Symbol right) => throw new NotImplementedException();
}
";
        private const string MinimalSymbolImplementationVisualBasic = @"
Imports System
Imports System.Collections.Immutable
Imports System.Globalization
Imports System.Threading
Imports Microsoft.CodeAnalysis
 
Class Symbol
    Implements ISymbol
 
    Public ReadOnly Property Kind As SymbolKind Implements ISymbol.Kind
    Public ReadOnly Property Language As String Implements ISymbol.Language
    Public ReadOnly Property Name As String Implements ISymbol.Name
    Public ReadOnly Property MetadataName As String Implements ISymbol.MetadataName
    Public ReadOnly Property ContainingSymbol As ISymbol Implements ISymbol.ContainingSymbol
    Public ReadOnly Property ContainingAssembly As IAssemblySymbol Implements ISymbol.ContainingAssembly
    Public ReadOnly Property ContainingModule As IModuleSymbol Implements ISymbol.ContainingModule
    Public ReadOnly Property ContainingType As INamedTypeSymbol Implements ISymbol.ContainingType
    Public ReadOnly Property ContainingNamespace As INamespaceSymbol Implements ISymbol.ContainingNamespace
    Public ReadOnly Property IsDefinition As Boolean Implements ISymbol.IsDefinition
    Public ReadOnly Property IsStatic As Boolean Implements ISymbol.IsStatic
    Public ReadOnly Property IsVirtual As Boolean Implements ISymbol.IsVirtual
    Public ReadOnly Property IsOverride As Boolean Implements ISymbol.IsOverride
    Public ReadOnly Property IsAbstract As Boolean Implements ISymbol.IsAbstract
    Public ReadOnly Property IsSealed As Boolean Implements ISymbol.IsSealed
    Public ReadOnly Property IsExtern As Boolean Implements ISymbol.IsExtern
    Public ReadOnly Property IsImplicitlyDeclared As Boolean Implements ISymbol.IsImplicitlyDeclared
    Public ReadOnly Property CanBeReferencedByName As Boolean Implements ISymbol.CanBeReferencedByName
    Public ReadOnly Property Locations As ImmutableArray(Of Location) Implements ISymbol.Locations
    Public ReadOnly Property DeclaringSyntaxReferences As ImmutableArray(Of SyntaxReference) Implements ISymbol.DeclaringSyntaxReferences
    Public ReadOnly Property DeclaredAccessibility As Accessibility Implements ISymbol.DeclaredAccessibility
    Public ReadOnly Property OriginalDefinition As ISymbol Implements ISymbol.OriginalDefinition
    Public ReadOnly Property HasUnsupportedMetadata As Boolean Implements ISymbol.HasUnsupportedMetadata
 
    Public Sub Accept(visitor As SymbolVisitor) Implements ISymbol.Accept
        Throw New NotImplementedException()
    End Sub
 
    Public Function GetAttributes() As ImmutableArray(Of AttributeData) Implements ISymbol.GetAttributes
        Throw New NotImplementedException()
    End Function
 
    Public Function Accept(Of TResult)(visitor As SymbolVisitor(Of TResult)) As TResult Implements ISymbol.Accept
        Throw New NotImplementedException()
    End Function
 
    Public Function GetDocumentationCommentId() As String Implements ISymbol.GetDocumentationCommentId
        Throw New NotImplementedException()
    End Function
 
    Public Function GetDocumentationCommentXml(Optional preferredCulture As CultureInfo = Nothing, Optional expandIncludes As Boolean = False, Optional cancellationToken As CancellationToken = Nothing) As String Implements ISymbol.GetDocumentationCommentXml
        Throw New NotImplementedException()
    End Function
 
    Public Function ToDisplayString(Optional format As SymbolDisplayFormat = Nothing) As String Implements ISymbol.ToDisplayString
        Throw New NotImplementedException()
    End Function
 
    Public Function ToDisplayParts(Optional format As SymbolDisplayFormat = Nothing) As ImmutableArray(Of SymbolDisplayPart) Implements ISymbol.ToDisplayParts
        Throw New NotImplementedException()
    End Function
 
    Public Function ToMinimalDisplayString(semanticModel As SemanticModel, position As Integer, Optional format As SymbolDisplayFormat = Nothing) As String Implements ISymbol.ToMinimalDisplayString
        Throw New NotImplementedException()
    End Function
 
    Public Function ToMinimalDisplayParts(semanticModel As SemanticModel, position As Integer, Optional format As SymbolDisplayFormat = Nothing) As ImmutableArray(Of SymbolDisplayPart) Implements ISymbol.ToMinimalDisplayParts
        Throw New NotImplementedException()
    End Function
 
    Public Function Equals(other As ISymbol) As Boolean Implements IEquatable(Of ISymbol).Equals
        Throw New NotImplementedException()
    End Function
 
    Public Shared Operator =(left As Symbol, right As Symbol) As Boolean
        Throw New NotImplementedException()
    End Operator
 
    Public Shared Operator <>(left As Symbol, right As Symbol) As Boolean
        Throw New NotImplementedException()
    End Operator
End Class
";
 
        private const string SymbolEqualityComparerStubVisualBasic =
@"
Imports System.Collections.Generic
 
Namespace Microsoft
    Namespace CodeAnalysis
        Public Class SymbolEqualityComparer
            Implements IEqualityComparer(Of ISymbol)
 
            Public Shared ReadOnly [Default] As SymbolEqualityComparer = New SymbolEqualityComparer()
 
            Private Sub New()
            End Sub
 
            Public Function Equals(x As ISymbol, y As ISymbol) As Boolean Implements IEqualityComparer(Of ISymbol).Equals
                Throw New System.NotImplementedException()
            End Function
 
            Public Function GetHashCode(obj As ISymbol) As Integer Implements IEqualityComparer(Of ISymbol).GetHashCode
                Throw New System.NotImplementedException()
            End Function
        End Class
    End Namespace
End Namespace";
 
        private const string SymbolEqualityComparerStubCSharp =
@"
using System.Collections.Generic;
 
namespace Microsoft.CodeAnalysis
{
    public class SymbolEqualityComparer : IEqualityComparer<ISymbol>
    {
        public static readonly SymbolEqualityComparer Default = new SymbolEqualityComparer();
 
        private SymbolEqualityComparer()
        {
        }
 
        public bool Equals(ISymbol x, ISymbol y)
        {
            throw new System.NotImplementedException();
        }
 
        public int GetHashCode(ISymbol obj)
        {
            throw new System.NotImplementedException();
        }
    }
}";
 
        [Theory]
        [InlineData(nameof(ISymbol))]
        [InlineData(nameof(INamedTypeSymbol))]
        public async Task CompareTwoSymbolsEquals_CSharpAsync(string symbolType)
        {
            var source = $@"
using Microsoft.CodeAnalysis;
class TestClass {{
    bool Method({symbolType} x, {symbolType} y) {{
        return [|x == y|];
    }}
}}
";
            var fixedSource = $@"
using Microsoft.CodeAnalysis;
class TestClass {{
    bool Method({symbolType} x, {symbolType} y) {{
        return SymbolEqualityComparer.Default.Equals(x, y);
    }}
}}
";
            await new VerifyCS.Test
            {
                TestState = { Sources = { source, SymbolEqualityComparerStubCSharp } },
                FixedState = { Sources = { fixedSource, SymbolEqualityComparerStubCSharp } },
            }.RunAsync();
        }
 
        [Theory]
        [InlineData(nameof(ISymbol))]
        [InlineData(nameof(INamedTypeSymbol))]
        public async Task CompareTwoSymbolsEquals_NoComparer_CSharpAsync(string symbolType)
        {
            var source = $@"
using Microsoft.CodeAnalysis;
class TestClass {{
    bool Method({symbolType} x, {symbolType} y) {{
        return [|x == y|];
    }}
}}
";
            var fixedSource = $@"
using Microsoft.CodeAnalysis;
class TestClass {{
    bool Method({symbolType} x, {symbolType} y) {{
        return Equals(x, y);
    }}
}}
";
            await VerifyCS.VerifyCodeFixAsync(source, fixedSource);
        }
 
        [Theory]
        [WorkItem(2335, "https://github.com/dotnet/roslyn-analyzers/issues/2335")]
        [InlineData(nameof(ISymbol))]
        [InlineData(nameof(INamedTypeSymbol))]
        public async Task CompareTwoSymbolsByIdentity_CSharpAsync(string symbolType)
        {
            var source = $@"
using Microsoft.CodeAnalysis;
class TestClass {{
    bool Method1({symbolType} x, {symbolType} y) {{
        return (object)x == y;
    }}
    bool Method2({symbolType} x, {symbolType} y) {{
        return x == (object)y;
    }}
    bool Method3({symbolType} x, {symbolType} y) {{
        return (object)x == (object)y;
    }}
}}
";
 
            await VerifyCS.VerifyAnalyzerAsync(source);
        }
 
        [Fact]
        [WorkItem(2336, "https://github.com/dotnet/roslyn-analyzers/issues/2336")]
        public async Task CompareTwoSymbolImplementations_CSharpAsync()
        {
            var source = $@"
class TestClass {{
    bool Method(Symbol x, Symbol y) {{
        return x == y;
    }}
}}
";
 
            await new VerifyCS.Test
            {
                TestState = { Sources = { source, MinimalSymbolImplementationCSharp } },
            }.RunAsync();
        }
 
        [Theory]
        [WorkItem(2336, "https://github.com/dotnet/roslyn-analyzers/issues/2336")]
        [InlineData(nameof(ISymbol))]
        [InlineData(nameof(INamedTypeSymbol))]
        public async Task CompareSymbolImplementationWithInterface_CSharpAsync(string symbolType)
        {
            var source = $@"
using Microsoft.CodeAnalysis;
class TestClass {{
    bool Method(Symbol x, {symbolType} y) {{
        return [|x == y|];
    }}
}}
";
            var fixedSource = $@"
using Microsoft.CodeAnalysis;
class TestClass {{
    bool Method(Symbol x, {symbolType} y) {{
        return SymbolEqualityComparer.Default.Equals(x, y);
    }}
}}
";
 
            await new VerifyCS.Test
            {
                TestState = { Sources = { source, MinimalSymbolImplementationCSharp, SymbolEqualityComparerStubCSharp } },
                FixedState = { Sources = { fixedSource, MinimalSymbolImplementationCSharp, SymbolEqualityComparerStubCSharp } },
            }.RunAsync();
        }
 
        [Theory]
        [InlineData(nameof(ISymbol))]
        [InlineData(nameof(INamedTypeSymbol))]
        public async Task CompareSymbolImplementationWithInterface_NoComparer_CSharpAsync(string symbolType)
        {
            var source = $@"
using Microsoft.CodeAnalysis;
class TestClass {{
    bool Method(Symbol x, {symbolType} y) {{
        return [|x == y|];
    }}
}}
";
            var fixedSource = $@"
using Microsoft.CodeAnalysis;
class TestClass {{
    bool Method(Symbol x, {symbolType} y) {{
        return Equals(x, y);
    }}
}}
";
 
            await new VerifyCS.Test
            {
                TestState = { Sources = { source, MinimalSymbolImplementationCSharp } },
                FixedState = { Sources = { fixedSource, MinimalSymbolImplementationCSharp } },
            }.RunAsync();
        }
 
        [Theory]
        [CombinatorialData]
        public async Task CompareSymbolWithNull_CSharpAsync(
            [CombinatorialValues(nameof(ISymbol), nameof(INamedTypeSymbol))] string symbolType,
            [CombinatorialValues("==", "!=")] string @operator,
            [CombinatorialValues("null", "default", "default(ISymbol)")] string value)
        {
            var source = $@"
using Microsoft.CodeAnalysis;
class TestClass {{
    bool Method1({symbolType} x) {{
        return x {@operator} {value};
    }}
 
    bool Method2({symbolType} x) {{
        return {value} {@operator} x;
    }}
}}
";
 
            await VerifyCS.VerifyAnalyzerAsync(source);
        }
 
        [Theory]
        [InlineData(nameof(ISymbol))]
        [InlineData(nameof(INamedTypeSymbol))]
        public async Task CompareSymbolWithNullPattern_CSharpAsync(string symbolType)
        {
            var source = $@"
using Microsoft.CodeAnalysis;
class TestClass {{
    bool Method1({symbolType} x) {{
        return x is null;
    }}
}}
";
 
            await VerifyCS.VerifyAnalyzerAsync(source);
        }
 
        [Theory]
        [InlineData(nameof(ISymbol))]
        [InlineData(nameof(INamedTypeSymbol))]
        public async Task CompareTwoSymbolsEquals_VisualBasicAsync(string symbolType)
        {
            var source = $@"
Imports Microsoft.CodeAnalysis
Class TestClass
    Function Method(x As {symbolType}, y As {symbolType}) As Boolean
        Return [|x Is y|]
    End Function
End Class
";
            var fixedSource = $@"
Imports Microsoft.CodeAnalysis
Class TestClass
    Function Method(x As {symbolType}, y As {symbolType}) As Boolean
        Return SymbolEqualityComparer.Default.Equals(x, y)
    End Function
End Class
";
 
            await new VerifyVB.Test
            {
                TestState = { Sources = { source, SymbolEqualityComparerStubVisualBasic } },
                FixedState = { Sources = { fixedSource, SymbolEqualityComparerStubVisualBasic } },
            }.RunAsync();
        }
 
        [Theory]
        [InlineData(nameof(ISymbol))]
        [InlineData(nameof(INamedTypeSymbol))]
        public async Task CompareTwoSymbolsEquals_NoComparer_VisualBasicAsync(string symbolType)
        {
            var source = $@"
Imports Microsoft.CodeAnalysis
Class TestClass
    Function Method(x As {symbolType}, y As {symbolType}) As Boolean
        Return [|x Is y|]
    End Function
End Class
";
            var fixedSource = $@"
Imports Microsoft.CodeAnalysis
Class TestClass
    Function Method(x As {symbolType}, y As {symbolType}) As Boolean
        Return Equals(x, y)
    End Function
End Class
";
 
            await VerifyVB.VerifyCodeFixAsync(source, fixedSource);
        }
 
        [Theory]
        [WorkItem(2335, "https://github.com/dotnet/roslyn-analyzers/issues/2335")]
        [InlineData(nameof(ISymbol))]
        [InlineData(nameof(INamedTypeSymbol))]
        public async Task CompareTwoSymbolsByIdentity_VisualBasicAsync(string symbolType)
        {
            var source = $@"
Imports Microsoft.CodeAnalysis
Class TestClass
    Function Method(x As {symbolType}, y As {symbolType}) As Boolean
        Return DirectCast(x, Object) Is y
    End Function
End Class
";
 
            await VerifyVB.VerifyAnalyzerAsync(source);
        }
 
        [Theory]
        [WorkItem(2336, "https://github.com/dotnet/roslyn-analyzers/issues/2336")]
        [CombinatorialData]
        public async Task CompareTwoSymbolImplementations_VisualBasicAsync(
            [CombinatorialValues("Symbol", nameof(ISymbol), nameof(INamedTypeSymbol))] string symbolType,
            [CombinatorialValues("=", "<>", "Is", "IsNot")] string @operator)
        {
            var source = $@"
Imports Microsoft.CodeAnalysis
Class TestClass
    Function Method1(x As Symbol, y As {symbolType}) As Boolean
        Return x {@operator} y
    End Function
 
    Function Method2(x As Symbol, y As {symbolType}) As Boolean
        Return y {@operator} x
    End Function
End Class
";
 
            await new VerifyVB.Test
            {
                TestState = { Sources = { source, MinimalSymbolImplementationVisualBasic } },
            }.RunAsync();
        }
 
        [Theory]
        [CombinatorialData]
        public async Task CompareSymbolWithNull_VisualBasicAsync(
            [CombinatorialValues(nameof(ISymbol), nameof(INamedTypeSymbol))] string symbolType,
            [CombinatorialValues("Is", "IsNot")] string @operator)
        {
            var source = $@"
Imports Microsoft.CodeAnalysis
Class TestClass
    Function Method1(x As {symbolType}) As Boolean
        Return x {@operator} Nothing
    End Function
 
    Function Method2(x As {symbolType}) As Boolean
        Return Nothing {@operator} x
    End Function
End Class
";
 
            await VerifyVB.VerifyAnalyzerAsync(source);
        }
 
        [Theory]
        [CombinatorialData]
        public async Task CompareSymbolFromInstanceEquals_VisualBasicAsync(
            [CombinatorialValues(nameof(ISymbol), nameof(INamedTypeSymbol))] string symbolType,
            [CombinatorialValues("", "Not ")] string @operator)
        {
            var source = $@"
Imports Microsoft.CodeAnalysis
Class TestClass
    Sub Method1(x As {symbolType}, y As {symbolType})
        If {@operator}[|x.Equals(y)|] Then Exit Sub
    End Sub
End Class
";
 
            var fixedSource = $@"
Imports Microsoft.CodeAnalysis
Class TestClass
    Sub Method1(x As {symbolType}, y As {symbolType})
        If {@operator}SymbolEqualityComparer.Default.Equals(x, y) Then Exit Sub
    End Sub
End Class
";
 
            await new VerifyVB.Test
            {
                TestState = { Sources = { source, SymbolEqualityComparerStubVisualBasic } },
                FixedState = { Sources = { fixedSource, SymbolEqualityComparerStubVisualBasic } },
            }.RunAsync();
        }
 
        [Theory]
        [CombinatorialData]
        public async Task CompareSymbolFromInstanceEquals_CSharpAsync(
            [CombinatorialValues(nameof(ISymbol), nameof(INamedTypeSymbol))] string symbolType,
            [CombinatorialValues("", "!")] string @operator)
        {
            var source = $@"
using Microsoft.CodeAnalysis;
class TestClass
{{
    void Method1({symbolType} x , {symbolType} y)
    {{
        if ({@operator}[|x.Equals(y)|]) return;
    }}
}}
";
 
            var fixedSource = $@"
using Microsoft.CodeAnalysis;
class TestClass
{{
    void Method1({symbolType} x , {symbolType} y)
    {{
        if ({@operator}SymbolEqualityComparer.Default.Equals(x, y)) return;
    }}
}}
";
 
            await new VerifyCS.Test
            {
                TestState = { Sources = { source, SymbolEqualityComparerStubCSharp } },
                FixedState = { Sources = { fixedSource, SymbolEqualityComparerStubCSharp } },
            }.RunAsync();
        }
 
        [Fact]
        public async Task CompareSymbolFromInstanceEqualsWithConditionalAccess_VisualBasicAsync()
        {
            var source = @"
Imports Microsoft.CodeAnalysis
Class TestClass
    Sub Method1(x As ISymbol, y As ISymbol)
        If x?[|.Equals(y)|] Then Exit Sub
    End Sub
End Class
";
 
            var fixedSource = @"
Imports Microsoft.CodeAnalysis
Class TestClass
    Sub Method1(x As ISymbol, y As ISymbol)
        If SymbolEqualityComparer.Default.Equals(x, y) Then Exit Sub
    End Sub
End Class
";
 
            await new VerifyVB.Test
            {
                TestState = { Sources = { source, SymbolEqualityComparerStubVisualBasic } },
                FixedState = { Sources = { fixedSource, SymbolEqualityComparerStubVisualBasic } },
            }.RunAsync();
        }
 
        [Fact]
        public async Task CompareSymbolFromInstanceEqualsWithNullConditionalAccess_CSharpAsync()
        {
            var source = @"
using Microsoft.CodeAnalysis;
class TestClass
{
    void Method1(ISymbol x, ISymbol y)
    {
        if (x?[|.Equals(y)|] == true) return;
    }
}
";
 
            var fixedSource = @"
using Microsoft.CodeAnalysis;
class TestClass
{
    void Method1(ISymbol x, ISymbol y)
    {
        if (SymbolEqualityComparer.Default.Equals(x, y) == true) return;
    }
}
";
 
            await new VerifyCS.Test
            {
                TestState = { Sources = { source, SymbolEqualityComparerStubCSharp } },
                FixedState = { Sources = { fixedSource, SymbolEqualityComparerStubCSharp } },
            }.RunAsync();
        }
 
        [Fact]
        public async Task CompareSymbolFromInstanceEqualsWithChainConditionalAccess_VisualBasicAsync()
        {
            var source = @"
Imports Microsoft.CodeAnalysis
 
Class A
    Public b As B
End Class
 
Class B
    Public s As ISymbol
End Class
 
Class TestClass
    Sub Method1(a As A, b As B, s As ISymbol)
        If a?.b?.s?[|.Equals(s)|] Then Exit Sub
        If b?.s?[|.Equals(s)|] Then Exit Sub
    End Sub
End Class
";
 
            var fixedSource = @"
Imports Microsoft.CodeAnalysis
 
Class A
    Public b As B
End Class
 
Class B
    Public s As ISymbol
End Class
 
Class TestClass
    Sub Method1(a As A, b As B, s As ISymbol)
        If SymbolEqualityComparer.Default.Equals(a?.b?.s, s) Then Exit Sub
        If SymbolEqualityComparer.Default.Equals(b?.s, s) Then Exit Sub
    End Sub
End Class
";
 
            await new VerifyVB.Test
            {
                TestState = { Sources = { source, SymbolEqualityComparerStubVisualBasic } },
                FixedState = { Sources = { fixedSource, SymbolEqualityComparerStubVisualBasic } },
            }.RunAsync();
        }
 
        [Fact]
        public async Task CompareSymbolFromInstanceEqualsWithChainNullConditionalAccess_CSharpAsync()
        {
            var source = @"
using Microsoft.CodeAnalysis;
 
class A
{
    public B b;
}
 
class B
{
    public ISymbol s;
}
 
class TestClass
{
    void Method1(A a, B b, ISymbol s)
    {
        if (a?.b?.s?[|.Equals(s)|] == true) return;
        if (b?.s?[|.Equals(s)|] == true) return;
    }
}
";
 
            var fixedSource = @"
using Microsoft.CodeAnalysis;
 
class A
{
    public B b;
}
 
class B
{
    public ISymbol s;
}
 
class TestClass
{
    void Method1(A a, B b, ISymbol s)
    {
        if (SymbolEqualityComparer.Default.Equals(a?.b?.s, s) == true) return;
        if (SymbolEqualityComparer.Default.Equals(b?.s, s) == true) return;
    }
}
";
 
            await new VerifyCS.Test
            {
                TestState = { Sources = { source, SymbolEqualityComparerStubCSharp } },
                FixedState = { Sources = { fixedSource, SymbolEqualityComparerStubCSharp } },
            }.RunAsync();
        }
 
        [Fact]
        public async Task CompareSymbolFromInstanceEqualsWithChain_CSharpAsync()
        {
            var source = @"
using Microsoft.CodeAnalysis;
 
class A
{
    public B b;
    public B GetB() => null;
}
 
class B
{
    public ISymbol s;
    public ISymbol GetS() => null;
}
 
class TestClass
{
    void Method1(A a, ISymbol symbol)
    {
        if ([|a.b.s.Equals(symbol)|] == true) return;
        if ([|a.GetB().GetS().Equals(symbol)|] == true) return;
    }
}";
 
            var fixedSource = @"
using Microsoft.CodeAnalysis;
 
class A
{
    public B b;
    public B GetB() => null;
}
 
class B
{
    public ISymbol s;
    public ISymbol GetS() => null;
}
 
class TestClass
{
    void Method1(A a, ISymbol symbol)
    {
        if (SymbolEqualityComparer.Default.Equals(a.b.s, symbol) == true) return;
        if (SymbolEqualityComparer.Default.Equals(a.GetB().GetS(), symbol) == true) return;
    }
}";
 
            await new VerifyCS.Test
            {
                TestState = { Sources = { source, SymbolEqualityComparerStubCSharp } },
                FixedState = { Sources = { fixedSource, SymbolEqualityComparerStubCSharp } },
            }.RunAsync();
        }
 
        [Theory]
        [InlineData(nameof(ISymbol))]
        [InlineData(nameof(INamedTypeSymbol))]
        public async Task CompareSymbolImplementationWithInterface_EqualsComparison_CSharpAsync(string symbolType)
        {
            var source = $@"
using Microsoft.CodeAnalysis;
class TestClass {{
    bool Method(ISymbol x, {symbolType} y) {{
        return [|Equals(x, y)|];
    }}
}}
";
            var fixedSource = $@"
using Microsoft.CodeAnalysis;
class TestClass {{
    bool Method(ISymbol x, {symbolType} y) {{
        return SymbolEqualityComparer.Default.Equals(x, y);
    }}
}}
";
 
            await new VerifyCS.Test
            {
                TestState = { Sources = { source, SymbolEqualityComparerStubCSharp } },
                FixedState = { Sources = { fixedSource, SymbolEqualityComparerStubCSharp } },
            }.RunAsync();
        }
 
        [Fact, WorkItem(2493, "https://github.com/dotnet/roslyn-analyzers/issues/2493")]
        public async Task GetHashCode_DiagnosticAsync()
        {
            await VerifyCS.VerifyAnalyzerAsync(@"
using Microsoft.CodeAnalysis;
public class C
{
    public int M(ISymbol symbol, INamedTypeSymbol namedType)
    {
        return [|symbol.GetHashCode()|] + [|namedType.GetHashCode()|];
    }
}");
 
            await VerifyVB.VerifyAnalyzerAsync(@"
Imports Microsoft.CodeAnalysis
 
Public Class C
    Public Function M(ByVal symbol As ISymbol, ByVal namedType As INamedTypeSymbol) As Integer
        Return [|symbol.GetHashCode()|] + [|namedType.GetHashCode()|]
    End Function
End Class");
        }
 
        [Fact, WorkItem(2493, "https://github.com/dotnet/roslyn-analyzers/issues/2493")]
        public async Task CollectionConstructorsKnownToRequireComparer_DiagnosticAsync()
        {
            await new VerifyCS.Test
            {
                TestState =
                {
                    ReferenceAssemblies = CreateNetCoreReferenceAssemblies(),
                    Sources =
                    {
                        @"
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
 
public class C
{
    public void MethodWithDiagnostics(IEnumerable<ISymbol> symbols)
    {
        var kvps = symbols.Select(s => new KeyValuePair<ISymbol, int>(s, 0));
 
        [|new Dictionary<ISymbol, int>()|];
        [|new Dictionary<ISymbol, int>(42)|];
        [|new Dictionary<ISymbol, int>(capacity: 42)|];
        [|new Dictionary<ISymbol, int>(kvps)|];
 
        [|new HashSet<ISymbol>()|];
        [|new HashSet<ISymbol>(42)|];
        [|new HashSet<ISymbol>(symbols)|];
 
        [|new ConcurrentDictionary<ISymbol, int>()|];
        [|new ConcurrentDictionary<ISymbol, int>(kvps)|];
        [|new ConcurrentDictionary<ISymbol, int>(1, 42)|];
    }
 
    public void MethodWithoutDiagnostics()
    {
        new Dictionary<int, ISymbol>();
        new HashSet<string>();
        new ConcurrentDictionary<int, ISymbol>();
 
        new Dictionary<ISymbol, int>(SymbolEqualityComparer.Default);
    }
}",
                        SymbolEqualityComparerStubCSharp,
                    },
                },
                FixedState =
                {
                    Sources =
                    {
                        @"
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
 
public class C
{
    public void MethodWithDiagnostics(IEnumerable<ISymbol> symbols)
    {
        var kvps = symbols.Select(s => new KeyValuePair<ISymbol, int>(s, 0));
 
        new Dictionary<ISymbol, int>(SymbolEqualityComparer.Default);
        new Dictionary<ISymbol, int>(42, SymbolEqualityComparer.Default);
        new Dictionary<ISymbol, int>(capacity: 42, SymbolEqualityComparer.Default);
        new Dictionary<ISymbol, int>(kvps, SymbolEqualityComparer.Default);
 
        new HashSet<ISymbol>(SymbolEqualityComparer.Default);
        new HashSet<ISymbol>(42, SymbolEqualityComparer.Default);
        new HashSet<ISymbol>(symbols, SymbolEqualityComparer.Default);
 
        new ConcurrentDictionary<ISymbol, int>(SymbolEqualityComparer.Default);
        new ConcurrentDictionary<ISymbol, int>(kvps, SymbolEqualityComparer.Default);
        new ConcurrentDictionary<ISymbol, int>(1, 42, SymbolEqualityComparer.Default);
    }
 
    public void MethodWithoutDiagnostics()
    {
        new Dictionary<int, ISymbol>();
        new HashSet<string>();
        new ConcurrentDictionary<int, ISymbol>();
 
        new Dictionary<ISymbol, int>(SymbolEqualityComparer.Default);
    }
}",
                        SymbolEqualityComparerStubCSharp,
                    }
                }
            }.RunAsync();
 
            await new VerifyVB.Test
            {
                TestState =
                {
                    ReferenceAssemblies = CreateNetCoreReferenceAssemblies(),
                    Sources =
                    {
                        @"
Imports System.Collections.Concurrent
Imports System.Collections.Generic
Imports System.Linq
Imports Microsoft.CodeAnalysis
 
Public Class C
    Public Sub MethodWithDiagnostics(symbols As IEnumerable(Of ISymbol))
        Dim kvps = symbols.[Select](Function(s) New KeyValuePair(Of ISymbol, Integer)(s, 0))
 
        Dim x11 = [|New Dictionary(Of ISymbol, Integer)()|]
        Dim x12 = [|New Dictionary(Of ISymbol, Integer)(42)|]
        Dim x13 = [|New Dictionary(Of ISymbol, Integer)(kvps)|]
 
        Dim x21 = [|New HashSet(Of ISymbol)()|]
        Dim x22 = [|New HashSet(Of ISymbol)(42)|]
        Dim x23 = [|New HashSet(Of ISymbol)(symbols)|]
 
        Dim x31 = [|New ConcurrentDictionary(Of ISymbol, Integer)()|]
        Dim x32 = [|New ConcurrentDictionary(Of ISymbol, Integer)(kvps)|]
        Dim x33 = [|New ConcurrentDictionary(Of ISymbol, Integer)(1, 42)|]
    End Sub
 
    Public Sub MethodWithoutDiagnostics()
        Dim x1 = New Dictionary(Of Integer, ISymbol)()
        Dim x2 = New HashSet(Of String)()
        Dim x3 = New ConcurrentDictionary(Of Integer, ISymbol)()
 
        Dim x4 = New Dictionary(Of ISymbol, Integer)(SymbolEqualityComparer.Default)
    End Sub
End Class",
                        SymbolEqualityComparerStubVisualBasic,
                    },
                },
                FixedState =
                {
                    Sources =
                    {
                        @"
Imports System.Collections.Concurrent
Imports System.Collections.Generic
Imports System.Linq
Imports Microsoft.CodeAnalysis
 
Public Class C
    Public Sub MethodWithDiagnostics(symbols As IEnumerable(Of ISymbol))
        Dim kvps = symbols.[Select](Function(s) New KeyValuePair(Of ISymbol, Integer)(s, 0))
 
        Dim x11 = New Dictionary(Of ISymbol, Integer)(SymbolEqualityComparer.Default)
        Dim x12 = New Dictionary(Of ISymbol, Integer)(42, SymbolEqualityComparer.Default)
        Dim x13 = New Dictionary(Of ISymbol, Integer)(kvps, SymbolEqualityComparer.Default)
 
        Dim x21 = New HashSet(Of ISymbol)(SymbolEqualityComparer.Default)
        Dim x22 = New HashSet(Of ISymbol)(42, SymbolEqualityComparer.Default)
        Dim x23 = New HashSet(Of ISymbol)(symbols, SymbolEqualityComparer.Default)
 
        Dim x31 = New ConcurrentDictionary(Of ISymbol, Integer)(SymbolEqualityComparer.Default)
        Dim x32 = New ConcurrentDictionary(Of ISymbol, Integer)(kvps, SymbolEqualityComparer.Default)
        Dim x33 = New ConcurrentDictionary(Of ISymbol, Integer)(1, 42, SymbolEqualityComparer.Default)
    End Sub
 
    Public Sub MethodWithoutDiagnostics()
        Dim x1 = New Dictionary(Of Integer, ISymbol)()
        Dim x2 = New HashSet(Of String)()
        Dim x3 = New ConcurrentDictionary(Of Integer, ISymbol)()
 
        Dim x4 = New Dictionary(Of ISymbol, Integer)(SymbolEqualityComparer.Default)
    End Sub
End Class",
                        SymbolEqualityComparerStubVisualBasic,
                    },
                }
            }.RunAsync();
        }
 
        [Fact, WorkItem(2493, "https://github.com/dotnet/roslyn-analyzers/issues/2493")]
        public async Task CollectionMethodsKnownToRequireComparer_DiagnosticAsync()
        {
            await new VerifyCS.Test
            {
                TestState =
                {
                    Sources =
                    {
                        @"
using System;
using System.Collections.Immutable;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
public class C
{
    public void MethodWithDiagnostics(IEnumerable<KeyValuePair<ISymbol, int>> kvps, IEnumerable<ISymbol> symbols, IEnumerable<ISymbol> symbols2, ISymbol symbol)
    {
        [|ImmutableHashSet.Create<ISymbol>()|];
        [|ImmutableHashSet.CreateBuilder<ISymbol>()|];
        [|ImmutableHashSet.CreateRange(symbols)|];
        [|symbols.ToImmutableHashSet()|];
 
        [|ImmutableDictionary.Create<ISymbol, int>()|];
        [|ImmutableDictionary.CreateBuilder<ISymbol, int>()|];
        [|ImmutableDictionary.CreateRange(kvps)|];
        [|kvps.ToImmutableDictionary()|];
 
        [|symbols.Contains(symbol)|];
        [|symbols.Distinct()|];
        [|symbols.GroupBy(x => x)|];
        [|symbols.GroupJoin(symbols2, x => x, x => x, (x, y) => x)|];
        [|symbols.Intersect(symbols2)|];
        [|symbols.Join(symbols2, x => x, x => x, (x, y) => x)|];
        [|symbols.SequenceEqual(symbols2)|];
        [|symbols.ToDictionary(x => x)|];
        [|symbols.ToLookup(x => x)|];
        [|symbols.Union(symbols2)|];
 
        [|ImmutableHashSet.ToImmutableHashSet(symbols)|];
        symbols?[|.ToImmutableHashSet()|];
    }
 
    public void MethodWithoutDiagnostics(IEnumerable<KeyValuePair<int, ISymbol>> kvps, IEnumerable<int> integers, int integer)
    {
        ImmutableHashSet.Create<int>();
        ImmutableHashSet.CreateBuilder<int>();
        ImmutableHashSet.CreateRange(integers);
        integers.ToImmutableHashSet();
 
        ImmutableDictionary.Create<int, ISymbol>();
        ImmutableDictionary.CreateBuilder<int, ISymbol>();
        ImmutableDictionary.CreateRange(kvps);
        kvps.ToImmutableDictionary();
 
        integers.Contains(integer);
        integers.Distinct();
        integers.GroupBy(x => x);
        integers.GroupJoin(integers, x => x, x => x, (x, y) => x);
        integers.Intersect(integers);
        integers.Join(integers, x => x, x => x, (x, y) => x);
        integers.SequenceEqual(integers);
        integers.ToDictionary(x => x);
        integers.ToLookup(x => x);
        integers.Union(integers);
    }
}",
                        SymbolEqualityComparerStubCSharp,
                    },
                },
                FixedState =
                {
                    Sources =
                    {
                        @"
using System;
using System.Collections.Immutable;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
public class C
{
    public void MethodWithDiagnostics(IEnumerable<KeyValuePair<ISymbol, int>> kvps, IEnumerable<ISymbol> symbols, IEnumerable<ISymbol> symbols2, ISymbol symbol)
    {
        ImmutableHashSet.Create<ISymbol>(SymbolEqualityComparer.Default);
        ImmutableHashSet.CreateBuilder<ISymbol>(SymbolEqualityComparer.Default);
        ImmutableHashSet.CreateRange(SymbolEqualityComparer.Default, symbols);
        symbols.ToImmutableHashSet(SymbolEqualityComparer.Default);
 
        ImmutableDictionary.Create<ISymbol, int>(SymbolEqualityComparer.Default);
        ImmutableDictionary.CreateBuilder<ISymbol, int>(SymbolEqualityComparer.Default);
        ImmutableDictionary.CreateRange(SymbolEqualityComparer.Default, kvps);
        kvps.ToImmutableDictionary(SymbolEqualityComparer.Default);
 
        symbols.Contains(symbol, SymbolEqualityComparer.Default);
        symbols.Distinct(SymbolEqualityComparer.Default);
        symbols.GroupBy(x => x, SymbolEqualityComparer.Default);
        symbols.GroupJoin(symbols2, x => x, x => x, (x, y) => x, SymbolEqualityComparer.Default);
        symbols.Intersect(symbols2, SymbolEqualityComparer.Default);
        symbols.Join(symbols2, x => x, x => x, (x, y) => x, SymbolEqualityComparer.Default);
        symbols.SequenceEqual(symbols2, SymbolEqualityComparer.Default);
        symbols.ToDictionary(x => x, SymbolEqualityComparer.Default);
        symbols.ToLookup(x => x, SymbolEqualityComparer.Default);
        symbols.Union(symbols2, SymbolEqualityComparer.Default);
 
        ImmutableHashSet.ToImmutableHashSet(symbols, SymbolEqualityComparer.Default);
        symbols?.ToImmutableHashSet(SymbolEqualityComparer.Default);
    }
 
    public void MethodWithoutDiagnostics(IEnumerable<KeyValuePair<int, ISymbol>> kvps, IEnumerable<int> integers, int integer)
    {
        ImmutableHashSet.Create<int>();
        ImmutableHashSet.CreateBuilder<int>();
        ImmutableHashSet.CreateRange(integers);
        integers.ToImmutableHashSet();
 
        ImmutableDictionary.Create<int, ISymbol>();
        ImmutableDictionary.CreateBuilder<int, ISymbol>();
        ImmutableDictionary.CreateRange(kvps);
        kvps.ToImmutableDictionary();
 
        integers.Contains(integer);
        integers.Distinct();
        integers.GroupBy(x => x);
        integers.GroupJoin(integers, x => x, x => x, (x, y) => x);
        integers.Intersect(integers);
        integers.Join(integers, x => x, x => x, (x, y) => x);
        integers.SequenceEqual(integers);
        integers.ToDictionary(x => x);
        integers.ToLookup(x => x);
        integers.Union(integers);
    }
}",
                        SymbolEqualityComparerStubCSharp,
                    },
                }
            }.RunAsync();
 
            await new VerifyVB.Test
            {
                TestState =
                {
                    Sources =
                    {
                        @"
Imports System
Imports System.Collections.Immutable
Imports System.Collections.Generic
Imports System.Linq
Imports Microsoft.CodeAnalysis
 
Public Class C
    Public Sub MethodWithDiagnostics(kvps As IEnumerable(Of KeyValuePair(Of ISymbol, Integer)), symbols As IEnumerable(Of ISymbol), symbols2 As IEnumerable(Of ISymbol), symbol As ISymbol)
        Dim x1 = [|ImmutableHashSet.Create(Of ISymbol)()|]
        Dim x2 = [|ImmutableHashSet.CreateBuilder(Of ISymbol)()|]
        Dim x3 = [|ImmutableHashSet.CreateRange(symbols)|]
        Dim x4 = [|symbols.ToImmutableHashSet()|]
 
        Dim x5 = [|ImmutableDictionary.Create(Of ISymbol, Integer)()|]
        Dim x6 = [|ImmutableDictionary.CreateBuilder(Of ISymbol, Integer)()|]
        Dim x7 = [|ImmutableDictionary.CreateRange(kvps)|]
        Dim x8 = [|kvps.ToImmutableDictionary()|]
 
        Dim x9 = [|symbols.Contains(symbol)|]
        Dim x10 = [|symbols.Distinct()|]
        Dim x11 = [|symbols.GroupBy(Function(x) x)|]
        Dim x12 = [|symbols.GroupJoin(symbols2, Function(x) x, Function(x) x, Function(x, y) x)|]
        Dim x13 = [|symbols.Intersect(symbols2)|]
        Dim x14 = [|symbols.Join(symbols2, Function(x) x, Function(x) x, Function(x, y) x)|]
        Dim x15 = [|symbols.SequenceEqual(symbols2)|]
        Dim x16 = [|symbols.ToDictionary(Function(x) x)|]
        Dim x17 = [|symbols.ToLookup(Function(x) x)|]
        Dim x18 = [|symbols.Union(symbols2)|]
 
        Dim x19 = [|ImmutableHashSet.ToImmutableHashSet(symbols)|]
    End Sub
 
    Public Sub MethodWithoutDiagnostics(kvps As IEnumerable(Of KeyValuePair(Of Integer, ISymbol)), integers As IEnumerable(Of Integer), i As Integer)
        Dim x1 = ImmutableHashSet.Create(Of Integer)()
        Dim x2 = ImmutableHashSet.CreateBuilder(Of Integer)()
        Dim x3 = ImmutableHashSet.CreateRange(integers)
        Dim x4 = integers.ToImmutableHashSet()
 
        Dim x5 = ImmutableDictionary.Create(Of Integer, ISymbol)()
        Dim x6 = ImmutableDictionary.CreateBuilder(Of Integer, ISymbol)()
        Dim x7 = ImmutableDictionary.CreateRange(kvps)
        Dim x8 = kvps.ToImmutableDictionary()
 
        Dim x9 = integers.Contains(i)
        Dim x10 = integers.Distinct()
        Dim x11 = integers.GroupBy(Function(x) x)
        Dim x12 = integers.GroupJoin(integers, Function(x) x, Function(x) x, Function(x, y) x)
        Dim x13 = integers.Intersect(integers)
        Dim x14 = integers.Join(integers, Function(x) x, Function(x) x, Function(x, y) x)
        Dim x15 = integers.SequenceEqual(integers)
        Dim x16 = integers.ToDictionary(Function(x) x)
        Dim x17 = integers.ToLookup(Function(x) x)
        Dim x18 = integers.Union(integers)
    End Sub
End Class",
                        SymbolEqualityComparerStubVisualBasic,
                    },
                },
                FixedState =
                {
                    Sources =
                    {
                        @"
Imports System
Imports System.Collections.Immutable
Imports System.Collections.Generic
Imports System.Linq
Imports Microsoft.CodeAnalysis
 
Public Class C
    Public Sub MethodWithDiagnostics(kvps As IEnumerable(Of KeyValuePair(Of ISymbol, Integer)), symbols As IEnumerable(Of ISymbol), symbols2 As IEnumerable(Of ISymbol), symbol As ISymbol)
        Dim x1 = ImmutableHashSet.Create(Of ISymbol)(SymbolEqualityComparer.Default)
        Dim x2 = ImmutableHashSet.CreateBuilder(Of ISymbol)(SymbolEqualityComparer.Default)
        Dim x3 = ImmutableHashSet.CreateRange(SymbolEqualityComparer.Default, symbols)
        Dim x4 = symbols.ToImmutableHashSet(SymbolEqualityComparer.Default)
 
        Dim x5 = ImmutableDictionary.Create(Of ISymbol, Integer)(SymbolEqualityComparer.Default)
        Dim x6 = ImmutableDictionary.CreateBuilder(Of ISymbol, Integer)(SymbolEqualityComparer.Default)
        Dim x7 = ImmutableDictionary.CreateRange(SymbolEqualityComparer.Default, kvps)
        Dim x8 = kvps.ToImmutableDictionary(SymbolEqualityComparer.Default)
 
        Dim x9 = symbols.Contains(symbol, SymbolEqualityComparer.Default)
        Dim x10 = symbols.Distinct(SymbolEqualityComparer.Default)
        Dim x11 = symbols.GroupBy(Function(x) x, SymbolEqualityComparer.Default)
        Dim x12 = symbols.GroupJoin(symbols2, Function(x) x, Function(x) x, Function(x, y) x, SymbolEqualityComparer.Default)
        Dim x13 = symbols.Intersect(symbols2, SymbolEqualityComparer.Default)
        Dim x14 = symbols.Join(symbols2, Function(x) x, Function(x) x, Function(x, y) x, SymbolEqualityComparer.Default)
        Dim x15 = symbols.SequenceEqual(symbols2, SymbolEqualityComparer.Default)
        Dim x16 = symbols.ToDictionary(Function(x) x, SymbolEqualityComparer.Default)
        Dim x17 = symbols.ToLookup(Function(x) x, SymbolEqualityComparer.Default)
        Dim x18 = symbols.Union(symbols2, SymbolEqualityComparer.Default)
 
        Dim x19 = ImmutableHashSet.ToImmutableHashSet(symbols, SymbolEqualityComparer.Default)
    End Sub
 
    Public Sub MethodWithoutDiagnostics(kvps As IEnumerable(Of KeyValuePair(Of Integer, ISymbol)), integers As IEnumerable(Of Integer), i As Integer)
        Dim x1 = ImmutableHashSet.Create(Of Integer)()
        Dim x2 = ImmutableHashSet.CreateBuilder(Of Integer)()
        Dim x3 = ImmutableHashSet.CreateRange(integers)
        Dim x4 = integers.ToImmutableHashSet()
 
        Dim x5 = ImmutableDictionary.Create(Of Integer, ISymbol)()
        Dim x6 = ImmutableDictionary.CreateBuilder(Of Integer, ISymbol)()
        Dim x7 = ImmutableDictionary.CreateRange(kvps)
        Dim x8 = kvps.ToImmutableDictionary()
 
        Dim x9 = integers.Contains(i)
        Dim x10 = integers.Distinct()
        Dim x11 = integers.GroupBy(Function(x) x)
        Dim x12 = integers.GroupJoin(integers, Function(x) x, Function(x) x, Function(x, y) x)
        Dim x13 = integers.Intersect(integers)
        Dim x14 = integers.Join(integers, Function(x) x, Function(x) x, Function(x, y) x)
        Dim x15 = integers.SequenceEqual(integers)
        Dim x16 = integers.ToDictionary(Function(x) x)
        Dim x17 = integers.ToLookup(Function(x) x)
        Dim x18 = integers.Union(integers)
    End Sub
End Class",
                        SymbolEqualityComparerStubVisualBasic,
                    },
                }
            }.RunAsync();
        }
 
        [Fact, WorkItem(4469, "https://github.com/dotnet/roslyn-analyzers/issues/4469")]
        public async Task RS1024_SymbolEqualityComparerDefaultAsync()
        {
            await new VerifyCS.Test
            {
                TestState =
                {
                    Sources =
                    {
                        @"
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
 
public class C
{
    public void M(IEnumerable<ISymbol> e, ISymbol symbol, INamedTypeSymbol type)
    {
        e.Contains(symbol, SymbolEqualityComparer.Default);
 
        var asyncMethods = type.GetMembers()
            .OfType<IMethodSymbol>()
            .Where(x => x.IsAsync)
            .ToLookup(x => x.ContainingType, x => x, SymbolEqualityComparer.Default);
    }
}",
                        SymbolEqualityComparerStubCSharp,
                    },
                },
            }.RunAsync();
        }
 
        [Fact]
        [WorkItem(4470, "https://github.com/dotnet/roslyn-analyzers/issues/4470")]
        [WorkItem(4568, "https://github.com/dotnet/roslyn-analyzers/issues/4568")]
        public async Task RS1024_InvocationArgumentTypeIsNullAsync()
        {
            await new VerifyCS.Test
            {
                TestState =
                {
                    Sources =
                    {
                        @"
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
 
public class C
{
    private readonly HashSet<ITypeSymbol> _types = new HashSet<ITypeSymbol>(SymbolEqualityComparer.Default);
}",
                        SymbolEqualityComparerStubCSharp,
                    },
                },
            }.RunAsync();
        }
 
        [Fact, WorkItem(4413, "https://github.com/dotnet/roslyn-analyzers/issues/4413")]
        public async Task RS1024_SourceCollectionIsSymbolButLambdaIsNotAsync()
        {
            await new VerifyCS.Test
            {
                TestState =
                {
                    Sources =
                    {
                        @"
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
 
public class C
{
    public void M1(IFieldSymbol[] fields)
    {
        var result = fields.ToLookup(f => f.Name);
    }
 
    public void M2(IEnumerable<IPropertySymbol> source, IEnumerable<IPropertySymbol> destination)
    {
        var result = source.Join(destination, p => (p.Name, p.Type.Name), p => (p.Name, p.Type.Name), (p1, p2) => p1.Name);
    }
}",
                        SymbolEqualityComparerStubCSharp,
                    },
                },
            }.RunAsync();
        }
 
        [Fact, WorkItem(4956, "https://github.com/dotnet/roslyn-analyzers/issues/4956")]
        public async Task RS1024_StringGetHashCodeAsync()
        {
            await new VerifyCS.Test
            {
                TestState =
                {
                    Sources =
                    {
@"
using System;
 
class C
{
    void M()
    {
        ReadOnlySpan<char> testROS = default;
        int hashCode = string.GetHashCode(testROS, StringComparison.OrdinalIgnoreCase);
    }
}"
                        , SymbolEqualityComparerStubCSharp
                    },
                    ReferenceAssemblies = CreateNetCoreReferenceAssemblies()
                }
            }.RunAsync();
        }
 
        [Fact]
        public async Task RS1024_GetHashCodeOnInt64Async()
        {
            var code = @"
using System;
using Microsoft.CodeAnalysis;
 
static class HashCodeHelper
{
    public static Int32 GetHashCode(Int64 x) => 0;
    public static Int32 GetHashCode(ISymbol symbol) => [|symbol.GetHashCode()|];
}
 
public class C
{
    public int GetHashCode(Int64 obj)
    {
        return HashCodeHelper.GetHashCode(obj);
    }
 
    public int GetHashCode(ISymbol symbol)
    {
        return HashCodeHelper.GetHashCode(symbol);
    }
 
    public int GetHashCode(object o)
    {
        if (o is ISymbol symbol)
        {
            return [|HashCode.Combine(symbol)|];
        }
 
        return HashCode.Combine(o);
    }
 
    public int GetHashCode(object o1, object o2)
    {
        if (o1 is ISymbol symbol1 && o2 is ISymbol symbol2)
        {
            return [|HashCode.Combine(symbol1, symbol2)|];
        }
 
        if (o1 is ISymbol symbolFirst)
        {
            return [|HashCode.Combine(symbolFirst, o2)|];
        }
 
        if (o2 is ISymbol symbolSecond)
        {
            return [|HashCode.Combine(o1, symbolSecond)|];
        }
 
        return HashCode.Combine(o1, o2);
    }
}";
 
            await new VerifyCS.Test
            {
                TestState =
                {
                    Sources =
                    {
                        code, SymbolEqualityComparerStubCSharp
                    },
                },
                FixedState =
                {
                    Sources =
                    {
                        code, SymbolEqualityComparerStubCSharp
                    },
                    MarkupHandling = Testing.MarkupMode.Allow
                },
                ReferenceAssemblies = CreateNetCoreReferenceAssemblies()
            }.RunAsync();
        }
 
        [Fact]
        [WorkItem(5715, "https://github.com/dotnet/roslyn-analyzers/issues/5715")]
        public async Task RS1024_CustomComparer_Instance_Is_InterfaceAsync()
        {
            var csCode = @"
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
 
public class C
{
    public void M(IEnumerable<ITypeSymbol> symbols)
    {
        _ = new HashSet<ISymbol>(SymbolNameComparer.Instance);
        _ = symbols.ToDictionary(s => s, s => s.ToDisplayString(), SymbolNameComparer.Instance);
        _ = symbols.ToDictionary(s => s, s => s.ToDisplayString(), SymbolEqualityComparer.Default);
    }
}
 
internal sealed class SymbolNameComparer : EqualityComparer<ISymbol>
{
    private SymbolNameComparer() { }
 
    internal static IEqualityComparer<ISymbol> Instance { get; } = new SymbolNameComparer();
 
    public override bool Equals(ISymbol x, ISymbol y) => true;
 
    public override int GetHashCode(ISymbol obj) => 0;
}
";
 
            await new VerifyCS.Test
            {
                TestCode = csCode,
                FixedCode = csCode,
                ReferenceAssemblies = CreateNetCoreReferenceAssemblies(),
 
            }.RunAsync();
 
            var vbCode = @"
Imports System.Collections.Generic
Imports System.Linq
Imports Microsoft.CodeAnalysis
 
Public Class C
 
    Public Sub M(symbols As IEnumerable(Of ITypeSymbol))
        Dim x As New HashSet(Of ISymbol)(SymbolNameComparer.Instance)
        Dim y = symbols.ToDictionary(Function(s) s, Function(s) s.ToDisplayString(), SymbolNameComparer.Instance)
        Dim z = symbols.ToDictionary(Function(s) s, Function(s) s.ToDisplayString(), SymbolEqualityComparer.Default)
    End Sub
End Class
 
Class SymbolNameComparer
    Inherits EqualityComparer(Of ISymbol)
 
    Private Sub New()
    End Sub
 
    Friend Shared Property Instance As IEqualityComparer(Of ISymbol) = New SymbolNameComparer()
 
    Public Overrides Function Equals(x As ISymbol, y As ISymbol) As Boolean
        Return True
    End Function
 
    Public Overrides Function GetHashCode(obj As ISymbol) As Integer
        Return 0
    End Function
End Class
";
 
            await new VerifyVB.Test
            {
                TestCode = vbCode,
                FixedCode = vbCode,
                ReferenceAssemblies = CreateNetCoreReferenceAssemblies(),
 
            }.RunAsync();
        }
 
        [Fact]
        [WorkItem(5715, "https://github.com/dotnet/roslyn-analyzers/issues/5715")]
        public async Task RS1024_CustomComparer_Instance_Is_TypeAsync()
        {
            var csCode = @"
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
 
public class C
{
    public void M(IEnumerable<ITypeSymbol> symbols)
    {
        _ = new HashSet<ISymbol>(SymbolNameComparer.Instance);
        _ = symbols.ToDictionary(s => s, s => s.ToDisplayString(), SymbolNameComparer.Instance);
        _ = symbols.ToDictionary(s => s, s => s.ToDisplayString(), SymbolEqualityComparer.Default);
    }
}
 
internal sealed class SymbolNameComparer : EqualityComparer<ISymbol>
{
    private SymbolNameComparer() { }
 
    internal static SymbolNameComparer Instance { get; } = new SymbolNameComparer();
 
    public override bool Equals(ISymbol x, ISymbol y) => true;
 
    public override int GetHashCode(ISymbol obj) => 0;
}
";
 
            await new VerifyCS.Test
            {
                TestCode = csCode,
                FixedCode = csCode,
                ReferenceAssemblies = CreateNetCoreReferenceAssemblies(),
 
            }.RunAsync();
 
            var vbCode = @"
Imports System.Collections.Generic
Imports System.Linq
Imports Microsoft.CodeAnalysis
 
Public Class C
    Public Sub M(symbols As IEnumerable(Of ITypeSymbol))
        Dim x As New HashSet(Of ISymbol)(SymbolNameComparer.Instance)
        Dim y = symbols.ToDictionary(Function(s) s, Function(s) s.ToDisplayString(), SymbolNameComparer.Instance)
        Dim z = symbols.ToDictionary(Function(s) s, Function(s) s.ToDisplayString(), SymbolEqualityComparer.Default)
    End Sub
End Class
 
Class SymbolNameComparer
    Inherits EqualityComparer(Of ISymbol)
 
    Private Sub New()
    End Sub
 
    Friend Shared Property Instance As SymbolNameComparer = New SymbolNameComparer()
 
    Public Overrides Function Equals(x As ISymbol, y As ISymbol) As Boolean
        Return True
    End Function
 
    Public Overrides Function GetHashCode(obj As ISymbol) As Integer
        Return 0
    End Function
End Class
";
 
            await new VerifyVB.Test
            {
                TestCode = vbCode,
                FixedCode = vbCode,
                ReferenceAssemblies = CreateNetCoreReferenceAssemblies(),
 
            }.RunAsync();
        }
 
        private static ReferenceAssemblies CreateNetCoreReferenceAssemblies()
            => ReferenceAssemblies.NetCore.NetCoreApp31.AddPackages(ImmutableArray.Create(
                new PackageIdentity("Microsoft.CodeAnalysis", "4.0.1"),
                new PackageIdentity("System.Runtime.Serialization.Formatters", "4.3.0"),
                new PackageIdentity("System.Configuration.ConfigurationManager", "4.7.0"),
                new PackageIdentity("System.Security.Cryptography.Cng", "4.7.0"),
                new PackageIdentity("System.Security.Permissions", "4.7.0"),
                new PackageIdentity("Microsoft.VisualBasic", "10.3.0")));
    }
}