File: Microsoft.CodeQuality.Analyzers\ApiDesignGuidelines\OverloadOperatorEqualsOnOverridingValueTypeEqualsTests.cs
Web Access
Project: ..\..\..\src\Microsoft.CodeAnalysis.NetAnalyzers\tests\Microsoft.CodeAnalysis.NetAnalyzers.UnitTests\Microsoft.CodeAnalysis.NetAnalyzers.UnitTests.csproj (Microsoft.CodeAnalysis.NetAnalyzers.UnitTests)
// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the MIT license.  See License.txt in the project root for license information.
 
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Testing;
using Test.Utilities;
using Xunit;
using VerifyCS = Test.Utilities.CSharpCodeFixVerifier<
    Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines.OverloadOperatorEqualsOnOverridingValueTypeEqualsAnalyzer,
    Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>;
using VerifyVB = Test.Utilities.VisualBasicCodeFixVerifier<
    Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines.OverloadOperatorEqualsOnOverridingValueTypeEqualsAnalyzer,
    Microsoft.CodeAnalysis.Testing.EmptyCodeFixProvider>;
 
namespace Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines.UnitTests
{
    public partial class OverloadOperatorEqualsOnOverridingValueTypeEqualsTests
    {
        [Fact]
        public async Task CA2231NoWarningCSharpAsync()
        {
            await VerifyCS.VerifyAnalyzerAsync(@"
    using System;
 
    // Non-value type
    public class A
    {    
        public override bool Equals(Object obj)
        {
            return true;
        }
    }
 
    // value type without overriding Equals
    public struct B
    {    
        public new bool Equals(Object obj)
        {
            return true;
        }
    }
");
        }
 
        [Fact]
        public async Task CA2231NoEqualsOperatorCSharpAsync()
        {
            await VerifyCS.VerifyAnalyzerAsync(@"
    using System;
 
    public struct A
    {
        public override bool Equals(Object obj)
        {
            return true;
        }
    }
",
            GetCA2231CSharpResultAt(4, 19));
        }
 
        [Fact, WorkItem(1432, "https://github.com/dotnet/roslyn-analyzers/issues/1432")]
        public async Task CA2231NoEqualsOperatorButNotExternallyVisibleCSharpAsync()
        {
            await VerifyCS.VerifyAnalyzerAsync(@"
    using System;
 
    struct A
    {
        public override bool Equals(Object obj)
        {
            return true;
        }
    }
 
    public class A2
    {
        private struct B
        {
            public override bool Equals(Object obj)
            {
                return true;
            }
        }
    }
");
        }
 
        [Fact]
        public async Task CA2231NoEqualsOperatorCSharpOutofScopeAsync()
        {
            await VerifyCS.VerifyAnalyzerAsync(@"
    using System;
 
    public struct [|A|]
    {
        public override bool Equals(Object obj)
        {
            return true;
        }
    }
 
    // value type without overriding Equals
    public struct B
    {    
        public new bool Equals(Object obj)
        {
            return true;
        }
    }
");
        }
 
        [Fact]
        public async Task CA2231CSharpInnerClassHasNoEqualsOperatorCSharpAsync()
        {
            await VerifyCS.VerifyAnalyzerAsync(@"
    using System;
 
    public struct A
    {
        public override bool Equals(Object obj)
        {
            return true;
        }
 
        public struct Aa
        {
            public override bool Equals(Object obj)
            {
                return true;
            }
        }
    }
",
            GetCA2231CSharpResultAt(4, 19),
            GetCA2231CSharpResultAt(11, 23));
        }
 
        [Fact]
        public async Task CA2231HasEqualsOperatorCSharpAsync()
        {
            await VerifyCS.VerifyAnalyzerAsync(@"
    using System;
 
    public struct A
    {
        public override bool Equals(Object obj)
        {
            return true;
        }
 
        public static bool operator ==(A a1, A a2)
        {
            return false;
        }
 
        public static bool operator !=(A a1, A a2)
        {
            return false;
        }
    }
");
        }
 
        [Fact]
        public async Task CA2231_CSharp_RefStruct_NoDiagnosticAsync()
        {
            await new VerifyCS.Test
            {
                TestCode = @"
public ref struct S
{
    public override bool Equals(object other)
    {
        return false;
    }
}
",
                LanguageVersion = LanguageVersion.CSharp8
            }.RunAsync();
        }
 
        [Fact]
        public async Task CA2231NoWarningBasicAsync()
        {
            await VerifyVB.VerifyAnalyzerAsync(@"
Imports System
 
Public Class A
    Public Overloads Overrides Function Equals(obj As Object) As Boolean
        Return True
    End Function
End Class
");
        }
 
        [Fact]
        public async Task CA2231NoEqualsOperatorBasicAsync()
        {
            await VerifyVB.VerifyAnalyzerAsync(@"
Imports System
 
Public Structure A
    Public Overloads Overrides Function Equals(obj As Object) As Boolean
        Return True
    End Function
End Structure
",
            GetCA2231BasicResultAt(4, 18));
        }
 
        [Fact, WorkItem(1432, "https://github.com/dotnet/roslyn-analyzers/issues/1432")]
        public async Task CA2231NoEqualsOperatorButNotExternallyVisibleBasicAsync()
        {
            await VerifyVB.VerifyAnalyzerAsync(@"
Imports System
 
Structure A
    Public Overloads Overrides Function Equals(obj As Object) As Boolean
        Return True
    End Function
End Structure
 
Public Class A2
    Private Structure B
        Public Overloads Overrides Function Equals(obj As Object) As Boolean
            Return True
        End Function
    End Structure
End Class
");
        }
 
        [Fact]
        public async Task CA2231NoEqualsOperatorBasicWithScopeAsync()
        {
            await VerifyVB.VerifyAnalyzerAsync(@"
Imports System
 
Public Class A
    Public Overloads Overrides Function Equals(obj As Object) As Boolean
        Return True
    End Function
End Class
 
Public Structure [|B|]
    Public Overloads Overrides Function Equals(obj As Object) As Boolean
        Return True
    End Function
End Structure
");
        }
 
        [Fact]
        public async Task CA2231BasicInnerClassHasNoEqualsOperatorBasicAsync()
        {
            await VerifyVB.VerifyAnalyzerAsync(@"
Imports System
 
Public Structure A
    Public Overloads Overrides Function Equals(obj As Object) As Boolean
        Return True
    End Function
 
    Public Structure Aa
        Public Overloads Overrides Function Equals(obj As Object) As Boolean
            Return True
        End Function
    End Structure
End Structure
",
            GetCA2231BasicResultAt(4, 18),
            GetCA2231BasicResultAt(9, 22));
        }
 
        [Fact]
        public async Task CA2231HasEqualsOperatorBasicAsync()
        {
            await VerifyVB.VerifyAnalyzerAsync(@"
Imports System
 
Public Structure A
    Public Overloads Overrides Function Equals(obj As Object) As Boolean
        Return True
    End Function
 
    Public Shared Operator =(left As A, right As A)
        Return True
    End Operator
 
    Public Shared Operator <>(left As A, right As A)
        Return True
    End Operator
End Structure
");
        }
 
        private static DiagnosticResult GetCA2231CSharpResultAt(int line, int column)
#pragma warning disable RS0030 // Do not use banned APIs
            => VerifyCS.Diagnostic()
                .WithLocation(line, column);
#pragma warning restore RS0030 // Do not use banned APIs
 
        private static DiagnosticResult GetCA2231BasicResultAt(int line, int column)
#pragma warning disable RS0030 // Do not use banned APIs
            => VerifyVB.Diagnostic()
                .WithLocation(line, column);
#pragma warning restore RS0030 // Do not use banned APIs
    }
}