diff --git a/src/FluentAssertions.Analyzers.Tests/Tips/SanityTests.cs b/src/FluentAssertions.Analyzers.Tests/Tips/SanityTests.cs index 340d7de4..8655eaad 100644 --- a/src/FluentAssertions.Analyzers.Tests/Tips/SanityTests.cs +++ b/src/FluentAssertions.Analyzers.Tests/Tips/SanityTests.cs @@ -1,5 +1,4 @@ using FluentAssertions.Analyzers.TestUtils; -using FluentAssertions.Analyzers.Xunit; using Microsoft.CodeAnalysis; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -316,8 +315,8 @@ public static void True(bool input) .WithPackageReferences(PackageReference.XunitAssert_2_5_1, PackageReference.FluentAssertions_6_12_0) .WithExpectedDiagnostics(new DiagnosticResult() { - Id = AssertTrueAnalyzer.DiagnosticId, - Message = AssertTrueAnalyzer.Message, + Id = AssertAnalyzer.XunitRule.Id, + Message = AssertAnalyzer.Message, Severity = DiagnosticSeverity.Info, Locations = new[] { new DiagnosticResultLocation("Test0.cs", 7, 9) } }) diff --git a/src/FluentAssertions.Analyzers.Tests/Tips/XunitTests.cs b/src/FluentAssertions.Analyzers.Tests/Tips/XunitTests.cs index 51b33dfe..c55fcd29 100644 --- a/src/FluentAssertions.Analyzers.Tests/Tips/XunitTests.cs +++ b/src/FluentAssertions.Analyzers.Tests/Tips/XunitTests.cs @@ -1,6 +1,5 @@ using Microsoft.CodeAnalysis; using Microsoft.VisualStudio.TestTools.UnitTesting; -using FluentAssertions.Analyzers.Xunit; using FluentAssertions.Analyzers.TestUtils; namespace FluentAssertions.Analyzers.Tests.Tips @@ -14,7 +13,7 @@ public class XunitTests [DataRow("Assert.True(bool.Parse(\"true\"));")] [DataRow("Assert.True(bool.Parse(\"true\"), \"because it's possible\");")] [Implemented] - public void AssertTrue_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic("bool actual", assertion); + public void AssertTrue_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic("bool actual", assertion); [DataTestMethod] [DataRow( @@ -37,7 +36,7 @@ public class XunitTests /* newAssertion: */ "(actual == false).Should().BeTrue();")] [Implemented] public void AssertTrue_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("bool actual", oldAssertion, newAssertion); + => VerifyCSharpFix("bool actual", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.False(actual);")] @@ -45,7 +44,7 @@ public void AssertTrue_TestCodeFix(string oldAssertion, string newAssertion) [DataRow("Assert.False(bool.Parse(\"false\"));")] [DataRow("Assert.False(bool.Parse(\"false\"), \"because it's possible\");")] [Implemented] - public void AssertFalse_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic("bool actual", assertion); + public void AssertFalse_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic("bool actual", assertion); [DataTestMethod] [DataRow( @@ -62,13 +61,13 @@ public void AssertTrue_TestCodeFix(string oldAssertion, string newAssertion) /* newAssertion: */ "bool.Parse(\"false\").Should().BeFalse(\"because it's possible\");")] [Implemented] public void AssertFalse_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("bool actual", oldAssertion, newAssertion); + => VerifyCSharpFix("bool actual", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.Same(expected, actual);")] [Implemented] - public void AssertSame_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic("object actual, object expected", assertion); + public void AssertSame_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic("object actual, object expected", assertion); [DataTestMethod] [DataRow( @@ -76,12 +75,12 @@ public void AssertFalse_TestCodeFix(string oldAssertion, string newAssertion) /* newAssertion: */ "actual.Should().BeSameAs(expected);")] [Implemented] public void AssertSame_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("object actual, object expected", oldAssertion, newAssertion); + => VerifyCSharpFix("object actual, object expected", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.NotSame(expected, actual);")] [Implemented] - public void AssertNotSame_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic("object actual, object expected", assertion); + public void AssertNotSame_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic("object actual, object expected", assertion); [DataTestMethod] [DataRow( @@ -89,14 +88,14 @@ public void AssertSame_TestCodeFix(string oldAssertion, string newAssertion) /* newAssertion: */ "actual.Should().NotBeSameAs(expected);")] [Implemented] public void AssertNotSame_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("object actual, object expected", oldAssertion, newAssertion); + => VerifyCSharpFix("object actual, object expected", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.Equal(expected, actual, tolerance);")] [DataRow("Assert.Equal(expected, actual, 0.6f);")] [Implemented] public void AssertFloatEqualWithTolerance_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("float actual, float expected, float tolerance", assertion); + VerifyCSharpDiagnostic("float actual, float expected, float tolerance", assertion); [DataTestMethod] [DataRow( @@ -107,14 +106,14 @@ public void AssertFloatEqualWithTolerance_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().BeApproximately(expected, 0.6f);")] [Implemented] public void AssertFloatEqualWithTolerance_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("float actual, float expected, float tolerance", oldAssertion, newAssertion); + => VerifyCSharpFix("float actual, float expected, float tolerance", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.Equal(expected, actual, tolerance);")] [DataRow("Assert.Equal(expected, actual, 0.6);")] [Implemented] public void AssertDoubleEqualWithTolerance_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("double actual, double expected, double tolerance", assertion); + VerifyCSharpDiagnostic("double actual, double expected, double tolerance", assertion); [DataTestMethod] [DataRow( @@ -125,14 +124,14 @@ public void AssertDoubleEqualWithTolerance_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().BeApproximately(expected, 0.6);")] [Implemented] public void AssertDoubleEqualWithTolerance_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("double actual, double expected, double tolerance", oldAssertion, newAssertion); + => VerifyCSharpFix("double actual, double expected, double tolerance", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.Equal(expected, actual, precision);")] [DataRow("Assert.Equal(expected, actual, 5);")] [Implemented] public void AssertDoubleEqualWithPrecision_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("double actual, double expected, int precision", assertion); + VerifyCSharpDiagnostic("double actual, double expected, int precision", assertion); // There is no corresponding API in FluentAssertions [DataTestMethod] @@ -150,14 +149,14 @@ public void AssertDoubleEqualWithPrecision_TestAnalyzer(string assertion) => /* newAssertion: */ "Assert.Equal(expected, actual, 5, MidpointRounding.ToEven);")] [Implemented] public void AssertDoubleEqualWithPrecision_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("double actual, double expected, int precision, MidpointRounding rounding", oldAssertion, newAssertion); + => VerifyCSharpFix("double actual, double expected, int precision, MidpointRounding rounding", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.Equal(expected, actual, precision);")] [DataRow("Assert.Equal(expected, actual, 5);")] [Implemented] public void AssertDecimalEqualWithPrecision_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("decimal actual, decimal expected, int precision", assertion); + VerifyCSharpDiagnostic("decimal actual, decimal expected, int precision", assertion); // There is no corresponding API in FluentAssertions [DataTestMethod] @@ -169,13 +168,13 @@ public void AssertDecimalEqualWithPrecision_TestAnalyzer(string assertion) => /* newAssertion: */ "Assert.Equal(expected, actual, 5);")] [Implemented] public void AssertDecimalEqualWithPrecision_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("decimal actual, decimal expected, int precision", oldAssertion, newAssertion); + => VerifyCSharpFix("decimal actual, decimal expected, int precision", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.Equal(expected, actual, precision);")] [DataRow("Assert.Equal(expected, actual, TimeSpan.FromSeconds(1));")] [Implemented] - public void AssertDateTimeEqual_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic("DateTime actual, DateTime expected, TimeSpan precision", assertion); + public void AssertDateTimeEqual_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic("DateTime actual, DateTime expected, TimeSpan precision", assertion); [DataTestMethod] [DataRow( @@ -186,14 +185,14 @@ public void AssertDecimalEqualWithPrecision_TestCodeFix(string oldAssertion, str /* newAssertion: */ "actual.Should().BeCloseTo(expected, TimeSpan.FromSeconds(1));")] [Implemented] public void AssertDateTimeEqual_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("DateTime actual, DateTime expected, TimeSpan precision", oldAssertion, newAssertion); + => VerifyCSharpFix("DateTime actual, DateTime expected, TimeSpan precision", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.Equal(expected, actual, comparer);")] [DataRow("Assert.Equal(expected, actual, ReferenceEqualityComparer.Instance);")] [Implemented] public void AssertObjectEqualWithComparer_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("object actual, object expected, IEqualityComparer comparer", assertion); + VerifyCSharpDiagnostic("object actual, object expected, IEqualityComparer comparer", assertion); [DataTestMethod] [DataRow( @@ -204,12 +203,12 @@ public void AssertObjectEqualWithComparer_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().BeEquivalentTo(expected, options => options.Using(ReferenceEqualityComparer.Instance));")] [Implemented] public void AssertObjectEqualWithComparer_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("object actual, object expected, IEqualityComparer comparer", oldAssertion, newAssertion); + => VerifyCSharpFix("object actual, object expected, IEqualityComparer comparer", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.Equal(expected, actual);")] [Implemented] - public void AssertObjectEqual_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic("object actual, object expected", assertion); + public void AssertObjectEqual_TestAnalyzer(string assertion) => VerifyCSharpDiagnostic("object actual, object expected", assertion); [DataTestMethod] [DataRow( @@ -217,13 +216,13 @@ public void AssertObjectEqualWithComparer_TestCodeFix(string oldAssertion, strin /* newAssertion: */ "actual.Should().Be(expected);")] [Implemented] public void AssertObjectEqual_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("object actual, object expected", oldAssertion, newAssertion); + => VerifyCSharpFix("object actual, object expected", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.Equal(expected, actual);")] [Implemented] public void AssertStringEqual_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("string actual, string expected", assertion); + VerifyCSharpDiagnostic("string actual, string expected", assertion); [DataTestMethod] [DataRow( @@ -231,13 +230,13 @@ public void AssertStringEqual_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().Be(expected);")] [Implemented] public void AssertStringEqual_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("string actual, string expected", oldAssertion, newAssertion); + => VerifyCSharpFix("string actual, string expected", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.StrictEqual(expected, actual);")] [Implemented] public void AssertStrictEqual_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("object actual, object expected", assertion); + VerifyCSharpDiagnostic("object actual, object expected", assertion); [DataTestMethod] [DataRow( @@ -245,14 +244,14 @@ public void AssertStrictEqual_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().Be(expected);")] [Implemented] public void AssertStrictEqual_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("object actual, object expected", oldAssertion, newAssertion); + => VerifyCSharpFix("object actual, object expected", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.NotEqual(expected, actual, precision);")] [DataRow("Assert.NotEqual(expected, actual, 5);")] [Implemented] public void AssertDoubleNotEqualWithPrecision_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("double actual, double expected, int precision", assertion); + VerifyCSharpDiagnostic("double actual, double expected, int precision", assertion); // There is no corresponding API in FluentAssertions [DataTestMethod] @@ -264,14 +263,14 @@ public void AssertDoubleNotEqualWithPrecision_TestAnalyzer(string assertion) => /* newAssertion: */ "Assert.NotEqual(expected, actual, 5);")] [Implemented] public void AssertDoubleNotEqualWithPrecision_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("double actual, double expected, int precision", oldAssertion, newAssertion); + => VerifyCSharpFix("double actual, double expected, int precision", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.NotEqual(expected, actual, precision);")] [DataRow("Assert.NotEqual(expected, actual, 5);")] [Implemented] public void AssertDecimalNotEqualWithPrecision_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("decimal actual, decimal expected, int precision", assertion); + VerifyCSharpDiagnostic("decimal actual, decimal expected, int precision", assertion); // There is no corresponding API in FluentAssertions [DataTestMethod] @@ -283,14 +282,14 @@ public void AssertDecimalNotEqualWithPrecision_TestAnalyzer(string assertion) => /* newAssertion: */ "Assert.NotEqual(expected, actual, 5);")] [Implemented] public void AssertDecimalNotEqualWithPrecision_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("decimal actual, decimal expected, int precision", oldAssertion, newAssertion); + => VerifyCSharpFix("decimal actual, decimal expected, int precision", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.NotEqual(expected, actual, comparer);")] [DataRow("Assert.NotEqual(expected, actual, ReferenceEqualityComparer.Instance);")] [Implemented] public void AssertObjectNotEqualWithComparer_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("object actual, object expected, IEqualityComparer comparer", assertion); + VerifyCSharpDiagnostic("object actual, object expected, IEqualityComparer comparer", assertion); [DataTestMethod] [DataRow( @@ -301,13 +300,13 @@ public void AssertObjectNotEqualWithComparer_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().NotBeEquivalentTo(expected, options => options.Using(ReferenceEqualityComparer.Instance));")] [Implemented] public void AssertObjectNotEqualWithComparer_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("object actual, object expected, IEqualityComparer comparer", oldAssertion, newAssertion); + => VerifyCSharpFix("object actual, object expected, IEqualityComparer comparer", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.NotEqual(expected, actual);")] [Implemented] public void AssertObjectNotEqual_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("object actual, object expected", assertion); + VerifyCSharpDiagnostic("object actual, object expected", assertion); [DataTestMethod] [DataRow( @@ -315,13 +314,13 @@ public void AssertObjectNotEqual_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().NotBe(expected);")] [Implemented] public void AssertObjectNotEqual_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("object actual, object expected", oldAssertion, newAssertion); + => VerifyCSharpFix("object actual, object expected", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.NotStrictEqual(expected, actual);")] [Implemented] public void AssertObjectNotStrictEqual_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("object actual, object expected", assertion); + VerifyCSharpDiagnostic("object actual, object expected", assertion); [DataTestMethod] [DataRow( @@ -329,13 +328,13 @@ public void AssertObjectNotStrictEqual_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().NotBe(expected);")] [Implemented] public void AssertObjectNotStrictEqual_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("object actual, object expected", oldAssertion, newAssertion); + => VerifyCSharpFix("object actual, object expected", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.Null(actual);")] [Implemented] public void AssertNull_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("object actual", assertion); + VerifyCSharpDiagnostic("object actual", assertion); [DataTestMethod] [DataRow( @@ -343,13 +342,13 @@ public void AssertNull_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().BeNull();")] [Implemented] public void AssertNull_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("object actual", oldAssertion, newAssertion); + => VerifyCSharpFix("object actual", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.NotNull(actual);")] [Implemented] public void AssertNotNull_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("object actual", assertion); + VerifyCSharpDiagnostic("object actual", assertion); [DataTestMethod] [DataRow( @@ -357,13 +356,13 @@ public void AssertNotNull_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().NotBeNull();")] [Implemented] public void AssertNotNull_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("object actual", oldAssertion, newAssertion); + => VerifyCSharpFix("object actual", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.Contains(expected, actual);")] [Implemented] public void AssertStringContains_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("string actual, string expected", assertion); + VerifyCSharpDiagnostic("string actual, string expected", assertion); [DataTestMethod] [DataRow( @@ -371,7 +370,7 @@ public void AssertStringContains_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().Contain(expected);")] [Implemented] public void AssertStringContains_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("string actual, string expected", oldAssertion, newAssertion); + => VerifyCSharpFix("string actual, string expected", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.Contains(expected, actual);", "ISet actual, string expected")] @@ -380,7 +379,7 @@ public void AssertStringContains_TestCodeFix(string oldAssertion, string newAsse [DataRow("Assert.Contains(expected, actual);", "ImmutableHashSet actual, string expected")] [Implemented] public void AssertSetContains_TestAnalyzer(string assertion, string arguments) => - VerifyCSharpDiagnostic(arguments, assertion); + VerifyCSharpDiagnostic(arguments, assertion); [DataTestMethod] [DataRow( @@ -401,13 +400,13 @@ public void AssertSetContains_TestAnalyzer(string assertion, string arguments) = /* arguments: */ "ImmutableHashSet actual, string expected")] [Implemented] public void AssertSetContains_TestCodeFix(string oldAssertion, string newAssertion, string arguments) - => VerifyCSharpFix(arguments, oldAssertion, newAssertion); + => VerifyCSharpFix(arguments, oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.DoesNotContain(expected, actual);")] [Implemented] public void AssertStringDoesNotContain_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("string actual, string expected", assertion); + VerifyCSharpDiagnostic("string actual, string expected", assertion); [DataTestMethod] [DataRow( @@ -415,7 +414,7 @@ public void AssertStringDoesNotContain_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().NotContain(expected);")] [Implemented] public void AssertStringDoesNotContain_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("string actual, string expected", oldAssertion, newAssertion); + => VerifyCSharpFix("string actual, string expected", oldAssertion, newAssertion); [DataTestMethod] @@ -425,7 +424,7 @@ public void AssertStringDoesNotContain_TestCodeFix(string oldAssertion, string n [DataRow("Assert.DoesNotContain(expected, actual);", "ImmutableHashSet actual, string expected")] [Implemented] public void AssertSetDoesNotContain_TestAnalyzer(string assertion, string arguments) => - VerifyCSharpDiagnostic(arguments, assertion); + VerifyCSharpDiagnostic(arguments, assertion); [DataTestMethod] [DataRow( @@ -446,14 +445,14 @@ public void AssertSetDoesNotContain_TestAnalyzer(string assertion, string argume /* arguments: */ "ImmutableHashSet actual, string expected")] [Implemented] public void AssertSetDoesNotContain_TestCodeFix(string oldAssertion, string newAssertion, string arguments) - => VerifyCSharpFix(arguments, oldAssertion, newAssertion); + => VerifyCSharpFix(arguments, oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.Matches(expectedRegexPattern, actual);")] [Implemented] public void AssertStringMatches_String_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("string actual, string expectedRegexPattern", assertion); + VerifyCSharpDiagnostic("string actual, string expectedRegexPattern", assertion); [DataTestMethod] [DataRow( @@ -461,13 +460,13 @@ public void AssertStringMatches_String_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().MatchRegex(expectedRegexPattern);")] [Implemented] public void AssertStringMatches_String_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("string actual, string expectedRegexPattern", oldAssertion, newAssertion); + => VerifyCSharpFix("string actual, string expectedRegexPattern", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.Matches(expectedRegex, actual);")] [Implemented] public void AssertStringMatches_Regex_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("string actual, Regex expectedRegex", assertion); + VerifyCSharpDiagnostic("string actual, Regex expectedRegex", assertion); [DataTestMethod] [DataRow( @@ -475,13 +474,13 @@ public void AssertStringMatches_Regex_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().MatchRegex(expectedRegex);")] [Implemented] public void AssertStringMatches_Regex_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("string actual, Regex expectedRegex", oldAssertion, newAssertion); + => VerifyCSharpFix("string actual, Regex expectedRegex", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.DoesNotMatch(expectedRegexPattern, actual);")] [Implemented] public void AssertStringDoesNotMatch_String_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("string actual, string expectedRegexPattern", assertion); + VerifyCSharpDiagnostic("string actual, string expectedRegexPattern", assertion); [DataTestMethod] [DataRow( @@ -489,13 +488,13 @@ public void AssertStringDoesNotMatch_String_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().NotMatchRegex(expectedRegexPattern);")] [Implemented] public void AssertStringDoesNotMatch_String_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("string actual, string expectedRegexPattern", oldAssertion, newAssertion); + => VerifyCSharpFix("string actual, string expectedRegexPattern", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.DoesNotMatch(expectedRegex, actual);")] [Implemented] public void AssertStringDoesNotMatch_Regex_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("string actual, Regex expectedRegex", assertion); + VerifyCSharpDiagnostic("string actual, Regex expectedRegex", assertion); [DataTestMethod] [DataRow( @@ -503,13 +502,13 @@ public void AssertStringDoesNotMatch_Regex_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().NotMatchRegex(expectedRegex);")] [Implemented] public void AssertStringDoesNotMatch_Regex_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("string actual, Regex expectedRegex", oldAssertion, newAssertion); + => VerifyCSharpFix("string actual, Regex expectedRegex", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.Empty(actual);")] [Implemented] public void AssertEmpty_String_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("string actual", assertion); + VerifyCSharpDiagnostic("string actual", assertion); [DataTestMethod] [DataRow( @@ -517,13 +516,13 @@ public void AssertEmpty_String_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().BeEmpty();")] [Implemented] public void AssertEmpty_String_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("string actual", oldAssertion, newAssertion); + => VerifyCSharpFix("string actual", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.EndsWith(expected, actual);")] [Implemented] public void AssertEndsWith_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("string actual, string expected", assertion); + VerifyCSharpDiagnostic("string actual, string expected", assertion); [DataTestMethod] [DataRow( @@ -531,13 +530,13 @@ public void AssertEndsWith_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().EndWith(expected);")] [Implemented] public void AssertEndsWith_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("string actual, string expected", oldAssertion, newAssertion); + => VerifyCSharpFix("string actual, string expected", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.StartsWith(expected, actual);")] [Implemented] public void AssertStartsWith_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("string actual, string expected", assertion); + VerifyCSharpDiagnostic("string actual, string expected", assertion); [DataTestMethod] [DataRow( @@ -545,13 +544,13 @@ public void AssertStartsWith_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().StartWith(expected);")] [Implemented] public void AssertStartsWith_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("string actual, string expected", oldAssertion, newAssertion); + => VerifyCSharpFix("string actual, string expected", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.Subset(expected, actual);")] [Implemented] public void AssertSubset_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("ISet actual, ISet expected", assertion); + VerifyCSharpDiagnostic("ISet actual, ISet expected", assertion); [DataTestMethod] [DataRow( @@ -559,7 +558,7 @@ public void AssertSubset_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().BeSubsetOf(expected);")] [Implemented] public void AssertSubset_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("ISet actual, ISet expected", oldAssertion, newAssertion); + => VerifyCSharpFix("ISet actual, ISet expected", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.IsAssignableFrom(expected, actual);")] @@ -567,7 +566,7 @@ public void AssertSubset_TestCodeFix(string oldAssertion, string newAssertion) [DataRow("Assert.IsAssignableFrom(actual);")] [Implemented] public void AssertIsAssignableFrom_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("string actual, Type expected", assertion); + VerifyCSharpDiagnostic("string actual, Type expected", assertion); [DataTestMethod] [DataRow( @@ -581,7 +580,7 @@ public void AssertIsAssignableFrom_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().BeAssignableTo();")] [Implemented] public void AssertIsAssignableFrom_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("string actual, Type expected", oldAssertion, newAssertion); + => VerifyCSharpFix("string actual, Type expected", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.IsNotAssignableFrom(expected, actual);")] @@ -589,7 +588,7 @@ public void AssertIsAssignableFrom_TestCodeFix(string oldAssertion, string newAs [DataRow("Assert.IsNotAssignableFrom(actual);")] [Implemented] public void AssertIsNotAssignableFrom_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("string actual, Type expected", assertion); + VerifyCSharpDiagnostic("string actual, Type expected", assertion); [DataTestMethod] [DataRow( @@ -603,7 +602,7 @@ public void AssertIsNotAssignableFrom_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().NotBeAssignableTo();")] [Implemented] public void AssertIsNotAssignableFrom_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("string actual, Type expected", oldAssertion, newAssertion); + => VerifyCSharpFix("string actual, Type expected", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.IsType(expected, actual);")] @@ -611,7 +610,7 @@ public void AssertIsNotAssignableFrom_TestCodeFix(string oldAssertion, string ne [DataRow("Assert.IsType(actual);")] [Implemented] public void AssertIsType_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("string actual, Type expected", assertion); + VerifyCSharpDiagnostic("string actual, Type expected", assertion); [DataTestMethod] [DataRow( @@ -625,7 +624,7 @@ public void AssertIsType_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().BeOfType();")] [Implemented] public void AssertIsType_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("string actual, Type expected", oldAssertion, newAssertion); + => VerifyCSharpFix("string actual, Type expected", oldAssertion, newAssertion); [DataTestMethod] [DataRow("Assert.IsNotType(expected, actual);")] @@ -633,7 +632,7 @@ public void AssertIsType_TestCodeFix(string oldAssertion, string newAssertion) [DataRow("Assert.IsNotType(actual);")] [Implemented] public void AssertIsNotType_TestAnalyzer(string assertion) => - VerifyCSharpDiagnostic("string actual, Type expected", assertion); + VerifyCSharpDiagnostic("string actual, Type expected", assertion); [DataTestMethod] [DataRow( @@ -647,24 +646,19 @@ public void AssertIsNotType_TestAnalyzer(string assertion) => /* newAssertion: */ "actual.Should().NotBeOfType();")] [Implemented] public void AssertIsNotType_TestCodeFix(string oldAssertion, string newAssertion) - => VerifyCSharpFix("string actual, Type expected", oldAssertion, newAssertion); + => VerifyCSharpFix("string actual, Type expected", oldAssertion, newAssertion); - private void VerifyCSharpDiagnostic(string methodArguments, string assertion) where TDiagnosticAnalyzer : Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer, new() + private void VerifyCSharpDiagnostic(string methodArguments, string assertion) { var source = GenerateCode.XunitAssertion(methodArguments, assertion); - - var type = typeof(TDiagnosticAnalyzer); - var diagnosticId = (string)type.GetField("DiagnosticId").GetValue(null); - var message = (string)type.GetField("Message").GetValue(null); - DiagnosticVerifier.VerifyDiagnostic(new DiagnosticVerifierArguments() .WithAllAnalyzers() .WithSources(source) .WithPackageReferences(PackageReference.FluentAssertions_6_12_0, PackageReference.XunitAssert_2_5_1) .WithExpectedDiagnostics(new DiagnosticResult { - Id = diagnosticId, - Message = message, + Id = AssertAnalyzer.XunitRule.Id, + Message = AssertAnalyzer.Message, Locations = new DiagnosticResultLocation[] { new("Test0.cs", 15, 13) @@ -674,16 +668,14 @@ public void AssertIsNotType_TestCodeFix(string oldAssertion, string newAssertion ); } - private void VerifyCSharpFix(string methodArguments, string oldAssertion, string newAssertion) - where TCodeFixProvider : Microsoft.CodeAnalysis.CodeFixes.CodeFixProvider, new() - where TDiagnosticAnalyzer : Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer, new() + private void VerifyCSharpFix(string methodArguments, string oldAssertion, string newAssertion) { var oldSource = GenerateCode.XunitAssertion(methodArguments, oldAssertion); var newSource = GenerateCode.XunitAssertion(methodArguments, newAssertion); DiagnosticVerifier.VerifyFix(new CodeFixVerifierArguments() - .WithDiagnosticAnalyzer() - .WithCodeFixProvider() + .WithDiagnosticAnalyzer() + .WithCodeFixProvider() .WithSources(oldSource) .WithFixedSources(newSource) .WithPackageReferences(PackageReference.FluentAssertions_6_12_0, PackageReference.XunitAssert_2_5_1) diff --git a/src/FluentAssertions.Analyzers/Tips/AssertAnalyzer.cs b/src/FluentAssertions.Analyzers/Tips/AssertAnalyzer.cs index 4e980caf..76a3cf68 100644 --- a/src/FluentAssertions.Analyzers/Tips/AssertAnalyzer.cs +++ b/src/FluentAssertions.Analyzers/Tips/AssertAnalyzer.cs @@ -77,11 +77,10 @@ public override void Initialize(AnalysisContext context) var analyzerContext = new AnalyzerContext(context.Compilation); - // TODO: enable xunit - // if (analyzerContext.IsXUnitAvailable) - // { - // context.RegisterOperationAction(analyzerContext.AnalyzeXunitInvocation, OperationKind.Invocation); - // } + if (analyzerContext.IsXUnitAvailable) + { + context.RegisterOperationAction(analyzerContext.AnalyzeXunitInvocation, OperationKind.Invocation); + } if (analyzerContext.IsMSTestsAvailable) { diff --git a/src/FluentAssertions.Analyzers/Tips/DocumentEditorUtils.cs b/src/FluentAssertions.Analyzers/Tips/DocumentEditorUtils.cs index c5c2b13c..1f51af27 100644 --- a/src/FluentAssertions.Analyzers/Tips/DocumentEditorUtils.cs +++ b/src/FluentAssertions.Analyzers/Tips/DocumentEditorUtils.cs @@ -20,7 +20,7 @@ public static CreateChangedDocument RenameMethodToSubjectShouldAssertion(IInvoca return await RewriteExpression(invocationExpression, [ ..Array.ConvertAll(argumentsToRemove, arg => new RemoveNodeAction(invocationExpression.ArgumentList.Arguments[arg])), - new SubjectShouldAssertionAction(argumentIndex, newName) + new SubjectShouldAssertionAction(argumentIndex, newName) ], context, ctx); }; @@ -33,7 +33,18 @@ public static CreateChangedDocument RenameMethodToSubjectShouldGenericAssertion( return await RewriteExpression(invocationExpression, [ ..Array.ConvertAll(argumentsToRemove, arg => new RemoveNodeAction(invocationExpression.ArgumentList.Arguments[arg])), - new SubjectShouldGenericAssertionAction(argumentIndex, newName, genericTypes) + new SubjectShouldGenericAssertionAction(argumentIndex, newName, genericTypes) + ], context, ctx); + }; + + public static CreateChangedDocument RenameMethodToSubjectShouldAssertionWithOptionsLambda(IInvocationOperation invocation, CodeFixContext context, string newName, int argumentIndex, int optionsIndex) + => async ctx => + { + var invocationExpression = (InvocationExpressionSyntax)invocation.Syntax; + + return await RewriteExpression(invocationExpression, [ + new SubjectShouldAssertionAction(argumentIndex, newName), + new CreateEquivalencyAssertionOptionsLambda(optionsIndex) ], context, ctx); }; diff --git a/src/FluentAssertions.Analyzers/Tips/Editing/CreateEquivalencyAssertionOptionsLambda.cs b/src/FluentAssertions.Analyzers/Tips/Editing/CreateEquivalencyAssertionOptionsLambda.cs new file mode 100644 index 00000000..f6eccfd7 --- /dev/null +++ b/src/FluentAssertions.Analyzers/Tips/Editing/CreateEquivalencyAssertionOptionsLambda.cs @@ -0,0 +1,26 @@ +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Editing; + +namespace FluentAssertions.Analyzers; + +public class CreateEquivalencyAssertionOptionsLambda : IEditAction +{ + private readonly int _argumentIndex; + + public CreateEquivalencyAssertionOptionsLambda(int argumentIndex) + { + _argumentIndex = argumentIndex; + } + + public void Apply(DocumentEditor editor, InvocationExpressionSyntax invocationExpression) + { + const string lambdaParameter = "options"; + const string equivalencyAssertionOptionsMethod = "Using"; + + var generator = editor.Generator; + var optionsParameter = invocationExpression.ArgumentList.Arguments[_argumentIndex]; + + var equivalencyAssertionLambda = generator.ValueReturningLambdaExpression(lambdaParameter, generator.InvocationExpression(generator.MemberAccessExpression(generator.IdentifierName(lambdaParameter), equivalencyAssertionOptionsMethod), optionsParameter)); + editor.ReplaceNode(optionsParameter.Expression, equivalencyAssertionLambda); + } +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/MsTestCodeFixProvider.cs b/src/FluentAssertions.Analyzers/Tips/MsTestCodeFixProvider.cs index 0cdd23a8..bd45f8ef 100644 --- a/src/FluentAssertions.Analyzers/Tips/MsTestCodeFixProvider.cs +++ b/src/FluentAssertions.Analyzers/Tips/MsTestCodeFixProvider.cs @@ -1,104 +1,68 @@ using System.Collections.Immutable; using System.Composition; -using System.Threading.Tasks; -using FluentAssertions.Analyzers.Utilities; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Operations; using CreateChangedDocument = System.Func>; namespace FluentAssertions.Analyzers; [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(MsTestCodeFixProvider)), Shared] -public class MsTestCodeFixProvider : CodeFixProvider +public class MsTestCodeFixProvider : TestingFrameworkCodeFixProvider { - const string Title = "Replace with FluentAssertions"; public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertAnalyzer.MSTestsRule.Id); - public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; - public override async Task RegisterCodeFixesAsync(CodeFixContext context) - { - var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken); - var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken); - - var testContext = new MsTestCodeFixContext(semanticModel.Compilation); - foreach (var diagnostic in context.Diagnostics) - { - var node = root.FindNode(diagnostic.Location.SourceSpan); - if (node is not InvocationExpressionSyntax invocationExpression) - { - continue; - } - - var operation = semanticModel.GetOperation(invocationExpression, context.CancellationToken); - if (operation is not IInvocationOperation invocation) - { - continue; - } - TryComputeFix(invocation, context, testContext, diagnostic); - } - } - - private void TryComputeFix(IInvocationOperation invocation, CodeFixContext context, MsTestCodeFixContext testContext, Diagnostic diagnostic) + protected override CreateChangedDocument TryComputeFix(IInvocationOperation invocation, CodeFixContext context, TestingFrameworkCodeFixContext testContext, Diagnostic diagnostic) { var assertType = invocation.TargetMethod.ContainingType; - var createChangedDocument = assertType.Name switch + return assertType.Name switch { "Assert" => TryComputeFixForAssert(invocation, context, testContext), "StringAssert" => TryComputeFixForStringAssert(invocation, context, testContext), "CollectionAssert" => TryComputeFixForCollectionAssert(invocation, context, testContext), _ => null }; - - if (createChangedDocument is null) - { - return; - } - - context.RegisterCodeFix(CodeAction.Create(Title, createChangedDocument, equivalenceKey: Title), diagnostic); } - private CreateChangedDocument TryComputeFixForAssert(IInvocationOperation invocation, CodeFixContext context, MsTestCodeFixContext t) + private CreateChangedDocument TryComputeFixForAssert(IInvocationOperation invocation, CodeFixContext context, TestingFrameworkCodeFixContext t) { switch (invocation.TargetMethod.Name) { - case "AreEqual" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemBoolean): // AreEqual(string? expected, string? actual, bool ignoreCase) - case "AreEqual" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemBoolean, t.SystemString): // AreEqual(string? expected, string? actual, bool ignoreCase, string? message) - case "AreEqual" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemBoolean, t.SystemString, t.ObjectArray): // AreEqual(string? expected, string? actual, bool ignoreCase, string? message, params object?[]? parameters) + case "AreEqual" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.Boolean): // AreEqual(string? expected, string? actual, bool ignoreCase) + case "AreEqual" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.Boolean, t.String): // AreEqual(string? expected, string? actual, bool ignoreCase, string? message) + case "AreEqual" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.Boolean, t.String, t.ObjectArray): // AreEqual(string? expected, string? actual, bool ignoreCase, string? message, params object?[]? parameters) { var ignoreCase = invocation.Arguments.Length >= 3 && invocation.Arguments[2].IsLiteralValue(true); var newMethod = ignoreCase ? "BeEquivalentTo" : "Be"; return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, newMethod, argumentIndex: 1, argumentsToRemove: [2]); } - case "AreEqual" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemBoolean, t.SystemGlobalizationCultureInfo): // AreEqual(string? expected, string? actual, bool ignoreCase, CultureInfo? culture) - case "AreEqual" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemBoolean, t.SystemGlobalizationCultureInfo, t.SystemString): // AreEqual(string? expected, string? actual, bool ignoreCase, CultureInfo? culture, string? message) - case "AreEqual" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemBoolean, t.SystemGlobalizationCultureInfo, t.SystemString, t.ObjectArray): // AreEqual(string? expected, string? actual, bool ignoreCase, CultureInfo? culture, string? message, params object?[]? parameters) + case "AreEqual" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.Boolean, t.CultureInfo): // AreEqual(string? expected, string? actual, bool ignoreCase, CultureInfo? culture) + case "AreEqual" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.Boolean, t.CultureInfo, t.String): // AreEqual(string? expected, string? actual, bool ignoreCase, CultureInfo? culture, string? message) + case "AreEqual" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.Boolean, t.CultureInfo, t.String, t.ObjectArray): // AreEqual(string? expected, string? actual, bool ignoreCase, CultureInfo? culture, string? message, params object?[]? parameters) { var ignoreCase = invocation.Arguments.Length >= 3 && invocation.Arguments[2].IsLiteralValue(true); var newMethod = ignoreCase ? "BeEquivalentTo" : "Be"; - if (!invocation.Arguments[3].IsStaticPropertyReference(t.SystemGlobalizationCultureInfo, "CurrentCulture")) + if (!invocation.Arguments[3].IsStaticPropertyReference(t.CultureInfo, "CurrentCulture")) { break; // TODO: Handle other cultures } return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, newMethod, argumentIndex: 1, argumentsToRemove: [2, 3]); } - case "AreEqual" when ArgumentsAreTypeOf(invocation, t.SystemFloat, t.SystemFloat, t.SystemFloat): // AreEqual(float expected, float actual, float delta) - case "AreEqual" when ArgumentsAreTypeOf(invocation, t.SystemFloat, t.SystemFloat, t.SystemFloat, t.SystemString): // AreEqual(float expected, float actual, float delta, string? message) - case "AreEqual" when ArgumentsAreTypeOf(invocation, t.SystemFloat, t.SystemFloat, t.SystemFloat, t.SystemString, t.ObjectArray): // AreEqual(float expected, float actual, float delta, string? message, params object?[]? parameters) - case "AreEqual" when ArgumentsAreTypeOf(invocation, t.SystemDouble, t.SystemDouble, t.SystemDouble): // AreEqual(double expected, double actual, double delta) - case "AreEqual" when ArgumentsAreTypeOf(invocation, t.SystemDouble, t.SystemDouble, t.SystemDouble, t.SystemString): // AreEqual(double expected, double actual, double delta, string? message) - case "AreEqual" when ArgumentsAreTypeOf(invocation, t.SystemDouble, t.SystemDouble, t.SystemDouble, t.SystemString, t.ObjectArray): // AreEqual(double expected, double actual, double delta, string? message, params object?[]? parameters) - case "AreEqual" when ArgumentsAreTypeOf(invocation, t.SystemDecimal, t.SystemDecimal, t.SystemDecimal): // AreEqual(decimal expected, decimal actual, decimal delta) - case "AreEqual" when ArgumentsAreTypeOf(invocation, t.SystemDecimal, t.SystemDecimal, t.SystemDecimal, t.SystemString): // AreEqual(decimal expected, decimal actual, decimal delta, string? message) - case "AreEqual" when ArgumentsAreTypeOf(invocation, t.SystemDecimal, t.SystemDecimal, t.SystemDecimal, t.SystemString, t.ObjectArray): // AreEqual(decimal expected, decimal actual, decimal delta, string? message, params object?[]? parameters) + case "AreEqual" when ArgumentsAreTypeOf(invocation, t.Float, t.Float, t.Float): // AreEqual(float expected, float actual, float delta) + case "AreEqual" when ArgumentsAreTypeOf(invocation, t.Float, t.Float, t.Float, t.String): // AreEqual(float expected, float actual, float delta, string? message) + case "AreEqual" when ArgumentsAreTypeOf(invocation, t.Float, t.Float, t.Float, t.String, t.ObjectArray): // AreEqual(float expected, float actual, float delta, string? message, params object?[]? parameters) + case "AreEqual" when ArgumentsAreTypeOf(invocation, t.Double, t.Double, t.Double): // AreEqual(double expected, double actual, double delta) + case "AreEqual" when ArgumentsAreTypeOf(invocation, t.Double, t.Double, t.Double, t.String): // AreEqual(double expected, double actual, double delta, string? message) + case "AreEqual" when ArgumentsAreTypeOf(invocation, t.Double, t.Double, t.Double, t.String, t.ObjectArray): // AreEqual(double expected, double actual, double delta, string? message, params object?[]? parameters) + case "AreEqual" when ArgumentsAreTypeOf(invocation, t.Decimal, t.Decimal, t.Decimal): // AreEqual(decimal expected, decimal actual, decimal delta) + case "AreEqual" when ArgumentsAreTypeOf(invocation, t.Decimal, t.Decimal, t.Decimal, t.String): // AreEqual(decimal expected, decimal actual, decimal delta, string? message) + case "AreEqual" when ArgumentsAreTypeOf(invocation, t.Decimal, t.Decimal, t.Decimal, t.String, t.ObjectArray): // AreEqual(decimal expected, decimal actual, decimal delta, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeApproximately", argumentIndex: 1, argumentsToRemove: []); case "AreEqual" when ArgumentsAreTypeOf(invocation, startFromIndex: 2): // AreEqual(T? expected, T? actual) - case "AreEqual" when ArgumentsAreTypeOf(invocation, startFromIndex: 2, t.SystemString): // AreEqual(T? expected, T? actual, string? message) - case "AreEqual" when ArgumentsAreTypeOf(invocation, startFromIndex: 2, t.SystemString, t.ObjectArray): // AreEqual(T? expected, T? actual, string? message, params object?[]? parameters) + case "AreEqual" when ArgumentsAreTypeOf(invocation, startFromIndex: 2, t.String): // AreEqual(T? expected, T? actual, string? message) + case "AreEqual" when ArgumentsAreTypeOf(invocation, startFromIndex: 2, t.String, t.ObjectArray): // AreEqual(T? expected, T? actual, string? message, params object?[]? parameters) if (invocation.Arguments[0].IsLiteralNull()) { return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeNull", argumentIndex: 1, argumentsToRemove: [0]); @@ -108,41 +72,41 @@ private CreateChangedDocument TryComputeFixForAssert(IInvocationOperation invoca return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeNull", argumentIndex: 0, argumentsToRemove: [1]); } return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "Be", argumentIndex: 1, argumentsToRemove: []); - case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemBoolean): // AreNotEqual(string? expected, string? actual, bool ignoreCase) - case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemBoolean, t.SystemString): // AreNotEqual(string? expected, string? actual, bool ignoreCase, string? message) - case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemBoolean, t.SystemString, t.ObjectArray): // AreNotEqual(string? expected, string? actual, bool ignoreCase, string? message, params object?[]? parameters) + case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.Boolean): // AreNotEqual(string? expected, string? actual, bool ignoreCase) + case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.Boolean, t.String): // AreNotEqual(string? expected, string? actual, bool ignoreCase, string? message) + case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.Boolean, t.String, t.ObjectArray): // AreNotEqual(string? expected, string? actual, bool ignoreCase, string? message, params object?[]? parameters) { var ignoreCase = invocation.Arguments.Length >= 3 && invocation.Arguments[2].IsLiteralValue(true); var newMethod = ignoreCase ? "NotBeEquivalentTo" : "NotBe"; return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, newMethod, argumentIndex: 1, argumentsToRemove: [2]); } - case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemBoolean, t.SystemGlobalizationCultureInfo): // AreNotEqual(string? expected, string? actual, bool ignoreCase, CultureInfo? culture) - case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemBoolean, t.SystemGlobalizationCultureInfo, t.SystemString): // AreNotEqual(string? expected, string? actual, bool ignoreCase, CultureInfo? culture, string? message) - case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemBoolean, t.SystemGlobalizationCultureInfo, t.SystemString, t.ObjectArray): // AreNotEqual(string? expected, string? actual, bool ignoreCase, CultureInfo? culture, string? message, params object?[]? parameters) + case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.Boolean, t.CultureInfo): // AreNotEqual(string? expected, string? actual, bool ignoreCase, CultureInfo? culture) + case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.Boolean, t.CultureInfo, t.String): // AreNotEqual(string? expected, string? actual, bool ignoreCase, CultureInfo? culture, string? message) + case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.Boolean, t.CultureInfo, t.String, t.ObjectArray): // AreNotEqual(string? expected, string? actual, bool ignoreCase, CultureInfo? culture, string? message, params object?[]? parameters) { var ignoreCase = invocation.Arguments.Length >= 3 && invocation.Arguments[2].IsLiteralValue(true); var newMethod = ignoreCase ? "NotBeEquivalentTo" : "NotBe"; - if (!invocation.Arguments[3].IsStaticPropertyReference(t.SystemGlobalizationCultureInfo, "CurrentCulture")) + if (!invocation.Arguments[3].IsStaticPropertyReference(t.CultureInfo, "CurrentCulture")) { break; // TODO: Handle other cultures } return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, newMethod, argumentIndex: 1, argumentsToRemove: [2, 3]); } - case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.SystemFloat, t.SystemFloat, t.SystemFloat): // AreNotEqual(float expected, float actual, float delta) - case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.SystemFloat, t.SystemFloat, t.SystemFloat, t.SystemString): // AreNotEqual(float expected, float actual, float delta, string? message) - case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.SystemFloat, t.SystemFloat, t.SystemFloat, t.SystemString, t.ObjectArray): // AreNotEqual(float expected, float actual, float delta, string? message, params object?[]? parameters) - case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.SystemDouble, t.SystemDouble, t.SystemDouble): // AreNotEqual(double expected, double actual, double delta) - case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.SystemDouble, t.SystemDouble, t.SystemDouble, t.SystemString): // AreNotEqual(double expected, double actual, double delta, string? message) - case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.SystemDouble, t.SystemDouble, t.SystemDouble, t.SystemString, t.ObjectArray): // AreNotEqual(double expected, double actual, double delta, string? message, params object?[]? parameters) - case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.SystemDecimal, t.SystemDecimal, t.SystemDecimal): // AreNotEqual(decimal expected, decimal actual, decimal delta) - case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.SystemDecimal, t.SystemDecimal, t.SystemDecimal, t.SystemString): // AreNotEqual(decimal expected, decimal actual, decimal delta, string? message) - case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.SystemDecimal, t.SystemDecimal, t.SystemDecimal, t.SystemString, t.ObjectArray): // AreNotEqual(decimal expected, decimal actual, decimal delta, string? message, params object?[]? parameters) + case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.Float, t.Float, t.Float): // AreNotEqual(float expected, float actual, float delta) + case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.Float, t.Float, t.Float, t.String): // AreNotEqual(float expected, float actual, float delta, string? message) + case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.Float, t.Float, t.Float, t.String, t.ObjectArray): // AreNotEqual(float expected, float actual, float delta, string? message, params object?[]? parameters) + case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.Double, t.Double, t.Double): // AreNotEqual(double expected, double actual, double delta) + case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.Double, t.Double, t.Double, t.String): // AreNotEqual(double expected, double actual, double delta, string? message) + case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.Double, t.Double, t.Double, t.String, t.ObjectArray): // AreNotEqual(double expected, double actual, double delta, string? message, params object?[]? parameters) + case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.Decimal, t.Decimal, t.Decimal): // AreNotEqual(decimal expected, decimal actual, decimal delta) + case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.Decimal, t.Decimal, t.Decimal, t.String): // AreNotEqual(decimal expected, decimal actual, decimal delta, string? message) + case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.Decimal, t.Decimal, t.Decimal, t.String, t.ObjectArray): // AreNotEqual(decimal expected, decimal actual, decimal delta, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotBeApproximately", argumentIndex: 1, argumentsToRemove: []); case "AreNotEqual" when ArgumentsAreTypeOf(invocation, startFromIndex: 2): // AreNotEqual(T? expected, T? actual) - case "AreNotEqual" when ArgumentsAreTypeOf(invocation, startFromIndex: 2, t.SystemString): // AreNotEqual(T? expected, T? actual, string? message) - case "AreNotEqual" when ArgumentsAreTypeOf(invocation, startFromIndex: 2, t.SystemString, t.ObjectArray): // AreNotEqual(T? expected, T? actual, string? message, params object?[]? parameters) + case "AreNotEqual" when ArgumentsAreTypeOf(invocation, startFromIndex: 2, t.String): // AreNotEqual(T? expected, T? actual, string? message) + case "AreNotEqual" when ArgumentsAreTypeOf(invocation, startFromIndex: 2, t.String, t.ObjectArray): // AreNotEqual(T? expected, T? actual, string? message, params object?[]? parameters) if (invocation.Arguments[0].IsLiteralNull()) { return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotBeNull", argumentIndex: 1, argumentsToRemove: [0]); @@ -153,47 +117,47 @@ private CreateChangedDocument TryComputeFixForAssert(IInvocationOperation invoca } return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotBe", argumentIndex: 1, argumentsToRemove: []); case "AreSame" when ArgumentsAreTypeOf(invocation, startFromIndex: 2): // AreSame(string? expected, string? actual) - case "AreSame" when ArgumentsAreTypeOf(invocation, startFromIndex: 2, t.SystemString): // AreSame(string? expected, string? actual, string? message) - case "AreSame" when ArgumentsAreTypeOf(invocation, startFromIndex: 2, t.SystemString, t.ObjectArray): // AreSame(string? expected, string? actual, string? message, params object?[]? parameters) + case "AreSame" when ArgumentsAreTypeOf(invocation, startFromIndex: 2, t.String): // AreSame(string? expected, string? actual, string? message) + case "AreSame" when ArgumentsAreTypeOf(invocation, startFromIndex: 2, t.String, t.ObjectArray): // AreSame(string? expected, string? actual, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeSameAs", argumentIndex: 1, argumentsToRemove: []); case "AreNotSame" when ArgumentsAreTypeOf(invocation, startFromIndex: 2): // AreNotSame(string? expected, string? actual) - case "AreNotSame" when ArgumentsAreTypeOf(invocation, startFromIndex: 2, t.SystemString): // AreNotSame(string? expected, string? actual, string? message) - case "AreNotSame" when ArgumentsAreTypeOf(invocation, startFromIndex: 2, t.SystemString, t.ObjectArray): // AreNotSame(string? expected, string? actual, string? message, params object?[]? parameters) + case "AreNotSame" when ArgumentsAreTypeOf(invocation, startFromIndex: 2, t.String): // AreNotSame(string? expected, string? actual, string? message) + case "AreNotSame" when ArgumentsAreTypeOf(invocation, startFromIndex: 2, t.String, t.ObjectArray): // AreNotSame(string? expected, string? actual, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotBeSameAs", argumentIndex: 1, argumentsToRemove: []); - case "IsTrue" when ArgumentsAreTypeOf(invocation, t.SystemBoolean): // IsTrue(bool condition) - case "IsTrue" when ArgumentsAreTypeOf(invocation, t.SystemBoolean, t.SystemString): // IsTrue(bool condition, string? message) - case "IsTrue" when ArgumentsAreTypeOf(invocation, t.SystemBoolean, t.SystemString, t.ObjectArray): // IsTrue(bool condition, string? message, params object?[]? parameters) + case "IsTrue" when ArgumentsAreTypeOf(invocation, t.Boolean): // IsTrue(bool condition) + case "IsTrue" when ArgumentsAreTypeOf(invocation, t.Boolean, t.String): // IsTrue(bool condition, string? message) + case "IsTrue" when ArgumentsAreTypeOf(invocation, t.Boolean, t.String, t.ObjectArray): // IsTrue(bool condition, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeTrue", argumentIndex: 0, argumentsToRemove: []); - case "IsFalse" when ArgumentsAreTypeOf(invocation, t.SystemBoolean): // IsFalse(bool condition) - case "IsFalse" when ArgumentsAreTypeOf(invocation, t.SystemBoolean, t.SystemString): // IsFalse(bool condition, string? message) - case "IsFalse" when ArgumentsAreTypeOf(invocation, t.SystemBoolean, t.SystemString, t.ObjectArray): // IsFalse(bool condition, string? message, params object?[]? parameters) + case "IsFalse" when ArgumentsAreTypeOf(invocation, t.Boolean): // IsFalse(bool condition) + case "IsFalse" when ArgumentsAreTypeOf(invocation, t.Boolean, t.String): // IsFalse(bool condition, string? message) + case "IsFalse" when ArgumentsAreTypeOf(invocation, t.Boolean, t.String, t.ObjectArray): // IsFalse(bool condition, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeFalse", argumentIndex: 0, argumentsToRemove: []); - case "IsNull" when ArgumentsAreTypeOf(invocation, t.SystemObject): // IsNull(object? value) - case "IsNull" when ArgumentsAreTypeOf(invocation, t.SystemObject, t.SystemString): // IsNull(object? value, string? message) - case "IsNull" when ArgumentsAreTypeOf(invocation, t.SystemObject, t.SystemString, t.ObjectArray): // IsNull(object? value, string? message, params object?[]? parameters) + case "IsNull" when ArgumentsAreTypeOf(invocation, t.Object): // IsNull(object? value) + case "IsNull" when ArgumentsAreTypeOf(invocation, t.Object, t.String): // IsNull(object? value, string? message) + case "IsNull" when ArgumentsAreTypeOf(invocation, t.Object, t.String, t.ObjectArray): // IsNull(object? value, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeNull", argumentIndex: 0, argumentsToRemove: []); - case "IsNotNull" when ArgumentsAreTypeOf(invocation, t.SystemObject): // IsNotNull(object? value) - case "IsNotNull" when ArgumentsAreTypeOf(invocation, t.SystemObject, t.SystemString): // IsNotNull(object? value, string? message) - case "IsNotNull" when ArgumentsAreTypeOf(invocation, t.SystemObject, t.SystemString, t.ObjectArray): // IsNotNull(object? value, string? message, params object?[]? parameters) + case "IsNotNull" when ArgumentsAreTypeOf(invocation, t.Object): // IsNotNull(object? value) + case "IsNotNull" when ArgumentsAreTypeOf(invocation, t.Object, t.String): // IsNotNull(object? value, string? message) + case "IsNotNull" when ArgumentsAreTypeOf(invocation, t.Object, t.String, t.ObjectArray): // IsNotNull(object? value, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotBeNull", argumentIndex: 0, argumentsToRemove: []); - case "ThrowsException" when ArgumentsAreTypeOf(invocation, t.SystemAction): // ThrowsException(Action action) - case "ThrowsException" when ArgumentsAreTypeOf(invocation, t.SystemAction, t.SystemString): // ThrowsException(Action action, string? message) - case "ThrowsException" when ArgumentsAreTypeOf(invocation, t.SystemAction, t.SystemString, t.ObjectArray): // ThrowsException(Action action, string? message, params object?[]? parameters) - case "ThrowsException" when ArgumentsAreTypeOf(invocation, t.SystemFuncOfObject): // ThrowsException(Func action) - case "ThrowsException" when ArgumentsAreTypeOf(invocation, t.SystemFuncOfObject, t.SystemString): // ThrowsException(Func action, string? message) - case "ThrowsException" when ArgumentsAreTypeOf(invocation, t.SystemFuncOfObject, t.SystemString, t.ObjectArray): // ThrowsException(Func action, string? message, params object?[]? parameters) + case "ThrowsException" when ArgumentsAreTypeOf(invocation, t.Action): // ThrowsException(Action action) + case "ThrowsException" when ArgumentsAreTypeOf(invocation, t.Action, t.String): // ThrowsException(Action action, string? message) + case "ThrowsException" when ArgumentsAreTypeOf(invocation, t.Action, t.String, t.ObjectArray): // ThrowsException(Action action, string? message, params object?[]? parameters) + case "ThrowsException" when ArgumentsAreTypeOf(invocation, t.FuncOfObject): // ThrowsException(Func action) + case "ThrowsException" when ArgumentsAreTypeOf(invocation, t.FuncOfObject, t.String): // ThrowsException(Func action, string? message) + case "ThrowsException" when ArgumentsAreTypeOf(invocation, t.FuncOfObject, t.String, t.ObjectArray): // ThrowsException(Func action, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameGenericMethodToSubjectShouldGenericAssertion(invocation, context, "ThrowExactly", argumentIndex: 0, argumentsToRemove: []); - case "ThrowsExceptionAsync" when ArgumentsAreTypeOf(invocation, t.SystemFuncOfTask): // ThrowsExceptionAsync(Func action) - case "ThrowsExceptionAsync" when ArgumentsAreTypeOf(invocation, t.SystemFuncOfTask, t.SystemString): // ThrowsExceptionAsync(Func action, string? message) - case "ThrowsExceptionAsync" when ArgumentsAreTypeOf(invocation, t.SystemFuncOfTask, t.SystemString, t.ObjectArray): // ThrowsExceptionAsync(Func action, string? message, params object?[]? parameters) + case "ThrowsExceptionAsync" when ArgumentsAreTypeOf(invocation, t.FuncOfTask): // ThrowsExceptionAsync(Func action) + case "ThrowsExceptionAsync" when ArgumentsAreTypeOf(invocation, t.FuncOfTask, t.String): // ThrowsExceptionAsync(Func action, string? message) + case "ThrowsExceptionAsync" when ArgumentsAreTypeOf(invocation, t.FuncOfTask, t.String, t.ObjectArray): // ThrowsExceptionAsync(Func action, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameGenericMethodToSubjectShouldGenericAssertion(invocation, context, "ThrowExactlyAsync", argumentIndex: 0, argumentsToRemove: []); - case "IsInstanceOfType" when ArgumentsAreTypeOf(invocation, t.SystemObject): // IsInstanceOfType(object? value) - case "IsInstanceOfType" when ArgumentsAreTypeOf(invocation, t.SystemObject, t.SystemString): // IsInstanceOfType(object? value, string? message) - case "IsInstanceOfType" when ArgumentsAreTypeOf(invocation, t.SystemObject, t.SystemString, t.ObjectArray): // IsInstanceOfType(object? value, string? message, params object?[]? parameters) + case "IsInstanceOfType" when ArgumentsAreTypeOf(invocation, t.Object): // IsInstanceOfType(object? value) + case "IsInstanceOfType" when ArgumentsAreTypeOf(invocation, t.Object, t.String): // IsInstanceOfType(object? value, string? message) + case "IsInstanceOfType" when ArgumentsAreTypeOf(invocation, t.Object, t.String, t.ObjectArray): // IsInstanceOfType(object? value, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameGenericMethodToSubjectShouldGenericAssertion(invocation, context, "BeOfType", argumentIndex: 0, argumentsToRemove: []); - case "IsInstanceOfType" when ArgumentsAreTypeOf(invocation, t.SystemObject, t.SystemType): // IsInstanceOfType(object? value, Type expectedType) - case "IsInstanceOfType" when ArgumentsAreTypeOf(invocation, t.SystemObject, t.SystemType, t.SystemString): // IsInstanceOfType(object? value, Type expectedType, string? message) - case "IsInstanceOfType" when ArgumentsAreTypeOf(invocation, t.SystemObject, t.SystemType, t.SystemString, t.ObjectArray): // IsInstanceOfType(object? value, Type expectedType, string? message, params object?[]? parameters) + case "IsInstanceOfType" when ArgumentsAreTypeOf(invocation, t.Object, t.Type): // IsInstanceOfType(object? value, Type expectedType) + case "IsInstanceOfType" when ArgumentsAreTypeOf(invocation, t.Object, t.Type, t.String): // IsInstanceOfType(object? value, Type expectedType, string? message) + case "IsInstanceOfType" when ArgumentsAreTypeOf(invocation, t.Object, t.Type, t.String, t.ObjectArray): // IsInstanceOfType(object? value, Type expectedType, string? message, params object?[]? parameters) { if (invocation.Arguments[1].Value is not ITypeOfOperation typeOf) { @@ -202,13 +166,13 @@ private CreateChangedDocument TryComputeFixForAssert(IInvocationOperation invoca return DocumentEditorUtils.RenameMethodToSubjectShouldGenericAssertion(invocation, ImmutableArray.Create(typeOf.TypeOperand), context, "BeOfType", argumentIndex: 0, argumentsToRemove: [1]); } - case "IsNotInstanceOfType" when ArgumentsAreTypeOf(invocation, t.SystemObject): // IsNotInstanceOfType(object? value) - case "IsNotInstanceOfType" when ArgumentsAreTypeOf(invocation, t.SystemObject, t.SystemString): // IsNotInstanceOfType(object? value, string? message) - case "IsNotInstanceOfType" when ArgumentsAreTypeOf(invocation, t.SystemObject, t.SystemString, t.ObjectArray): // IsNotInstanceOfType(object? value, string? message, params object?[]? parameters) + case "IsNotInstanceOfType" when ArgumentsAreTypeOf(invocation, t.Object): // IsNotInstanceOfType(object? value) + case "IsNotInstanceOfType" when ArgumentsAreTypeOf(invocation, t.Object, t.String): // IsNotInstanceOfType(object? value, string? message) + case "IsNotInstanceOfType" when ArgumentsAreTypeOf(invocation, t.Object, t.String, t.ObjectArray): // IsNotInstanceOfType(object? value, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameGenericMethodToSubjectShouldGenericAssertion(invocation, context, "NotBeOfType", argumentIndex: 0, argumentsToRemove: []); - case "IsNotInstanceOfType" when ArgumentsAreTypeOf(invocation, t.SystemObject, t.SystemType): // IsNotInstanceOfType(object? value, Type expectedType) - case "IsNotInstanceOfType" when ArgumentsAreTypeOf(invocation, t.SystemObject, t.SystemType, t.SystemString): // IsNotInstanceOfType(object? value, Type expectedType, string? message) - case "IsNotInstanceOfType" when ArgumentsAreTypeOf(invocation, t.SystemObject, t.SystemType, t.SystemString, t.ObjectArray): // IsNotInstanceOfType(object? value, Type expectedType, string? message, params object?[]? parameters) + case "IsNotInstanceOfType" when ArgumentsAreTypeOf(invocation, t.Object, t.Type): // IsNotInstanceOfType(object? value, Type expectedType) + case "IsNotInstanceOfType" when ArgumentsAreTypeOf(invocation, t.Object, t.Type, t.String): // IsNotInstanceOfType(object? value, Type expectedType, string? message) + case "IsNotInstanceOfType" when ArgumentsAreTypeOf(invocation, t.Object, t.Type, t.String, t.ObjectArray): // IsNotInstanceOfType(object? value, Type expectedType, string? message, params object?[]? parameters) { if (invocation.Arguments[1].Value is not ITypeOfOperation typeOf) { @@ -222,50 +186,50 @@ private CreateChangedDocument TryComputeFixForAssert(IInvocationOperation invoca return null; } - private CreateChangedDocument TryComputeFixForStringAssert(IInvocationOperation invocation, CodeFixContext context, MsTestCodeFixContext t) + private CreateChangedDocument TryComputeFixForStringAssert(IInvocationOperation invocation, CodeFixContext context, TestingFrameworkCodeFixContext t) { switch (invocation.TargetMethod.Name) { - case "Contains" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString): // Contains(string? value, string? substring) - case "Contains" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemString): // Contains(string? value, string? substring, string? message) - case "Contains" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemString, t.ObjectArray): // Contains(string? value, string? substring, string? message, params object?[]? parameters) + case "Contains" when ArgumentsAreTypeOf(invocation, t.String, t.String): // Contains(string? value, string? substring) + case "Contains" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.String): // Contains(string? value, string? substring, string? message) + case "Contains" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.String, t.ObjectArray): // Contains(string? value, string? substring, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "Contain", argumentIndex: 0, argumentsToRemove: []); - case "Contains" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemStringComparison): // Contains(string? value, string? substring, StringComparison comparisonType) + case "Contains" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.StringComparison): // Contains(string? value, string? substring, StringComparison comparisonType) break; // TODO: support StringComparison constant values - case "Contains" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemString, t.SystemStringComparison): // Contains(string? value, string? substring, string? message, StringComparison comparisonType) - case "Contains" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemString, t.SystemStringComparison, t.ObjectArray): // Contains(string? value, string? substring, string? message, StringComparison comparisonType, params object?[]? parameters) + case "Contains" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.String, t.StringComparison): // Contains(string? value, string? substring, string? message, StringComparison comparisonType) + case "Contains" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.String, t.StringComparison, t.ObjectArray): // Contains(string? value, string? substring, string? message, StringComparison comparisonType, params object?[]? parameters) break; // TODO: support StringComparison constant values - case "StartsWith" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString): // StartsWith(string? value, string? substring) - case "StartsWith" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemString): // StartsWith(string? value, string? substring, string? message) - case "StartsWith" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemString, t.ObjectArray): // StartsWith(string? value, string? substring, string? message, params object?[]? parameters) + case "StartsWith" when ArgumentsAreTypeOf(invocation, t.String, t.String): // StartsWith(string? value, string? substring) + case "StartsWith" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.String): // StartsWith(string? value, string? substring, string? message) + case "StartsWith" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.String, t.ObjectArray): // StartsWith(string? value, string? substring, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "StartWith", argumentIndex: 0, argumentsToRemove: []); - case "StartsWith" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemStringComparison): // StartsWith(string? value, string? substring, StringComparison comparisonType) + case "StartsWith" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.StringComparison): // StartsWith(string? value, string? substring, StringComparison comparisonType) break; // TODO: support StringComparison constant values - case "StartsWith" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemString, t.SystemStringComparison): // StartsWith(string? value, string? substring, string? message, StringComparison comparisonType) - case "StartsWith" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemString, t.SystemStringComparison, t.ObjectArray): // StartsWith(string? value, string? substring, string? message, StringComparison comparisonType, params object?[]? parameters) + case "StartsWith" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.String, t.StringComparison): // StartsWith(string? value, string? substring, string? message, StringComparison comparisonType) + case "StartsWith" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.String, t.StringComparison, t.ObjectArray): // StartsWith(string? value, string? substring, string? message, StringComparison comparisonType, params object?[]? parameters) break; // TODO: support StringComparison constant values - case "EndsWith" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString): // EndsWith(string? value, string? substring) - case "EndsWith" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemString): // EndsWith(string? value, string? substring, string? message) - case "EndsWith" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemString, t.ObjectArray): // EndsWith(string? value, string? substring, string? message, params object?[]? parameters) + case "EndsWith" when ArgumentsAreTypeOf(invocation, t.String, t.String): // EndsWith(string? value, string? substring) + case "EndsWith" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.String): // EndsWith(string? value, string? substring, string? message) + case "EndsWith" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.String, t.ObjectArray): // EndsWith(string? value, string? substring, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "EndWith", argumentIndex: 0, argumentsToRemove: []); - case "EndsWith" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemStringComparison): // EndsWith(string? value, string? substring, StringComparison comparisonType) + case "EndsWith" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.StringComparison): // EndsWith(string? value, string? substring, StringComparison comparisonType) break; // TODO: support StringComparison constant values - case "EndsWith" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemString, t.SystemStringComparison): // EndsWith(string? value, string? substring, string? message, StringComparison comparisonType) - case "EndsWith" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemString, t.SystemString, t.SystemStringComparison, t.ObjectArray): // EndsWith(string? value, string? substring, string? message, StringComparison comparisonType, params object?[]? parameters) + case "EndsWith" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.String, t.StringComparison): // EndsWith(string? value, string? substring, string? message, StringComparison comparisonType) + case "EndsWith" when ArgumentsAreTypeOf(invocation, t.String, t.String, t.String, t.StringComparison, t.ObjectArray): // EndsWith(string? value, string? substring, string? message, StringComparison comparisonType, params object?[]? parameters) break; // TODO: support StringComparison constant values - case "Matches" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemTextRegularExpressionsRegex): // Matches(string? value, Regex? pattern) - case "Matches" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemTextRegularExpressionsRegex, t.SystemString): // Matches(string? value, Regex? pattern, string? message) - case "Matches" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemTextRegularExpressionsRegex, t.SystemString, t.ObjectArray): // Matches(string? value, Regex? pattern, string? message, params object?[]? parameters) + case "Matches" when ArgumentsAreTypeOf(invocation, t.String, t.Regex): // Matches(string? value, Regex? pattern) + case "Matches" when ArgumentsAreTypeOf(invocation, t.String, t.Regex, t.String): // Matches(string? value, Regex? pattern, string? message) + case "Matches" when ArgumentsAreTypeOf(invocation, t.String, t.Regex, t.String, t.ObjectArray): // Matches(string? value, Regex? pattern, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "MatchRegex", argumentIndex: 0, argumentsToRemove: []); - case "DoesNotMatch" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemTextRegularExpressionsRegex): // DoesNotMatch(string? value, Regex? pattern) - case "DoesNotMatch" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemTextRegularExpressionsRegex, t.SystemString): // DoesNotMatch(string? value, Regex? pattern, string? message) - case "DoesNotMatch" when ArgumentsAreTypeOf(invocation, t.SystemString, t.SystemTextRegularExpressionsRegex, t.SystemString, t.ObjectArray): // DoesNotMatch(string? value, Regex? pattern, string? message, params object?[]? parameters) + case "DoesNotMatch" when ArgumentsAreTypeOf(invocation, t.String, t.Regex): // DoesNotMatch(string? value, Regex? pattern) + case "DoesNotMatch" when ArgumentsAreTypeOf(invocation, t.String, t.Regex, t.String): // DoesNotMatch(string? value, Regex? pattern, string? message) + case "DoesNotMatch" when ArgumentsAreTypeOf(invocation, t.String, t.Regex, t.String, t.ObjectArray): // DoesNotMatch(string? value, Regex? pattern, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotMatchRegex", argumentIndex: 0, argumentsToRemove: []); } return null; } - private CreateChangedDocument TryComputeFixForCollectionAssert(IInvocationOperation invocation, CodeFixContext context, MsTestCodeFixContext t) + private CreateChangedDocument TryComputeFixForCollectionAssert(IInvocationOperation invocation, CodeFixContext context, TestingFrameworkCodeFixContext t) { if (!invocation.Arguments[0].ImplementsOrIsInterface(SpecialType.System_Collections_Generic_IEnumerable_T)) { @@ -274,41 +238,41 @@ private CreateChangedDocument TryComputeFixForCollectionAssert(IInvocationOperat switch (invocation.TargetMethod.Name) { - case "Contains" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemObject): // Contains(ICollection collection, object? element) - case "Contains" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemObject, t.SystemString): // Contains(ICollection collection, object? element, string? message) - case "Contains" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemObject, t.SystemString, t.ObjectArray): // Contains(ICollection collection, object? element, string? message, params object?[]? parameters) + case "Contains" when ArgumentsAreTypeOf(invocation, t.ICollection, t.Object): // Contains(ICollection collection, object? element) + case "Contains" when ArgumentsAreTypeOf(invocation, t.ICollection, t.Object, t.String): // Contains(ICollection collection, object? element, string? message) + case "Contains" when ArgumentsAreTypeOf(invocation, t.ICollection, t.Object, t.String, t.ObjectArray): // Contains(ICollection collection, object? element, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "Contain", argumentIndex: 0, argumentsToRemove: []); - case "DoesNotContain" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemObject): // DoesNotContain(ICollection collection, object? element) - case "DoesNotContain" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemObject, t.SystemString): // DoesNotContain(ICollection collection, object? element, string? message) - case "DoesNotContain" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemObject, t.SystemString, t.ObjectArray): // DoesNotContain(ICollection collection, object? element, string? message, params object?[]? parameters) + case "DoesNotContain" when ArgumentsAreTypeOf(invocation, t.ICollection, t.Object): // DoesNotContain(ICollection collection, object? element) + case "DoesNotContain" when ArgumentsAreTypeOf(invocation, t.ICollection, t.Object, t.String): // DoesNotContain(ICollection collection, object? element, string? message) + case "DoesNotContain" when ArgumentsAreTypeOf(invocation, t.ICollection, t.Object, t.String, t.ObjectArray): // DoesNotContain(ICollection collection, object? element, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotContain", argumentIndex: 0, argumentsToRemove: []); - case "AllItemsAreNotNull" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection): // AllItemsAreInstancesOfType(ICollection collection) - case "AllItemsAreNotNull" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemString): // AllItemsAreInstancesOfType(ICollection collection, string? message) - case "AllItemsAreNotNull" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemString, t.ObjectArray): // AllItemsAreInstancesOfType(ICollection collection, string? message, params object?[]? parameters) + case "AllItemsAreNotNull" when ArgumentsAreTypeOf(invocation, t.ICollection): // AllItemsAreInstancesOfType(ICollection collection) + case "AllItemsAreNotNull" when ArgumentsAreTypeOf(invocation, t.ICollection, t.String): // AllItemsAreInstancesOfType(ICollection collection, string? message) + case "AllItemsAreNotNull" when ArgumentsAreTypeOf(invocation, t.ICollection, t.String, t.ObjectArray): // AllItemsAreInstancesOfType(ICollection collection, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotContainNulls", argumentIndex: 0, argumentsToRemove: []); - case "AllItemsAreUnique" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection): // AllItemsAreUnique(ICollection collection) - case "AllItemsAreUnique" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemString): // AllItemsAreUnique(ICollection collection, string? message) - case "AllItemsAreUnique" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemString, t.ObjectArray): // AllItemsAreUnique(ICollection collection, string? message, params object?[]? parameters) + case "AllItemsAreUnique" when ArgumentsAreTypeOf(invocation, t.ICollection): // AllItemsAreUnique(ICollection collection) + case "AllItemsAreUnique" when ArgumentsAreTypeOf(invocation, t.ICollection, t.String): // AllItemsAreUnique(ICollection collection, string? message) + case "AllItemsAreUnique" when ArgumentsAreTypeOf(invocation, t.ICollection, t.String, t.ObjectArray): // AllItemsAreUnique(ICollection collection, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "OnlyHaveUniqueItems", argumentIndex: 0, argumentsToRemove: []); - case "IsSubsetOf" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection): // IsSubsetOf(ICollection subset, ICollection superset) - case "IsSubsetOf" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection, t.SystemString): // IsSubsetOf(ICollection subset, ICollection superset, string? message) - case "IsSubsetOf" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection, t.SystemString, t.ObjectArray): // IsSubsetOf(ICollection subset, ICollection superset, string? message, params object?[]? parameters) + case "IsSubsetOf" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection): // IsSubsetOf(ICollection subset, ICollection superset) + case "IsSubsetOf" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection, t.String): // IsSubsetOf(ICollection subset, ICollection superset, string? message) + case "IsSubsetOf" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection, t.String, t.ObjectArray): // IsSubsetOf(ICollection subset, ICollection superset, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeSubsetOf", argumentIndex: 0, argumentsToRemove: []); - case "IsNotSubsetOf" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection): // IsNotSubsetOf(ICollection subset, ICollection superset) - case "IsNotSubsetOf" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection, t.SystemString): // IsNotSubsetOf(ICollection subset, ICollection superset, string? message) - case "IsNotSubsetOf" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection, t.SystemString, t.ObjectArray): // IsNotSubsetOf(ICollection subset, ICollection superset, string? message, params object?[]? parameters) + case "IsNotSubsetOf" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection): // IsNotSubsetOf(ICollection subset, ICollection superset) + case "IsNotSubsetOf" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection, t.String): // IsNotSubsetOf(ICollection subset, ICollection superset, string? message) + case "IsNotSubsetOf" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection, t.String, t.ObjectArray): // IsNotSubsetOf(ICollection subset, ICollection superset, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotBeSubsetOf", argumentIndex: 0, argumentsToRemove: []); - case "AreEquivalent" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection): // AreEquivalent(ICollection expected, ICollection actual) - case "AreEquivalent" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection, t.SystemString): // AreEquivalent(ICollection expected, ICollection actual, string? message) - case "AreEquivalent" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection, t.SystemString, t.ObjectArray): // AreEquivalent(ICollection expected, ICollection actual, string? message, params object?[]? parameters) + case "AreEquivalent" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection): // AreEquivalent(ICollection expected, ICollection actual) + case "AreEquivalent" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection, t.String): // AreEquivalent(ICollection expected, ICollection actual, string? message) + case "AreEquivalent" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection, t.String, t.ObjectArray): // AreEquivalent(ICollection expected, ICollection actual, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeEquivalentTo", argumentIndex: 1, argumentsToRemove: []); - case "AreNotEquivalent" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection): // AreNotEquivalent(ICollection expected, ICollection actual) - case "AreNotEquivalent" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection, t.SystemString): // AreNotEquivalent(ICollection expected, ICollection actual, string? message) - case "AreNotEquivalent" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection, t.SystemString, t.ObjectArray): // AreNotEquivalent(ICollection expected, ICollection actual, string? message, params object?[]? parameters) + case "AreNotEquivalent" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection): // AreNotEquivalent(ICollection expected, ICollection actual) + case "AreNotEquivalent" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection, t.String): // AreNotEquivalent(ICollection expected, ICollection actual, string? message) + case "AreNotEquivalent" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection, t.String, t.ObjectArray): // AreNotEquivalent(ICollection expected, ICollection actual, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotBeEquivalentTo", argumentIndex: 1, argumentsToRemove: []); - case "AllItemsAreInstancesOfType" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemType): // AllItemsAreInstancesOfType(ICollection collection, Type expectedType) - case "AllItemsAreInstancesOfType" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemType, t.SystemString): // AllItemsAreInstancesOfType(ICollection collection, Type expectedType, string? message) - case "AllItemsAreInstancesOfType" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemType, t.SystemString, t.ObjectArray): // AllItemsAreInstancesOfType(ICollection collection, Type expectedType, string? message, params object?[]? parameters) + case "AllItemsAreInstancesOfType" when ArgumentsAreTypeOf(invocation, t.ICollection, t.Type): // AllItemsAreInstancesOfType(ICollection collection, Type expectedType) + case "AllItemsAreInstancesOfType" when ArgumentsAreTypeOf(invocation, t.ICollection, t.Type, t.String): // AllItemsAreInstancesOfType(ICollection collection, Type expectedType, string? message) + case "AllItemsAreInstancesOfType" when ArgumentsAreTypeOf(invocation, t.ICollection, t.Type, t.String, t.ObjectArray): // AllItemsAreInstancesOfType(ICollection collection, Type expectedType, string? message, params object?[]? parameters) { if (invocation.Arguments[1].Value is not ITypeOfOperation typeOf) { @@ -317,63 +281,23 @@ private CreateChangedDocument TryComputeFixForCollectionAssert(IInvocationOperat return DocumentEditorUtils.RenameMethodToSubjectShouldGenericAssertion(invocation, ImmutableArray.Create(typeOf.TypeOperand), context, "AllBeOfType", argumentIndex: 0, argumentsToRemove: [1]); } - case "AreEqual" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection): // AreEqual(ICollection expected, ICollection actual) - case "AreEqual" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection, t.SystemString): // AreEqual(ICollection expected, ICollection actual, string? message) - case "AreEqual" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection, t.SystemString, t.ObjectArray): // AreEqual(ICollection expected, ICollection actual, string? message, params object?[]? parameters) + case "AreEqual" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection): // AreEqual(ICollection expected, ICollection actual) + case "AreEqual" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection, t.String): // AreEqual(ICollection expected, ICollection actual, string? message) + case "AreEqual" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection, t.String, t.ObjectArray): // AreEqual(ICollection expected, ICollection actual, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "Equal", argumentIndex: 1, argumentsToRemove: []); - case "AreEqual" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection, t.SystemCollectionsIComparer): // AreEqual(ICollection expected, ICollection actual, IComparer? comparer) - case "AreEqual" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection, t.SystemCollectionsIComparer, t.SystemString): // AreEqual(ICollection expected, ICollection actual, IComparer? comparer, string? message) - case "AreEqual" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection, t.SystemCollectionsIComparer, t.SystemString, t.ObjectArray): // AreEqual(ICollection expected, ICollection actual, IComparer? comparer, string? message, params object?[]? parameters) + case "AreEqual" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection, t.IComparer): // AreEqual(ICollection expected, ICollection actual, IComparer? comparer) + case "AreEqual" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection, t.IComparer, t.String): // AreEqual(ICollection expected, ICollection actual, IComparer? comparer, string? message) + case "AreEqual" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection, t.IComparer, t.String, t.ObjectArray): // AreEqual(ICollection expected, ICollection actual, IComparer? comparer, string? message, params object?[]? parameters) break; // TODO: support IComparer - case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection): // AreNotEqual(ICollection notExpected, ICollection actual) - case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection, t.SystemString): // AreNotEqual(ICollection notExpected, ICollection actual, string? message) - case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection, t.SystemString, t.ObjectArray): // AreNotEqual(ICollection notExpected, ICollection actual, string? message, params object?[]? parameters) + case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection): // AreNotEqual(ICollection notExpected, ICollection actual) + case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection, t.String): // AreNotEqual(ICollection notExpected, ICollection actual, string? message) + case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection, t.String, t.ObjectArray): // AreNotEqual(ICollection notExpected, ICollection actual, string? message, params object?[]? parameters) return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotEqual", argumentIndex: 1, argumentsToRemove: []); - case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection, t.SystemCollectionsIComparer): // AreNotEqual(ICollection notExpected, ICollection actual, IComparer? comparer) - case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection, t.SystemCollectionsIComparer, t.SystemString): // AreNotEqual(ICollection notExpected, ICollection actual, IComparer? comparer, string? message) - case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.SystemCollectionsICollection, t.SystemCollectionsICollection, t.SystemCollectionsIComparer, t.SystemString, t.ObjectArray): // AreNotEqual(ICollection notExpected, ICollection actual, IComparer? comparer, string? message, params object?[]? parameters) + case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection, t.IComparer): // AreNotEqual(ICollection notExpected, ICollection actual, IComparer? comparer) + case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection, t.IComparer, t.String): // AreNotEqual(ICollection notExpected, ICollection actual, IComparer? comparer, string? message) + case "AreNotEqual" when ArgumentsAreTypeOf(invocation, t.ICollection, t.ICollection, t.IComparer, t.String, t.ObjectArray): // AreNotEqual(ICollection notExpected, ICollection actual, IComparer? comparer, string? message, params object?[]? parameters) break; // TODO: support IComparer } return null; } - - private static bool ArgumentsAreTypeOf(IInvocationOperation invocation, params ITypeSymbol[] types) => ArgumentsAreTypeOf(invocation, 0, types); - private static bool ArgumentsAreTypeOf(IInvocationOperation invocation, int startFromIndex, params ITypeSymbol[] types) - { - if (invocation.TargetMethod.Parameters.Length != types.Length + startFromIndex) - { - return false; - } - - for (int i = startFromIndex; i < types.Length; i++) - { - if (!invocation.TargetMethod.Parameters[i].Type.EqualsSymbol(types[i])) - { - return false; - } - } - - return true; - } - - private sealed class MsTestCodeFixContext(Compilation compilation) - { - public INamedTypeSymbol SystemObject { get; } = compilation.ObjectType; - public INamedTypeSymbol SystemString { get; } = compilation.GetTypeByMetadataName("System.String"); - public INamedTypeSymbol SystemFloat { get; } = compilation.GetTypeByMetadataName("System.Single"); - public INamedTypeSymbol SystemDouble { get; } = compilation.GetTypeByMetadataName("System.Double"); - public INamedTypeSymbol SystemDecimal { get; } = compilation.GetTypeByMetadataName("System.Decimal"); - public INamedTypeSymbol SystemBoolean { get; } = compilation.GetTypeByMetadataName("System.Boolean"); - public INamedTypeSymbol SystemAction { get; } = compilation.GetTypeByMetadataName("System.Action"); - public INamedTypeSymbol SystemType { get; } = compilation.GetTypeByMetadataName("System.Type"); - public INamedTypeSymbol SystemFuncOfObject { get; } = compilation.GetTypeByMetadataName("System.Func`1").Construct(compilation.ObjectType); - public INamedTypeSymbol SystemFuncOfTask { get; } = compilation.GetTypeByMetadataName("System.Func`1").Construct(compilation.GetTypeByMetadataName("System.Threading.Tasks.Task")); - public IArrayTypeSymbol ObjectArray { get; } = compilation.CreateArrayTypeSymbol(compilation.ObjectType); - public INamedTypeSymbol SystemGlobalizationCultureInfo { get; } = compilation.GetTypeByMetadataName("System.Globalization.CultureInfo"); - public INamedTypeSymbol SystemStringComparison { get; } = compilation.GetTypeByMetadataName("System.StringComparison"); - public INamedTypeSymbol SystemTextRegularExpressionsRegex { get; } = compilation.GetTypeByMetadataName("System.Text.RegularExpressions.Regex"); - public INamedTypeSymbol SystemCollectionsICollection { get; } = compilation.GetTypeByMetadataName("System.Collections.ICollection"); - public INamedTypeSymbol SystemCollectionsIComparer { get; } = compilation.GetTypeByMetadataName("System.Collections.IComparer"); - - } } diff --git a/src/FluentAssertions.Analyzers/Tips/TestingFrameworkCodeFixProvider.cs b/src/FluentAssertions.Analyzers/Tips/TestingFrameworkCodeFixProvider.cs new file mode 100644 index 00000000..3ef4a3cf --- /dev/null +++ b/src/FluentAssertions.Analyzers/Tips/TestingFrameworkCodeFixProvider.cs @@ -0,0 +1,136 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using FluentAssertions.Analyzers.Utilities; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Operations; +using CreateChangedDocument = System.Func>; + +namespace FluentAssertions.Analyzers; + +public abstract class TestingFrameworkCodeFixProvider : CodeFixProvider +{ + protected const string Title = "Replace with FluentAssertions"; + + public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; + + public override async Task RegisterCodeFixesAsync(CodeFixContext context) + { + var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken); + var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken); + + var testContext = new TestingFrameworkCodeFixContext(semanticModel.Compilation); + foreach (var diagnostic in context.Diagnostics) + { + var node = root.FindNode(diagnostic.Location.SourceSpan); + if (node is not InvocationExpressionSyntax invocationExpression) + { + continue; + } + + var operation = semanticModel.GetOperation(invocationExpression, context.CancellationToken); + if (operation is not IInvocationOperation invocation) + { + continue; + } + + var fix = TryComputeFix(invocation, context, testContext, diagnostic); + if (fix is not null) + { + context.RegisterCodeFix(CodeAction.Create(Title, fix, equivalenceKey: Title), diagnostic); + } + } + } + + protected abstract CreateChangedDocument TryComputeFix(IInvocationOperation invocation, CodeFixContext context, TestingFrameworkCodeFixContext t, Diagnostic diagnostic); + + protected static bool ArgumentsAreTypeOf(IInvocationOperation invocation, params ITypeSymbol[] types) => ArgumentsAreTypeOf(invocation, 0, types); + protected static bool ArgumentsAreTypeOf(IInvocationOperation invocation, int startFromIndex, params ITypeSymbol[] types) + { + if (invocation.TargetMethod.Parameters.Length != types.Length + startFromIndex) + { + return false; + } + + for (int i = startFromIndex; i < types.Length; i++) + { + if (!invocation.TargetMethod.Parameters[i].Type.EqualsSymbol(types[i])) + { + return false; + } + } + + return true; + } + + protected static bool ArgumentsAreGenericTypeOf(IInvocationOperation invocation, params ITypeSymbol[] types) + { + const int generics = 1; + if (invocation.TargetMethod.Parameters.Length != types.Length) + { + return false; + } + + if (invocation.TargetMethod.TypeArguments.Length != generics) + { + return false; + } + + var genericType = invocation.TargetMethod.TypeArguments[0]; + + for (int i = 0; i < types.Length; i++) + { + if (invocation.TargetMethod.Parameters[i].Type is not INamedTypeSymbol parameterType) + { + return false; + } + + if (parameterType.TypeArguments.IsEmpty && parameterType.EqualsSymbol(genericType)) + { + continue; + } + + if (parameterType.TypeArguments.Length != generics + || !(parameterType.TypeArguments[0].EqualsSymbol(genericType) && parameterType.OriginalDefinition.EqualsSymbol(types[i]))) + { + return false; + } + } + + return true; + } + + protected static bool ArgumentsCount(IInvocationOperation invocation, int arguments) + { + return invocation.TargetMethod.Parameters.Length == arguments; + } + + protected sealed class TestingFrameworkCodeFixContext(Compilation compilation) + { + public INamedTypeSymbol Object { get; } = compilation.ObjectType; + public INamedTypeSymbol String { get; } = compilation.GetTypeByMetadataName("System.String"); + public INamedTypeSymbol Int32 { get; } = compilation.GetTypeByMetadataName("System.Int32"); + public INamedTypeSymbol Float { get; } = compilation.GetTypeByMetadataName("System.Single"); + public INamedTypeSymbol Double { get; } = compilation.GetTypeByMetadataName("System.Double"); + public INamedTypeSymbol Decimal { get; } = compilation.GetTypeByMetadataName("System.Decimal"); + public INamedTypeSymbol Boolean { get; } = compilation.GetTypeByMetadataName("System.Boolean"); + public INamedTypeSymbol Action { get; } = compilation.GetTypeByMetadataName("System.Action"); + public INamedTypeSymbol Type { get; } = compilation.GetTypeByMetadataName("System.Type"); + public INamedTypeSymbol DateTime { get; } = compilation.GetTypeByMetadataName("System.DateTime"); + public INamedTypeSymbol TimeSpan { get; } = compilation.GetTypeByMetadataName("System.TimeSpan"); + public INamedTypeSymbol FuncOfObject { get; } = compilation.GetTypeByMetadataName("System.Func`1").Construct(compilation.ObjectType); + public INamedTypeSymbol FuncOfTask { get; } = compilation.GetTypeByMetadataName("System.Func`1").Construct(compilation.GetTypeByMetadataName("System.Threading.Tasks.Task")); + public IArrayTypeSymbol ObjectArray { get; } = compilation.CreateArrayTypeSymbol(compilation.ObjectType); + public INamedTypeSymbol CultureInfo { get; } = compilation.GetTypeByMetadataName("System.Globalization.CultureInfo"); + public INamedTypeSymbol StringComparison { get; } = compilation.GetTypeByMetadataName("System.StringComparison"); + public INamedTypeSymbol Regex { get; } = compilation.GetTypeByMetadataName("System.Text.RegularExpressions.Regex"); + public INamedTypeSymbol ICollection { get; } = compilation.GetTypeByMetadataName("System.Collections.ICollection"); + public INamedTypeSymbol IComparer { get; } = compilation.GetTypeByMetadataName("System.Collections.IComparer"); + public INamedTypeSymbol IEqualityComparerOfT1 { get; } = compilation.GetTypeByMetadataName("System.Collections.Generic.IEqualityComparer`1"); + public INamedTypeSymbol IEnumerableOfT1 { get; } = compilation.GetTypeByMetadataName("System.Collections.Generic.IEnumerable`1"); + + public INamedTypeSymbol Identity { get; } = null; + } +} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertContains.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertContains.cs deleted file mode 100644 index 093d005b..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertContains.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; -using FluentAssertions.Analyzers.Utilities; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; - -namespace FluentAssertions.Analyzers.Xunit; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class AssertContainsAnalyzer : XunitAnalyzer -{ - public const string DiagnosticId = Constants.Tips.Xunit.AssertContains; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().Contain()."; - - protected override DiagnosticDescriptor Rule => new(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - - protected override IEnumerable Visitors => new FluentAssertionsCSharpSyntaxVisitor[] - { - new AssertContainsStringSyntaxVisitor(), - new AssertContainsSetSyntaxVisitor() - }; - - //public static void Contains(string expectedSubstring, string? actualString) - public class AssertContainsStringSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertContainsStringSyntaxVisitor() : base( - MemberValidator.ArgumentsMatch("Contains", - ArgumentValidator.IsType(TypeSelector.GetStringType), - ArgumentValidator.IsType(TypeSelector.GetStringType)) - ) - { - } - } - - //public static void Contains(T expected, ISet actual) - //public static void Contains(T expected, IReadOnlySet actual) - //public static void Contains(T expected, HashSet actual) - //public static void Contains(T expected, ImmutableHashSet actual) - public class AssertContainsSetSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertContainsSetSyntaxVisitor() : base( - MemberValidator.ArgumentsMatch("Contains", - ArgumentValidator.Exists(), - ArgumentValidator.IsTypeOrConstructedFromTypeOrImplementsType(SpecialType.System_Collections_IEnumerable)) - ) - { - } - } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertContainsCodeFix)), Shared] -public class AssertContainsCodeFix : XunitCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertContainsAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression( - ExpressionSyntax expression, - FluentAssertionsDiagnosticProperties properties) - { - switch (properties.VisitorName) - { - case nameof(AssertContainsAnalyzer.AssertContainsStringSyntaxVisitor): - case nameof(AssertContainsAnalyzer.AssertContainsSetSyntaxVisitor): - return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "Contains", "Contain"); - default: - throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); - } - } -} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertDoesNotContain.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertDoesNotContain.cs deleted file mode 100644 index 84e4f9c2..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertDoesNotContain.cs +++ /dev/null @@ -1,74 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; -using FluentAssertions.Analyzers.Utilities; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; - -namespace FluentAssertions.Analyzers.Xunit; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class AssertDoesNotContainAnalyzer : XunitAnalyzer -{ - public const string DiagnosticId = Constants.Tips.Xunit.AssertDoesNotContain; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().NotContain()."; - - protected override DiagnosticDescriptor Rule => new(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - - protected override IEnumerable Visitors => new FluentAssertionsCSharpSyntaxVisitor[] - { - new AssertDoesNotContainStringSyntaxVisitor(), - new AssertDoesNotContainSetSyntaxVisitor() - }; - - //public static void DoesNotContain(string expectedSubstring, string? actualString) - public class AssertDoesNotContainStringSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertDoesNotContainStringSyntaxVisitor() : base( - MemberValidator.ArgumentsMatch("DoesNotContain", - ArgumentValidator.IsType(TypeSelector.GetStringType), - ArgumentValidator.IsType(TypeSelector.GetStringType)) - ) - { - } - } - - //public static void DoesNotContain(T expected, ISet actual) - //public static void DoesNotContain(T expected, IReadOnlySet actual) - //public static void DoesNotContain(T expected, HashSet actual) - //public static void DoesNotContain(T expected, ImmutableHashSet actual) - public class AssertDoesNotContainSetSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertDoesNotContainSetSyntaxVisitor() : base( - MemberValidator.ArgumentsMatch("DoesNotContain", - ArgumentValidator.Exists(), - ArgumentValidator.IsTypeOrConstructedFromTypeOrImplementsType(SpecialType.System_Collections_IEnumerable)) - ) - { - } - } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertDoesNotContainCodeFix)), Shared] -public class AssertDoesNotContainCodeFix : XunitCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertDoesNotContainAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression( - ExpressionSyntax expression, - FluentAssertionsDiagnosticProperties properties) - { - switch (properties.VisitorName) - { - case nameof(AssertDoesNotContainAnalyzer.AssertDoesNotContainStringSyntaxVisitor): - case nameof(AssertDoesNotContainAnalyzer.AssertDoesNotContainSetSyntaxVisitor): - return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "DoesNotContain", "NotContain"); - default: - throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); - } - } -} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertDoesNotMatch.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertDoesNotMatch.cs deleted file mode 100644 index e048a7ab..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertDoesNotMatch.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; -using FluentAssertions.Analyzers.Utilities; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; - -namespace FluentAssertions.Analyzers.Xunit; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class AssertDoesNotMatchAnalyzer : XunitAnalyzer -{ - public const string DiagnosticId = Constants.Tips.Xunit.AssertDoesNotMatch; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().NotMatchRegex()"; - - protected override DiagnosticDescriptor Rule => new(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - - protected override IEnumerable Visitors => new FluentAssertionsCSharpSyntaxVisitor[] - { - new AssertDoesNotMatchStringSyntaxVisitor() - }; - - //public static void DoesNotMatch(string expectedRegexPattern, string? actualString) - //public static void DoesNotMatch(Regex expectedRegex, string? actualString) - public class AssertDoesNotMatchStringSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertDoesNotMatchStringSyntaxVisitor() : base( - MemberValidator.ArgumentsMatch("DoesNotMatch", - ArgumentValidator.IsAnyType(TypeSelector.GetStringType, TypeSelector.GetRegexType), - ArgumentValidator.IsType(TypeSelector.GetStringType)) - ) - { - } - } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertDoesNotMatchCodeFix)), Shared] -public class AssertDoesNotMatchCodeFix : XunitCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertDoesNotMatchAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression( - ExpressionSyntax expression, - FluentAssertionsDiagnosticProperties properties) - { - switch (properties.VisitorName) - { - case nameof(AssertDoesNotMatchAnalyzer.AssertDoesNotMatchStringSyntaxVisitor): - return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "DoesNotMatch", "NotMatchRegex"); - default: - throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); - } - } -} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertEmpty.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertEmpty.cs deleted file mode 100644 index d0e73f2b..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertEmpty.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; -using FluentAssertions.Analyzers.Utilities; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; - -namespace FluentAssertions.Analyzers.Xunit; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class AssertEmptyAnalyzer : XunitAnalyzer -{ - public const string DiagnosticId = Constants.Tips.Xunit.AssertEmpty; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().BeEmpty()"; - - protected override DiagnosticDescriptor Rule => new(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - - protected override IEnumerable Visitors => new FluentAssertionsCSharpSyntaxVisitor[] - { - new AssertEmptyStringSyntaxVisitor() - }; - - //public static void Empty(string value) - public class AssertEmptyStringSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertEmptyStringSyntaxVisitor() : base( - MemberValidator.ArgumentsMatch("Empty", - ArgumentValidator.IsType(TypeSelector.GetStringType)) - ) - { - } - } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertEmptyCodeFix)), Shared] -public class AssertEmptyCodeFix : XunitCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertEmptyAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression( - ExpressionSyntax expression, - FluentAssertionsDiagnosticProperties properties) - { - switch (properties.VisitorName) - { - case nameof(AssertEmptyAnalyzer.AssertEmptyStringSyntaxVisitor): - return RenameMethodAndReplaceWithSubjectShould(expression, "Empty", "BeEmpty"); - default: - throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); - } - } -} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertEndsWith.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertEndsWith.cs deleted file mode 100644 index 82c43812..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertEndsWith.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; -using FluentAssertions.Analyzers.Utilities; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; - -namespace FluentAssertions.Analyzers.Xunit; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class AssertEndsWithAnalyzer : XunitAnalyzer -{ - public const string DiagnosticId = Constants.Tips.Xunit.AssertEndsWith; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().EndWith()"; - - protected override DiagnosticDescriptor Rule => new(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - - protected override IEnumerable Visitors => new FluentAssertionsCSharpSyntaxVisitor[] - { - new AssertEndsWithStringSyntaxVisitor() - }; - - //public static void EndsWith(string? expectedEndString, string? actualString) - public class AssertEndsWithStringSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertEndsWithStringSyntaxVisitor() : base( - MemberValidator.ArgumentsMatch("EndsWith", - ArgumentValidator.IsType(TypeSelector.GetStringType), - ArgumentValidator.IsType(TypeSelector.GetStringType)) - ) - { - } - } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertEndsWithCodeFix)), Shared] -public class AssertEndsWithCodeFix : XunitCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertEndsWithAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression( - ExpressionSyntax expression, - FluentAssertionsDiagnosticProperties properties) - { - switch (properties.VisitorName) - { - case nameof(AssertEndsWithAnalyzer.AssertEndsWithStringSyntaxVisitor): - return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "EndsWith", "EndWith"); - default: - throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); - } - } -} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertEqual.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertEqual.cs deleted file mode 100644 index 68f58b47..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertEqual.cs +++ /dev/null @@ -1,158 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using FluentAssertions.Analyzers.Utilities; - -namespace FluentAssertions.Analyzers.Xunit; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class AssertEqualAnalyzer : XunitAnalyzer -{ - public const string DiagnosticId = Constants.Tips.Xunit.AssertEqual; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().BeApproximately() for complex numbers, .Should().BeEquivalentTo() for comparer, and .Should().Be() for other cases."; - - protected override DiagnosticDescriptor Rule => new(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors => new FluentAssertionsCSharpSyntaxVisitor[] - { - new AssertStringEqualSyntaxVisitor(), - new AssertFloatEqualWithToleranceSyntaxVisitor(), - new AssertDoubleEqualWithToleranceSyntaxVisitor(), - new AssertDoubleEqualWithPrecisionSyntaxVisitor(), - new AssertDecimalEqualWithPrecisionSyntaxVisitor(), - new AssertDateTimeEqualSyntaxVisitor(), - new AssertObjectEqualWithComparerSyntaxVisitor(), - new AssertObjectEqualSyntaxVisitor() - }; - - // public static void Equal(string? expected, string? actual) - public class AssertStringEqualSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertStringEqualSyntaxVisitor() : base( - MemberValidator.ArgumentsMatch("Equal", - ArgumentValidator.IsType(TypeSelector.GetStringType), - ArgumentValidator.IsType(TypeSelector.GetStringType))) - { - } - } - - // public static void Equal(float expected, float actual, float tolerance) - public class AssertFloatEqualWithToleranceSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertFloatEqualWithToleranceSyntaxVisitor() : base( - MemberValidator.ArgumentsMatch("Equal", - ArgumentValidator.IsType(TypeSelector.GetFloatType), - ArgumentValidator.IsType(TypeSelector.GetFloatType), - ArgumentValidator.IsType(TypeSelector.GetFloatType)) - ) - { - } - } - - // public static void Equal(double expected, double actual, double tolerance) - public class AssertDoubleEqualWithToleranceSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertDoubleEqualWithToleranceSyntaxVisitor() : base( - MemberValidator.ArgumentsMatch("Equal", - ArgumentValidator.IsType(TypeSelector.GetDoubleType), - ArgumentValidator.IsType(TypeSelector.GetDoubleType), - ArgumentValidator.IsType(TypeSelector.GetDoubleType)) - ) - { - } - } - - // public static void Equal(double expected, double actual, int precision) - public class AssertDoubleEqualWithPrecisionSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertDoubleEqualWithPrecisionSyntaxVisitor() : base( - MemberValidator.ArgumentsMatch("Equal", - ArgumentValidator.IsType(TypeSelector.GetDoubleType), - ArgumentValidator.IsType(TypeSelector.GetDoubleType), - ArgumentValidator.IsType(TypeSelector.GetIntType)) - ) - { - } - } - - // public static void Equal(decimal expected, decimal actual, int precision) - // public static void Equal(double expected, double actual, int precision, MidpointRounding rounding) - public class AssertDecimalEqualWithPrecisionSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertDecimalEqualWithPrecisionSyntaxVisitor() : base( - MemberValidator.ArgumentsMatch("Equal", - ArgumentValidator.IsType(TypeSelector.GetDecimalType), - ArgumentValidator.IsType(TypeSelector.GetDecimalType), - ArgumentValidator.IsType(TypeSelector.GetIntType)) - ) - { - } - } - - // public static void Equal(DateTime expected, DateTime actual, TimeSpan precision) - public class AssertDateTimeEqualSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertDateTimeEqualSyntaxVisitor() : base( - MemberValidator.ArgumentsMatch("Equal", - ArgumentValidator.IsType(TypeSelector.GetDateTimeType), - ArgumentValidator.IsType(TypeSelector.GetDateTimeType), - ArgumentValidator.IsType(TypeSelector.GetTimeSpanType))) - { - } - } - - // public static void Equal(T expected, T actual, IEqualityComparer comparer) - public class AssertObjectEqualWithComparerSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertObjectEqualWithComparerSyntaxVisitor() : base( - MemberValidator.HasArguments("Equal", count: 3)) - { - } - } - - // public static void Equal(T expected, T actual) - public class AssertObjectEqualSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertObjectEqualSyntaxVisitor() : base(MemberValidator.HasArguments("Equal", count: 2)) - { - } - } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertEqualCodeFix)), Shared] -public class AssertEqualCodeFix : XunitCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertEqualAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression( - ExpressionSyntax expression, - FluentAssertionsDiagnosticProperties properties) - { - switch (properties.VisitorName) - { - case nameof(AssertEqualAnalyzer.AssertFloatEqualWithToleranceSyntaxVisitor): - case nameof(AssertEqualAnalyzer.AssertDoubleEqualWithToleranceSyntaxVisitor): - return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "Equal", "BeApproximately"); - case nameof(AssertEqualAnalyzer.AssertDoubleEqualWithPrecisionSyntaxVisitor): - case nameof(AssertEqualAnalyzer.AssertDecimalEqualWithPrecisionSyntaxVisitor): - // There is no corresponding API in FluentAssertions - return expression; - case nameof(AssertEqualAnalyzer.AssertObjectEqualWithComparerSyntaxVisitor): - return GetNewExpressionForEqualityWithComparer(expression, "Equal", "BeEquivalentTo"); - case nameof(AssertEqualAnalyzer.AssertDateTimeEqualSyntaxVisitor): - return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "Equal", "BeCloseTo"); - case nameof(AssertEqualAnalyzer.AssertObjectEqualSyntaxVisitor): - case nameof(AssertEqualAnalyzer.AssertStringEqualSyntaxVisitor): - return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "Equal", "Be"); - default: - throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); - } - } -} diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertFalse.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertFalse.cs deleted file mode 100644 index 7b06af91..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertFalse.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; - -namespace FluentAssertions.Analyzers.Xunit; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class AssertFalseAnalyzer : XunitAnalyzer -{ - public const string DiagnosticId = Constants.Tips.Xunit.AssertFalse; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().BeFalse() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors - { - get - { - yield return new AssertFalseSyntaxVisitor(); - } - } - - public class AssertFalseSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertFalseSyntaxVisitor() : base(new MemberValidator("False")) - { - } - } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertFalseCodeFix)), Shared] -public class AssertFalseCodeFix : XunitCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertFalseAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - return RenameMethodAndReplaceWithSubjectShould(expression, "False", "BeFalse"); - } -} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertIsAssignableFrom.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertIsAssignableFrom.cs deleted file mode 100644 index 524beb41..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertIsAssignableFrom.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; -using System.Linq; -using FluentAssertions.Analyzers.Utilities; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using SF = Microsoft.CodeAnalysis.CSharp.SyntaxFactory; - -namespace FluentAssertions.Analyzers.Xunit; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class AssertIsAssignableFromAnalyzer : XunitAnalyzer -{ - public const string DiagnosticId = Constants.Tips.Xunit.AssertIsAssignableFrom; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().BeAssignableTo()."; - - protected override DiagnosticDescriptor Rule => new(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - - protected override IEnumerable Visitors => new FluentAssertionsCSharpSyntaxVisitor[] - { - new AssertIsAssignableFromGenericTypeSyntaxVisitor(), - new AssertIsAssignableFromTypeSyntaxVisitor() - }; - - //public static T IsAssignableFrom(object? @object) - public class AssertIsAssignableFromGenericTypeSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertIsAssignableFromGenericTypeSyntaxVisitor() : base( - MemberValidator.HasArguments("IsAssignableFrom", 1) - ) - { - } - } - - //public static T IsAssignableFrom(Type expectedType, object? @object) - public class AssertIsAssignableFromTypeSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertIsAssignableFromTypeSyntaxVisitor() : base( - MemberValidator.HasArguments("IsAssignableFrom", 2) - ) - { - } - } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertIsAssignableFromCodeFix)), Shared] -public class AssertIsAssignableFromCodeFix : XunitCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertIsAssignableFromAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression( - ExpressionSyntax expression, - FluentAssertionsDiagnosticProperties properties) - { - switch (properties.VisitorName) - { - case nameof(AssertIsAssignableFromAnalyzer.AssertIsAssignableFromGenericTypeSyntaxVisitor): - return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "IsAssignableFrom", "BeAssignableTo", argumentIndex: 0); - case nameof(AssertIsAssignableFromAnalyzer.AssertIsAssignableFromTypeSyntaxVisitor): - var newExpression = RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "IsAssignableFrom", "BeAssignableTo"); - return ReplaceTypeOfArgumentWithGenericTypeIfExists(newExpression, "BeAssignableTo"); - default: - throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); - } - } -} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertIsNotAssignableFrom.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertIsNotAssignableFrom.cs deleted file mode 100644 index 28c64f35..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertIsNotAssignableFrom.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; -using System.Linq; -using FluentAssertions.Analyzers.Utilities; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using SF = Microsoft.CodeAnalysis.CSharp.SyntaxFactory; - -namespace FluentAssertions.Analyzers.Xunit; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class AssertIsNotAssignableFromAnalyzer : XunitAnalyzer -{ - public const string DiagnosticId = Constants.Tips.Xunit.AssertIsNotAssignableFrom; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().NotBeAssignableTo()."; - - protected override DiagnosticDescriptor Rule => new(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - - protected override IEnumerable Visitors => new FluentAssertionsCSharpSyntaxVisitor[] - { - new AssertIsNotAssignableFromGenericTypeSyntaxVisitor(), - new AssertIsNotAssignableFromTypeSyntaxVisitor() - }; - - //public static T IsNotAssignableFrom(object? @object) - public class AssertIsNotAssignableFromGenericTypeSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertIsNotAssignableFromGenericTypeSyntaxVisitor() : base( - MemberValidator.HasArguments("IsNotAssignableFrom", 1) - ) - { - } - } - - //public static T IsNotAssignableFrom(Type expectedType, object? @object) - public class AssertIsNotAssignableFromTypeSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertIsNotAssignableFromTypeSyntaxVisitor() : base( - MemberValidator.HasArguments("IsNotAssignableFrom", 2) - ) - { - } - } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertIsNotAssignableFromCodeFix)), Shared] -public class AssertIsNotAssignableFromCodeFix : XunitCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertIsNotAssignableFromAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression( - ExpressionSyntax expression, - FluentAssertionsDiagnosticProperties properties) - { - switch (properties.VisitorName) - { - case nameof(AssertIsNotAssignableFromAnalyzer.AssertIsNotAssignableFromGenericTypeSyntaxVisitor): - return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "IsNotAssignableFrom", "NotBeAssignableTo", argumentIndex: 0); - case nameof(AssertIsNotAssignableFromAnalyzer.AssertIsNotAssignableFromTypeSyntaxVisitor): - var newExpression = RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "IsNotAssignableFrom", "NotBeAssignableTo"); - return ReplaceTypeOfArgumentWithGenericTypeIfExists(newExpression, "NotBeAssignableTo"); - default: - throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); - } - } -} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertIsNotType.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertIsNotType.cs deleted file mode 100644 index 177a2571..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertIsNotType.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; -using System.Linq; -using FluentAssertions.Analyzers.Utilities; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using SF = Microsoft.CodeAnalysis.CSharp.SyntaxFactory; - -namespace FluentAssertions.Analyzers.Xunit; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class AssertIsNotTypeAnalyzer : XunitAnalyzer -{ - public const string DiagnosticId = Constants.Tips.Xunit.AssertIsNotType; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().NotBeOfType()."; - - protected override DiagnosticDescriptor Rule => new(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - - protected override IEnumerable Visitors => new FluentAssertionsCSharpSyntaxVisitor[] - { - new AssertIsNotTypeGenericTypeSyntaxVisitor(), - new AssertIsNotTypeTypeSyntaxVisitor() - }; - - //public static T IsNotType(object? @object) - public class AssertIsNotTypeGenericTypeSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertIsNotTypeGenericTypeSyntaxVisitor() : base( - MemberValidator.HasArguments("IsNotType", 1) - ) - { - } - } - - //public static T IsNotType(Type expectedType, object? @object) - public class AssertIsNotTypeTypeSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertIsNotTypeTypeSyntaxVisitor() : base( - MemberValidator.HasArguments("IsNotType", 2) - ) - { - } - } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertIsNotTypeCodeFix)), Shared] -public class AssertIsNotTypeCodeFix : XunitCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertIsNotTypeAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression( - ExpressionSyntax expression, - FluentAssertionsDiagnosticProperties properties) - { - switch (properties.VisitorName) - { - case nameof(AssertIsNotTypeAnalyzer.AssertIsNotTypeGenericTypeSyntaxVisitor): - return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "IsNotType", "NotBeOfType", argumentIndex: 0); - case nameof(AssertIsNotTypeAnalyzer.AssertIsNotTypeTypeSyntaxVisitor): - var newExpression = RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "IsNotType", "NotBeOfType"); - return ReplaceTypeOfArgumentWithGenericTypeIfExists(newExpression, "NotBeOfType"); - default: - throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); - } - } -} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertIsType.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertIsType.cs deleted file mode 100644 index 90a5805d..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertIsType.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; -using System.Linq; -using FluentAssertions.Analyzers.Utilities; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using SF = Microsoft.CodeAnalysis.CSharp.SyntaxFactory; - -namespace FluentAssertions.Analyzers.Xunit; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class AssertIsTypeAnalyzer : XunitAnalyzer -{ - public const string DiagnosticId = Constants.Tips.Xunit.AssertIsType; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().BeOfType()."; - - protected override DiagnosticDescriptor Rule => new(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - - protected override IEnumerable Visitors => new FluentAssertionsCSharpSyntaxVisitor[] - { - new AssertIsTypeGenericTypeSyntaxVisitor(), - new AssertIsTypeTypeSyntaxVisitor() - }; - - //public static T IsType(object? @object) - public class AssertIsTypeGenericTypeSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertIsTypeGenericTypeSyntaxVisitor() : base( - MemberValidator.HasArguments("IsType", 1) - ) - { - } - } - - //public static T IsType(Type expectedType, object? @object) - public class AssertIsTypeTypeSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertIsTypeTypeSyntaxVisitor() : base( - MemberValidator.HasArguments("IsType", 2) - ) - { - } - } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertIsTypeCodeFix)), Shared] -public class AssertIsTypeCodeFix : XunitCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertIsTypeAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression( - ExpressionSyntax expression, - FluentAssertionsDiagnosticProperties properties) - { - switch (properties.VisitorName) - { - case nameof(AssertIsTypeAnalyzer.AssertIsTypeGenericTypeSyntaxVisitor): - return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "IsType", "BeOfType", argumentIndex: 0); - case nameof(AssertIsTypeAnalyzer.AssertIsTypeTypeSyntaxVisitor): - var newExpression = RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "IsType", "BeOfType"); - return ReplaceTypeOfArgumentWithGenericTypeIfExists(newExpression, "BeOfType"); - default: - throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); - } - } -} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertMatches.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertMatches.cs deleted file mode 100644 index a88b171f..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertMatches.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; -using FluentAssertions.Analyzers.Utilities; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; - -namespace FluentAssertions.Analyzers.Xunit; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class AssertMatchesAnalyzer : XunitAnalyzer -{ - public const string DiagnosticId = Constants.Tips.Xunit.AssertMatches; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().MatchRegex()"; - - protected override DiagnosticDescriptor Rule => new(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - - protected override IEnumerable Visitors => new FluentAssertionsCSharpSyntaxVisitor[] - { - new AssertMatchesStringSyntaxVisitor() - }; - - //public static void Matches(string expectedRegexPattern, string? actualString) - //public static void Matches(Regex expectedRegex, string? actualString) - public class AssertMatchesStringSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertMatchesStringSyntaxVisitor() : base( - MemberValidator.ArgumentsMatch("Matches", - ArgumentValidator.IsAnyType(TypeSelector.GetStringType, TypeSelector.GetRegexType), - ArgumentValidator.IsType(TypeSelector.GetStringType)) - ) - { - } - } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertMatchesCodeFix)), Shared] -public class AssertMatchesCodeFix : XunitCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertMatchesAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression( - ExpressionSyntax expression, - FluentAssertionsDiagnosticProperties properties) - { - switch (properties.VisitorName) - { - case nameof(AssertMatchesAnalyzer.AssertMatchesStringSyntaxVisitor): - return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "Matches", "MatchRegex"); - default: - throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); - } - } -} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertNotEqual.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertNotEqual.cs deleted file mode 100644 index a7d1b053..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertNotEqual.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using FluentAssertions.Analyzers.Utilities; - -namespace FluentAssertions.Analyzers.Xunit; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class AssertNotEqualAnalyzer : XunitAnalyzer -{ - public const string DiagnosticId = Constants.Tips.Xunit.AssertNotEqual; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().NotBeEquivalentTo() for comparer and .Should().NotBe() for other cases."; - - protected override DiagnosticDescriptor Rule => new(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors - { - get - { - yield return new AssertDoubleNotEqualWithPrecisionSyntaxVisitor(); - yield return new AssertDecimalNotEqualWithPrecisionSyntaxVisitor(); - yield return new AssertObjectNotEqualWithComparerSyntaxVisitor(); - yield return new AssertObjectNotEqualSyntaxVisitor(); - } - } - - // public static void NotEqual(double expected, double actual, int precision) - public class AssertDoubleNotEqualWithPrecisionSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertDoubleNotEqualWithPrecisionSyntaxVisitor() : base( - MemberValidator.ArgumentsMatch("NotEqual", - ArgumentValidator.IsType(TypeSelector.GetDoubleType), - ArgumentValidator.IsType(TypeSelector.GetDoubleType), - ArgumentValidator.IsType(TypeSelector.GetIntType)) - ) - { - } - } - - // public static void NotEqual(decimal expected, decimal actual, int precision) - public class AssertDecimalNotEqualWithPrecisionSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertDecimalNotEqualWithPrecisionSyntaxVisitor() : base( - MemberValidator.ArgumentsMatch("NotEqual", - ArgumentValidator.IsType(TypeSelector.GetDecimalType), - ArgumentValidator.IsType(TypeSelector.GetDecimalType), - ArgumentValidator.IsType(TypeSelector.GetIntType)) - ) - { - } - } - - // public static void NotEqual(T expected, T actual, IEqualityComparer comparer) - public class AssertObjectNotEqualWithComparerSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertObjectNotEqualWithComparerSyntaxVisitor() : base( - MemberValidator.HasArguments("NotEqual", count: 3)) - { - } - } - - // public static void NotEqual(T expected, T actual) - public class AssertObjectNotEqualSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertObjectNotEqualSyntaxVisitor() : base( - MemberValidator.HasArguments("NotEqual", count: 2)) - { - } - } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertNotEqualCodeFix)), Shared] -public class AssertNotEqualCodeFix : XunitCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertNotEqualAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression( - ExpressionSyntax expression, - FluentAssertionsDiagnosticProperties properties) - { - switch (properties.VisitorName) - { - case nameof(AssertNotEqualAnalyzer.AssertDoubleNotEqualWithPrecisionSyntaxVisitor): - case nameof(AssertNotEqualAnalyzer.AssertDecimalNotEqualWithPrecisionSyntaxVisitor): - // There is no corresponding API in FluentAssertions - return expression; - case nameof(AssertNotEqualAnalyzer.AssertObjectNotEqualWithComparerSyntaxVisitor): - return GetNewExpressionForEqualityWithComparer(expression, "NotEqual", "NotBeEquivalentTo"); - case nameof(AssertNotEqualAnalyzer.AssertObjectNotEqualSyntaxVisitor): - return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "NotEqual", "NotBe"); - default: - throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); - } - } -} diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertNotNull.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertNotNull.cs deleted file mode 100644 index 1576cc00..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertNotNull.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; - -namespace FluentAssertions.Analyzers.Xunit; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class AssertNotNullAnalyzer : XunitAnalyzer -{ - public const string DiagnosticId = Constants.Tips.Xunit.AssertNotNull; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().NotBeNull() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors - { - get - { - yield return new AssertNotNullSyntaxVisitor(); - } - } - - public class AssertNotNullSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertNotNullSyntaxVisitor() : base(new MemberValidator("NotNull")) - { - } - } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertNotNullCodeFix)), Shared] -public class AssertNotNullCodeFix : XunitCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertNotNullAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - return RenameMethodAndReplaceWithSubjectShould(expression, "NotNull", "NotBeNull"); - } -} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertNotSame.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertNotSame.cs deleted file mode 100644 index b25d5e37..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertNotSame.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; - -namespace FluentAssertions.Analyzers.Xunit; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class AssertNotSameAnalyzer : XunitAnalyzer -{ - public const string DiagnosticId = Constants.Tips.Xunit.AssertNotSame; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().NotBeSameAs() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors - { - get - { - yield return new AssertNotSameSyntaxVisitor(); - } - } - - public class AssertNotSameSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertNotSameSyntaxVisitor() : base(new MemberValidator("NotSame")) - { - } - } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertNotSameCodeFix)), Shared] -public class AssertNotSameCodeFix : XunitCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertNotSameAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "NotSame", "NotBeSameAs"); - } -} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertNotStrictEqual.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertNotStrictEqual.cs deleted file mode 100644 index 257c2fea..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertNotStrictEqual.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using FluentAssertions.Analyzers.Utilities; - -namespace FluentAssertions.Analyzers.Xunit; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class AssertNotStrictEqualAnalyzer : XunitAnalyzer -{ - public const string DiagnosticId = Constants.Tips.Xunit.AssertNotStrictEqual; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().NotBe() instead."; - - protected override DiagnosticDescriptor Rule => new(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors => new FluentAssertionsCSharpSyntaxVisitor[] - { - new AssertNotStrictEqualSyntaxVisitor() - }; - - // public static void NotStrictEqual(T expected, T actual) - public class AssertNotStrictEqualSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertNotStrictEqualSyntaxVisitor() : base(MemberValidator.HasArguments("NotStrictEqual", count: 2)) - { - } - } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertNotStrictEqualCodeFix)), Shared] -public class AssertNotStrictEqualCodeFix : XunitCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertNotStrictEqualAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression( - ExpressionSyntax expression, - FluentAssertionsDiagnosticProperties properties) - { - switch (properties.VisitorName) - { - case nameof(AssertNotStrictEqualAnalyzer.AssertNotStrictEqualSyntaxVisitor): - return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "NotStrictEqual", "NotBe"); - default: - throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); - } - } -} diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertNull.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertNull.cs deleted file mode 100644 index 68fe9d6d..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertNull.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; - -namespace FluentAssertions.Analyzers.Xunit; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class AssertNullAnalyzer : XunitAnalyzer -{ - public const string DiagnosticId = Constants.Tips.Xunit.AssertNull; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().BeNull() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors - { - get - { - yield return new AssertNullSyntaxVisitor(); - } - } - - public class AssertNullSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertNullSyntaxVisitor() : base(new MemberValidator("Null")) - { - } - } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertNullCodeFix)), Shared] -public class AssertNullCodeFix : XunitCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertNullAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - return RenameMethodAndReplaceWithSubjectShould(expression, "Null", "BeNull"); - } -} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertSame.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertSame.cs deleted file mode 100644 index 4d1b92a7..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertSame.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; - -namespace FluentAssertions.Analyzers.Xunit; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class AssertSameAnalyzer : XunitAnalyzer -{ - public const string DiagnosticId = Constants.Tips.Xunit.AssertSame; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().BeSameAs() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors - { - get - { - yield return new AssertSameSyntaxVisitor(); - } - } - - public class AssertSameSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertSameSyntaxVisitor() : base(new MemberValidator("Same")) - { - } - } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertSameCodeFix)), Shared] -public class AssertSameCodeFix : XunitCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertSameAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "Same", "BeSameAs"); - } -} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertStartsWith.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertStartsWith.cs deleted file mode 100644 index cb9e8125..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertStartsWith.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; -using FluentAssertions.Analyzers.Utilities; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; - -namespace FluentAssertions.Analyzers.Xunit; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class AssertStartsWithAnalyzer : XunitAnalyzer -{ - public const string DiagnosticId = Constants.Tips.Xunit.AssertStartsWith; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().StartWith()"; - - protected override DiagnosticDescriptor Rule => new(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - - protected override IEnumerable Visitors => new FluentAssertionsCSharpSyntaxVisitor[] - { - new AssertStartsWithStringSyntaxVisitor() - }; - - //public static void StartsWith(string? expectedStartString, string? actualString) - public class AssertStartsWithStringSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertStartsWithStringSyntaxVisitor() : base( - MemberValidator.ArgumentsMatch("StartsWith", - ArgumentValidator.IsType(TypeSelector.GetStringType), - ArgumentValidator.IsType(TypeSelector.GetStringType)) - ) - { - } - } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertStartsWithCodeFix)), Shared] -public class AssertStartsWithCodeFix : XunitCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertStartsWithAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression( - ExpressionSyntax expression, - FluentAssertionsDiagnosticProperties properties) - { - switch (properties.VisitorName) - { - case nameof(AssertStartsWithAnalyzer.AssertStartsWithStringSyntaxVisitor): - return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "StartsWith", "StartWith"); - default: - throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); - } - } -} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertStrictEqual.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertStrictEqual.cs deleted file mode 100644 index 90a4bb8c..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertStrictEqual.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using FluentAssertions.Analyzers.Utilities; - -namespace FluentAssertions.Analyzers.Xunit; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class AssertStrictEqualAnalyzer : XunitAnalyzer -{ - public const string DiagnosticId = Constants.Tips.Xunit.AssertStrictEqual; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().Be() instead."; - - protected override DiagnosticDescriptor Rule => new(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors => new FluentAssertionsCSharpSyntaxVisitor[] - { - new AssertStrictEqualSyntaxVisitor() - }; - - // public static void StrictEqual(T expected, T actual) - public class AssertStrictEqualSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertStrictEqualSyntaxVisitor() : base(MemberValidator.HasArguments("StrictEqual", count: 2)) - { - } - } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertStrictEqualCodeFix)), Shared] -public class AssertStrictEqualCodeFix : XunitCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertStrictEqualAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression( - ExpressionSyntax expression, - FluentAssertionsDiagnosticProperties properties) - { - switch (properties.VisitorName) - { - case nameof(AssertStrictEqualAnalyzer.AssertStrictEqualSyntaxVisitor): - return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "StrictEqual", "Be"); - default: - throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); - } - } -} diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertSubset.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertSubset.cs deleted file mode 100644 index 13ec8b64..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertSubset.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; -using FluentAssertions.Analyzers.Utilities; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; - -namespace FluentAssertions.Analyzers.Xunit; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class AssertSubsetAnalyzer : XunitAnalyzer -{ - public const string DiagnosticId = Constants.Tips.Xunit.AssertSubset; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().BeSubset()"; - - protected override DiagnosticDescriptor Rule => new(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - - protected override IEnumerable Visitors => new FluentAssertionsCSharpSyntaxVisitor[] - { - new AssertSubsetSyntaxVisitor() - }; - - //public static void Subset(ISet expectedSubset, ISet? actual) - public class AssertSubsetSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertSubsetSyntaxVisitor() : base( - MemberValidator.ArgumentsMatch("Subset", - ArgumentValidator.Exists(), - ArgumentValidator.IsTypeOrConstructedFromTypeOrImplementsType(SpecialType.System_Collections_IEnumerable)) - ) - { - } - } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertSubsetCodeFix)), Shared] -public class AssertSubsetCodeFix : XunitCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertSubsetAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression( - ExpressionSyntax expression, - FluentAssertionsDiagnosticProperties properties) - { - switch (properties.VisitorName) - { - case nameof(AssertSubsetAnalyzer.AssertSubsetSyntaxVisitor): - return RenameMethodAndReorderActualExpectedAndReplaceWithSubjectShould(expression, "Subset", "BeSubsetOf"); - default: - throw new System.InvalidOperationException($"Invalid visitor name - {properties.VisitorName}"); - } - } -} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertTrue.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/AssertTrue.cs deleted file mode 100644 index e0e62879..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/AssertTrue.cs +++ /dev/null @@ -1,45 +0,0 @@ -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Composition; - -namespace FluentAssertions.Analyzers.Xunit; - -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class AssertTrueAnalyzer : XunitAnalyzer -{ - public const string DiagnosticId = Constants.Tips.Xunit.AssertTrue; - public const string Category = Constants.Tips.Category; - - public const string Message = "Use .Should().BeTrue() instead."; - - protected override DiagnosticDescriptor Rule => new DiagnosticDescriptor(DiagnosticId, Title, Message, Category, DiagnosticSeverity.Info, true); - protected override IEnumerable Visitors - { - get - { - yield return new AssertTrueSyntaxVisitor(); - } - } - - public class AssertTrueSyntaxVisitor : FluentAssertionsCSharpSyntaxVisitor - { - public AssertTrueSyntaxVisitor() : base(new MemberValidator("True")) - { - } - } -} - -[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(AssertTrueCodeFix)), Shared] -public class AssertTrueCodeFix : XunitCodeFixProvider -{ - public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertTrueAnalyzer.DiagnosticId); - - protected override ExpressionSyntax GetNewExpression(ExpressionSyntax expression, FluentAssertionsDiagnosticProperties properties) - { - return RenameMethodAndReplaceWithSubjectShould(expression, "True", "BeTrue"); - } -} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/Xunit/XunitBase.cs b/src/FluentAssertions.Analyzers/Tips/Xunit/XunitBase.cs deleted file mode 100644 index be942617..00000000 --- a/src/FluentAssertions.Analyzers/Tips/Xunit/XunitBase.cs +++ /dev/null @@ -1,34 +0,0 @@ -using FluentAssertions.Analyzers.Utilities; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; - -namespace FluentAssertions.Analyzers.Xunit; - -public abstract class XunitAnalyzer : TestingLibraryAnalyzerBase -{ - protected override string TestingLibraryModule => "xunit.assert"; - protected override string TestingLibraryAssertionType => "Assert"; - - protected override bool ShouldAnalyzeVariableNamedType(INamedTypeSymbol type, SemanticModel semanticModel) => type.Name == "Assert"; -} - -public abstract class XunitCodeFixProvider : TestingLibraryCodeFixBase -{ - protected override string AssertClassName => "Assert"; - - protected ExpressionSyntax GetNewExpressionForEqualityWithComparer( - ExpressionSyntax expression, - string oldName, - string newName) - { - var rename = NodeReplacement.RenameAndExtractArguments(oldName, newName); - var newExpression = GetNewExpression(expression, rename); - - var actual = rename.Arguments[1]; - var optionsLambda = Expressions.OptionsUsing(rename.Arguments[2]); - - newExpression = ReplaceIdentifier(newExpression, AssertClassName, Expressions.SubjectShould(actual.Expression)); - - return GetNewExpression(newExpression, NodeReplacement.WithArguments(newName, rename.Arguments.RemoveAt(2).Add(optionsLambda).RemoveAt(1))); - } -} \ No newline at end of file diff --git a/src/FluentAssertions.Analyzers/Tips/XunitCodeFixProvider.cs b/src/FluentAssertions.Analyzers/Tips/XunitCodeFixProvider.cs new file mode 100644 index 00000000..20757677 --- /dev/null +++ b/src/FluentAssertions.Analyzers/Tips/XunitCodeFixProvider.cs @@ -0,0 +1,137 @@ +using System.Collections.Immutable; +using System.Composition; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.Operations; +using CreateChangedDocument = System.Func>; + +namespace FluentAssertions.Analyzers; + +[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(XunitCodeFixProvider)), Shared] +public class XunitCodeFixProvider : TestingFrameworkCodeFixProvider +{ + public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(AssertAnalyzer.XunitRule.Id); + + protected override CreateChangedDocument TryComputeFix(IInvocationOperation invocation, CodeFixContext context, TestingFrameworkCodeFixContext t, Diagnostic diagnostic) + { + switch (invocation.TargetMethod.Name) + { + case "True" when ArgumentsAreTypeOf(invocation, t.Boolean): // Assert.True(bool condition) + case "True" when ArgumentsAreTypeOf(invocation, t.Boolean, t.String): // Assert.True(bool condition, string userMessage) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeTrue", argumentIndex: 0, argumentsToRemove: []); + case "False" when ArgumentsAreTypeOf(invocation, t.Boolean): // Assert.False(bool condition) + case "False" when ArgumentsAreTypeOf(invocation, t.Boolean, t.String): // Assert.False(bool condition, string userMessage) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeFalse", argumentIndex: 0, argumentsToRemove: []); + case "Same" when ArgumentsAreTypeOf(invocation, t.Object, t.Object): // Assert.Same(object expected, object actual) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeSameAs", argumentIndex: 1, argumentsToRemove: []); + case "NotSame" when ArgumentsAreTypeOf(invocation, t.Object, t.Object): // Assert.NotSame(object expected, object actual) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotBeSameAs", argumentIndex: 1, argumentsToRemove: []); + case "Equal" when ArgumentsAreTypeOf(invocation, t.Float, t.Float, t.Float): // Assert.Equal(float expected, float actual, float tolerance) + case "Equal" when ArgumentsAreTypeOf(invocation, t.Double, t.Double, t.Double): // Assert.Equal(double expected, double actual, double tolerance) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeApproximately", argumentIndex: 1, argumentsToRemove: []); + case "Equal" when ArgumentsAreTypeOf(invocation, t.Float, t.Float, t.Int32): // Assert.Equal(float expected, float actual, int precision) + case "Equal" when ArgumentsAreTypeOf(invocation, t.Double, t.Double, t.Int32): // Assert.Equal(double expected, double actual, int precision) + case "Equal" when ArgumentsAreTypeOf(invocation, t.Decimal, t.Decimal, t.Int32): // Assert.Equal(decimal expected, decimal actual, int precision) + break; // TODO: support this + case "Equal" when ArgumentsAreTypeOf(invocation, t.DateTime, t.DateTime): // Assert.Equal(DateTime expected, DateTime actual) + case "Equal" when ArgumentsAreTypeOf(invocation, t.String, t.String): // Assert.Equal(string expected, string actual) + case "Equal" when ArgumentsAreTypeOf(invocation, t.Object, t.Object): // Assert.Equal(object expected, object actual) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "Be", argumentIndex: 1, argumentsToRemove: []); + case "Equal" when ArgumentsAreTypeOf(invocation, t.DateTime, t.DateTime, t.TimeSpan): // Assert.Equal(DateTime expected, DateTime actual, TimeSpan precision) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeCloseTo", argumentIndex: 1, argumentsToRemove: []); + case "Equal" when ArgumentsAreGenericTypeOf(invocation, t.Identity, t.Identity, t.IEqualityComparerOfT1): // Assert.Equal(T expected, T actual, IEqualityComparer comparer) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertionWithOptionsLambda(invocation, context, "BeEquivalentTo", argumentIndex: 1, optionsIndex: 2); + case "NotEqual" when ArgumentsAreTypeOf(invocation, t.Float, t.Float, t.Float): // Assert.NotEqual(float expected, float actual, float tolerance) + case "NotEqual" when ArgumentsAreTypeOf(invocation, t.Double, t.Double, t.Double): // Assert.NotEqual(double expected, double actual, double tolerance) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotBeApproximately", argumentIndex: 1, argumentsToRemove: []); + case "NotEqual" when ArgumentsAreTypeOf(invocation, t.Float, t.Float, t.Int32): // Assert.NotEqual(float expected, float actual, int precision) + case "NotEqual" when ArgumentsAreTypeOf(invocation, t.Double, t.Double, t.Int32): // Assert.NotEqual(double expected, double actual, int precision) + case "NotEqual" when ArgumentsAreTypeOf(invocation, t.Decimal, t.Decimal, t.Int32): // Assert.NotEqual(decimal expected, decimal actual, int precision) + break; // TODO: support this + case "NotEqual" when ArgumentsAreTypeOf(invocation, t.DateTime, t.DateTime): // Assert.NotEqual(DateTime expected, DateTime actual) + case "NotEqual" when ArgumentsAreTypeOf(invocation, t.String, t.String): // Assert.NotEqual(string expected, string actual) + case "NotEqual" when ArgumentsAreTypeOf(invocation, t.Object, t.Object): // Assert.NotEqual(object expected, object actual) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotBe", argumentIndex: 1, argumentsToRemove: []); + case "NotEqual" when ArgumentsAreTypeOf(invocation, t.DateTime, t.DateTime, t.TimeSpan): // Assert.NotEqual(DateTime expected, DateTime actual, TimeSpan precision) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotBeCloseTo", argumentIndex: 1, argumentsToRemove: []); + case "NotEqual" when ArgumentsAreGenericTypeOf(invocation, t.Identity, t.Identity, t.IEqualityComparerOfT1): // Assert.NotEqual(T expected, T actual, IEqualityComparer comparer) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertionWithOptionsLambda(invocation, context, "NotBeEquivalentTo", argumentIndex: 1, optionsIndex: 2); + case "StrictEqual" when ArgumentsCount(invocation, arguments: 2): // Assert.StrictEqual(T expected, T actual) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "Be", argumentIndex: 1, argumentsToRemove: []); + case "NotStrictEqual" when ArgumentsCount(invocation, arguments: 2): // Assert.NotStrictEqual(T expected, T actual) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotBe", argumentIndex: 1, argumentsToRemove: []); + case "Null" when ArgumentsCount(invocation, arguments: 1): // Assert.Null(object? @object) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeNull", argumentIndex: 0, argumentsToRemove: []); + case "NotNull" when ArgumentsCount(invocation, arguments: 1): // Assert.NotNull(object? @object) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotBeNull", argumentIndex: 0, argumentsToRemove: []); + case "Contains" when ArgumentsCount(invocation, arguments: 2): // Assert.Contains(T expected, IEnumerable collection) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "Contain", argumentIndex: 1, argumentsToRemove: []); + case "Contains" when ArgumentsAreGenericTypeOf(invocation, t.Identity, t.IEnumerableOfT1, t.IEqualityComparerOfT1): // Assert.Contains(T expected, IEnumerable collection, IEqualityComparer comparer) + break; // TODO: support this + case "DoesNotContain" when ArgumentsCount(invocation, arguments: 2): // Assert.DoesNotContain(string expectedSubstring, string? actualString) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotContain", argumentIndex: 1, argumentsToRemove: []); + case "DoesNotContain" when ArgumentsAreGenericTypeOf(invocation, t.Identity, t.IEnumerableOfT1, t.IEqualityComparerOfT1): // Assert.DoesNotContain(T expected, IEnumerable collection, IEqualityComparer comparer) + break; // TODO: support this + case "Matches" when ArgumentsAreTypeOf(invocation, t.String, t.String): // Assert.Matches(string regexPattern, string? actualString) + case "Matches" when ArgumentsAreTypeOf(invocation, t.Regex, t.String): // Assert.Matches(Regex regexPattern, string? actualString) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "MatchRegex", argumentIndex: 1, argumentsToRemove: []); + case "DoesNotMatch" when ArgumentsAreTypeOf(invocation, t.String, t.String): // Assert.DoesNotMatch(string regexPattern, string? actualString) + case "DoesNotMatch" when ArgumentsAreTypeOf(invocation, t.Regex, t.String): // Assert.DoesNotMatch(Regex regexPattern, string? actualString) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotMatchRegex", argumentIndex: 1, argumentsToRemove: []); + case "Empty" when ArgumentsCount(invocation, arguments: 1): // Assert.Empty(string value) | Assert.Empty(IEnumerable collection) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeEmpty", argumentIndex: 0, argumentsToRemove: []); + // TODO: support NotEmpty + case "EndsWith" when ArgumentsAreTypeOf(invocation, t.String, t.String): // Assert.EndsWith(string expectedEndString, string? actualString) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "EndWith", argumentIndex: 1, argumentsToRemove: []); + case "StartsWith" when ArgumentsAreTypeOf(invocation, t.String, t.String): // Assert.StartsWith(string expectedStartString, string? actualString) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "StartWith", argumentIndex: 1, argumentsToRemove: []); + case "Subset" when ArgumentsCount(invocation, arguments: 2): // Assert.Subset(ISet expectedSubset, ISet actualSet) + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeSubsetOf", argumentIndex: 1, argumentsToRemove: []); + case "IsAssignableFrom" when ArgumentsCount(invocation, arguments: 1): // Assert.IsAssignableFrom(object? @object) + return DocumentEditorUtils.RenameGenericMethodToSubjectShouldGenericAssertion(invocation, context, "BeAssignableTo", argumentIndex: 0, argumentsToRemove: []); + case "IsAssignableFrom" when ArgumentsCount(invocation, arguments: 2): // Assert.IsAssignableFrom(Type expectedType, object? @object) + { + if (invocation.Arguments[0].Value is not ITypeOfOperation typeOf) + { + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeAssignableTo", argumentIndex: 1, argumentsToRemove: []); + } + + return DocumentEditorUtils.RenameMethodToSubjectShouldGenericAssertion(invocation, ImmutableArray.Create(typeOf.TypeOperand), context, "BeAssignableTo", argumentIndex: 1, argumentsToRemove: [0]); + } + case "IsNotAssignableFrom" when ArgumentsCount(invocation, arguments: 1): // Assert.IsNotAssignableFrom(object? @object) + return DocumentEditorUtils.RenameGenericMethodToSubjectShouldGenericAssertion(invocation, context, "NotBeAssignableTo", argumentIndex: 0, argumentsToRemove: []); + case "IsNotAssignableFrom" when ArgumentsCount(invocation, arguments: 2): // Assert.IsNotAssignableFrom(Type expectedType, object? @object) + { + if (invocation.Arguments[0].Value is not ITypeOfOperation typeOf) + { + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotBeAssignableTo", argumentIndex: 1, argumentsToRemove: []); + } + + return DocumentEditorUtils.RenameMethodToSubjectShouldGenericAssertion(invocation, ImmutableArray.Create(typeOf.TypeOperand), context, "NotBeAssignableTo", argumentIndex: 1, argumentsToRemove: [0]); + } + case "IsType" when ArgumentsCount(invocation, 1): // Assert.IsType(object @object) + return DocumentEditorUtils.RenameGenericMethodToSubjectShouldGenericAssertion(invocation, context, "BeOfType", argumentIndex: 0, argumentsToRemove: []); + case "IsType" when ArgumentsCount(invocation, arguments: 2): // Assert.IsType(Type expectedType, object? @object) + { + if (invocation.Arguments[0].Value is not ITypeOfOperation typeOf) + { + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "BeOfType", argumentIndex: 1, argumentsToRemove: []); + } + + return DocumentEditorUtils.RenameMethodToSubjectShouldGenericAssertion(invocation, ImmutableArray.Create(typeOf.TypeOperand), context, "BeOfType", argumentIndex: 1, argumentsToRemove: [0]); + } + case "IsNotType" when ArgumentsCount(invocation, 1): // Assert.IsNotType(object @object) + return DocumentEditorUtils.RenameGenericMethodToSubjectShouldGenericAssertion(invocation, context, "NotBeOfType", argumentIndex: 0, argumentsToRemove: []); + case "IsNotType" when ArgumentsCount(invocation, arguments: 2): // Assert.IsNotType(Type expectedType, object? @object) + { + if (invocation.Arguments[0].Value is not ITypeOfOperation typeOf) + { + return DocumentEditorUtils.RenameMethodToSubjectShouldAssertion(invocation, context, "NotBeOfType", argumentIndex: 1, argumentsToRemove: []); + } + + return DocumentEditorUtils.RenameMethodToSubjectShouldGenericAssertion(invocation, ImmutableArray.Create(typeOf.TypeOperand), context, "NotBeOfType", argumentIndex: 1, argumentsToRemove: [0]); + } + } + return null; + } +} \ No newline at end of file