File: Microsoft.CodeQuality.Analyzers\ApiDesignGuidelines\OperatorOverloadsHaveNamedAlternatesTests.Fixer.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 Xunit;
using VerifyCS = Test.Utilities.CSharpCodeFixVerifier<
    Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines.OperatorOverloadsHaveNamedAlternatesAnalyzer,
    Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines.OperatorOverloadsHaveNamedAlternatesFixer>;
using VerifyVB = Test.Utilities.VisualBasicCodeFixVerifier<
    Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines.OperatorOverloadsHaveNamedAlternatesAnalyzer,
    Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines.OperatorOverloadsHaveNamedAlternatesFixer>;
 
namespace Microsoft.CodeQuality.Analyzers.ApiDesignGuidelines.UnitTests
{
    public class OperatorOverloadsHaveNamedAlternatesFixerTests
    {
        #region C# tests
 
        [Fact]
        public async Task AddAlternateMethod_CSharpAsync()
        {
            await VerifyCS.VerifyCodeFixAsync(@"
public class C
{
    public static C operator +(C left, C right) { return new C(); }
}
",
                VerifyCS.Diagnostic(OperatorOverloadsHaveNamedAlternatesAnalyzer.DefaultRule).WithSpan(4, 30, 4, 31).WithArguments("Add", "op_Addition"),
@"
public class C
{
    public static C operator +(C left, C right) { return new C(); }
 
    public static C Add(C left, C right)
    {
        throw new System.NotImplementedException();
    }
}
");
        }
 
        [Fact]
        public async Task AddAlternateOfMultiples_CSharpAsync()
        {
            await VerifyCS.VerifyCodeFixAsync(@"
public class C
{
    public static C operator %(C left, C right) { return new C(); }
}
",
                VerifyCS.Diagnostic(OperatorOverloadsHaveNamedAlternatesAnalyzer.MultipleRule).WithSpan(4, 30, 4, 31).WithArguments("Mod", "Remainder", "op_Modulus"),
@"
public class C
{
    public static C operator %(C left, C right) { return new C(); }
 
    public static C Mod(C left, C right)
    {
        throw new System.NotImplementedException();
    }
}
");
        }
 
        [Fact]
        public async Task AddAlternateProperty_CSharpAsync()
        {
            await VerifyCS.VerifyCodeFixAsync(@"
public class C
{
    public static bool operator true(C item) { return true; }
    public static bool operator false(C item) { return false; }
}
",
                VerifyCS.Diagnostic(OperatorOverloadsHaveNamedAlternatesAnalyzer.PropertyRule).WithSpan(4, 33, 4, 37).WithArguments("IsTrue", "op_True"),
@"
public class C
{
    public static bool operator true(C item) { return true; }
    public static bool operator false(C item) { return false; }
 
    public bool IsTrue
    {
        get
        {
            throw new System.NotImplementedException();
        }
    }
}
");
        }
 
        [Fact]
        public async Task AddAlternateForConversion_CSharpAsync()
        {
            await VerifyCS.VerifyCodeFixAsync(@"
public class C
{
    public static implicit operator int(C item) { return 0; }
}
",
                VerifyCS.Diagnostic(OperatorOverloadsHaveNamedAlternatesAnalyzer.MultipleRule).WithSpan(4, 37, 4, 40).WithArguments("ToInt32", "FromC", "op_Implicit"),
@"
public class C
{
    public static implicit operator int(C item) { return 0; }
 
    public int ToInt32()
    {
        throw new System.NotImplementedException();
    }
}
");
        }
 
        [Fact]
        public async Task AddAlternateForCompare_CSharpAsync()
        {
            await VerifyCS.VerifyCodeFixAsync(@"
public class C
{
    public static bool operator {|CS0216:<|}(C left, C right) { return true; }   // error CS0216: The operator requires a matching operator '>' to also be defined
}
",
                VerifyCS.Diagnostic(OperatorOverloadsHaveNamedAlternatesAnalyzer.MultipleRule).WithSpan(4, 33, 4, 34).WithArguments("CompareTo", "Compare", "op_LessThan"),
@"
public class C
{
    public static bool operator {|CS0216:<|}(C left, C right) { return true; }   // error CS0216: The operator requires a matching operator '>' to also be defined
 
    public int CompareTo(C other)
    {
        if (ReferenceEquals(other, null))
        {
            return 1;
        }
 
        throw new System.NotImplementedException();
    }
}
");
        }
 
        [Fact]
        public async Task AddAlternateForStructCompare_CSharpAsync()
        {
            await VerifyCS.VerifyCodeFixAsync(@"
public struct C
{
    public static bool operator {|CS0216:<|}(C left, C right) { return true; }   // error CS0216: The operator requires a matching operator '>' to also be defined
}
",
                VerifyCS.Diagnostic(OperatorOverloadsHaveNamedAlternatesAnalyzer.MultipleRule).WithSpan(4, 33, 4, 34).WithArguments("CompareTo", "Compare", "op_LessThan"),
@"
public struct C
{
    public static bool operator {|CS0216:<|}(C left, C right) { return true; }   // error CS0216: The operator requires a matching operator '>' to also be defined
 
    public int CompareTo(C other)
    {
        throw new System.NotImplementedException();
    }
}
");
        }
 
        [Fact]
        public async Task AddAlternateForIncrement_CSharpAsync()
        {
            await VerifyCS.VerifyCodeFixAsync(@"
public class C
{
    public static C operator ++(C item) { return new C(); }
}
",
                VerifyCS.Diagnostic(OperatorOverloadsHaveNamedAlternatesAnalyzer.DefaultRule).WithSpan(4, 30, 4, 32).WithArguments("Increment", "op_Increment"),
@"
public class C
{
    public static C operator ++(C item) { return new C(); }
 
    public static C Increment(C item)
    {
        throw new System.NotImplementedException();
    }
}
");
        }
 
        [Fact]
        public async Task FixImproperMethodVisibility_CSharpAsync()
        {
            await new VerifyCS.Test
            {
                TestCode = @"
public class C
{
    public static C operator +(C left, C right) { return new C(); }
    protected static C {|#0:Add|}(C left, C right) { return new C(); }
}
",
                ExpectedDiagnostics =
                {
                    VerifyCS.Diagnostic(OperatorOverloadsHaveNamedAlternatesAnalyzer.VisibilityRule).WithLocation(0).WithArguments("Add", "op_Addition"),
                },
                FixedCode = @"
public class C
{
    public static C operator +(C left, C right) { return new C(); }
    public static C Add(C left, C right) { return new C(); }
}
",
            }.RunAsync();
        }
 
        [Fact]
        public async Task FixImproperPropertyVisibility_CSharpAsync()
        {
            await new VerifyCS.Test
            {
                TestCode = @"
public class C
{
    public static bool operator true(C item) { return true; }
    public static bool operator false(C item) { return false; }
    bool {|#0:IsTrue|} => true;
}
",
                ExpectedDiagnostics =
                {
                    VerifyCS.Diagnostic(OperatorOverloadsHaveNamedAlternatesAnalyzer.VisibilityRule).WithLocation(0).WithArguments("IsTrue", "op_True"),
                },
                FixedCode = @"
public class C
{
    public static bool operator true(C item) { return true; }
    public static bool operator false(C item) { return false; }
    public bool IsTrue => true;
}
",
            }.RunAsync();
        }
 
        #endregion
 
        #region VB tests
 
        [Fact]
        public async Task AddAlternateMethod_BasicAsync()
        {
            await VerifyVB.VerifyCodeFixAsync(@"
Public Class C
    Public Shared Operator +(left As C, right As C) As C
        Return New C()
    End Operator
End Class
",
                VerifyVB.Diagnostic(OperatorOverloadsHaveNamedAlternatesAnalyzer.DefaultRule).WithSpan(3, 28, 3, 29).WithArguments("Add", "op_Addition"),
@"
Public Class C
    Public Shared Operator +(left As C, right As C) As C
        Return New C()
    End Operator
 
    Public Shared Function Add(left As C, right As C) As C
        Throw New System.NotImplementedException()
    End Function
End Class
");
        }
 
        [Fact]
        public async Task AddAlternateOfMultiples_BasicAsync()
        {
            await VerifyVB.VerifyCodeFixAsync(@"
Public Class C
    Public Shared Operator Mod(left As C, right As C) As C
        Return New C()
    End Operator
End Class
",
                VerifyVB.Diagnostic(OperatorOverloadsHaveNamedAlternatesAnalyzer.MultipleRule).WithSpan(3, 28, 3, 31).WithArguments("Mod", "Remainder", "op_Modulus"),
@"
Public Class C
    Public Shared Operator Mod(left As C, right As C) As C
        Return New C()
    End Operator
 
    Public Shared Function [Mod](left As C, right As C) As C
        Throw New System.NotImplementedException()
    End Function
End Class
");
        }
 
        [Fact]
        public async Task AddAlternateProperty_BasicAsync()
        {
            await VerifyVB.VerifyCodeFixAsync(@"
Public Class C
    Public Shared Operator IsTrue(item As C) As Boolean
        Return True
    End Operator
    Public Shared Operator IsFalse(item As C) As Boolean
        Return False
    End Operator
End Class
",
                VerifyVB.Diagnostic(OperatorOverloadsHaveNamedAlternatesAnalyzer.PropertyRule).WithSpan(3, 28, 3, 34).WithArguments("IsTrue", "op_True"),
@"
Public Class C
    Public Shared Operator IsTrue(item As C) As Boolean
        Return True
    End Operator
    Public Shared Operator IsFalse(item As C) As Boolean
        Return False
    End Operator
 
    Public ReadOnly Property IsTrue As Boolean
        Get
            Throw New System.NotImplementedException()
        End Get
    End Property
End Class
");
        }
 
        [Fact]
        public async Task AddAlternateForConversion_BasicAsync()
        {
            await VerifyVB.VerifyCodeFixAsync(@"
Public Class C
    Public Shared Widening Operator CType(ByVal item As C) As Integer
        Return 0
    End Operator
End Class
",
                VerifyVB.Diagnostic(OperatorOverloadsHaveNamedAlternatesAnalyzer.MultipleRule).WithSpan(3, 37, 3, 42).WithArguments("ToInt32", "FromC", "op_Implicit"),
@"
Public Class C
    Public Shared Widening Operator CType(ByVal item As C) As Integer
        Return 0
    End Operator
 
    Public Function ToInt32() As Integer
        Throw New System.NotImplementedException()
    End Function
End Class
");
        }
 
        [Fact]
        public async Task AddAlternateForCompare_BasicAsync()
        {
            await VerifyVB.VerifyCodeFixAsync(@"
Public Class C
    Public Shared Operator {|BC33033:<|}(left As C, right As C) As Boolean   ' error BC33033: Matching '>' operator is required
        Return True
    End Operator
End Class
",
                VerifyVB.Diagnostic(OperatorOverloadsHaveNamedAlternatesAnalyzer.MultipleRule).WithSpan(3, 28, 3, 29).WithArguments("CompareTo", "Compare", "op_LessThan"),
@"
Public Class C
    Public Shared Operator {|BC33033:<|}(left As C, right As C) As Boolean   ' error BC33033: Matching '>' operator is required
        Return True
    End Operator
 
    Public Function CompareTo(other As C) As Integer
        If ReferenceEquals(other, Nothing) Then
            Return 1
        End If
 
        Throw New System.NotImplementedException()
    End Function
End Class
");
        }
 
        [Fact]
        public async Task AddAlternateForStructCompare_BasicAsync()
        {
            await VerifyVB.VerifyCodeFixAsync(@"
Public Structure C
    Public Shared Operator {|BC33033:<|}(left As C, right As C) As Boolean   ' error BC33033: Matching '>' operator is required
        Return True
    End Operator
End Structure
",
                VerifyVB.Diagnostic(OperatorOverloadsHaveNamedAlternatesAnalyzer.MultipleRule).WithSpan(3, 28, 3, 29).WithArguments("CompareTo", "Compare", "op_LessThan"),
@"
Public Structure C
    Public Shared Operator {|BC33033:<|}(left As C, right As C) As Boolean   ' error BC33033: Matching '>' operator is required
        Return True
    End Operator
 
    Public Function CompareTo(other As C) As Integer
        Throw New System.NotImplementedException()
    End Function
End Structure
");
        }
 
        [Fact]
        public async Task FixImproperMethodVisibility_BasicAsync()
        {
            await new VerifyVB.Test
            {
                TestCode = @"
Public Class C
    Public Shared Operator +(left As C, right As C) As C
        Return New C()
    End Operator
 
    Protected Shared Function {|#0:Add|}(left As C, right As C) As C
        Return New C()
    End Function
End Class
",
                ExpectedDiagnostics =
                {
                    VerifyVB.Diagnostic(OperatorOverloadsHaveNamedAlternatesAnalyzer.VisibilityRule).WithLocation(0).WithArguments("Add", "op_Addition"),
                },
                FixedCode = @"
Public Class C
    Public Shared Operator +(left As C, right As C) As C
        Return New C()
    End Operator
 
    Public Shared Function Add(left As C, right As C) As C
        Return New C()
    End Function
End Class
",
            }.RunAsync();
        }
 
        [Fact]
        public async Task FixImproperPropertyVisibility_BasicAsync()
        {
            await new VerifyVB.Test
            {
                TestCode = @"
Public Class C
    Public Shared Operator IsTrue(item As C) As Boolean
        Return True
    End Operator
    Public Shared Operator IsFalse(item As C) As Boolean
        Return False
    End Operator
 
    Private ReadOnly Property {|#0:IsTrue|} As Boolean
        Get
            Return True
        End Get
    End Property
End Class
",
                ExpectedDiagnostics =
                {
                    VerifyVB.Diagnostic(OperatorOverloadsHaveNamedAlternatesAnalyzer.VisibilityRule).WithLocation(0).WithArguments("IsTrue", "op_True"),
                },
                FixedCode = @"
Public Class C
    Public Shared Operator IsTrue(item As C) As Boolean
        Return True
    End Operator
    Public Shared Operator IsFalse(item As C) As Boolean
        Return False
    End Operator
 
    Public ReadOnly Property IsTrue As Boolean
        Get
            Return True
        End Get
    End Property
End Class
",
            }.RunAsync();
        }
 
        #endregion
    }
}