diff --git a/src/xunit.analyzers.tests/Analyzers/X1000/MemberDataShouldReferenceValidMemberTests.cs b/src/xunit.analyzers.tests/Analyzers/X1000/MemberDataShouldReferenceValidMemberTests.cs index 99ea6f2d..5fb23828 100644 --- a/src/xunit.analyzers.tests/Analyzers/X1000/MemberDataShouldReferenceValidMemberTests.cs +++ b/src/xunit.analyzers.tests/Analyzers/X1000/MemberDataShouldReferenceValidMemberTests.cs @@ -254,149 +254,180 @@ public void TestMethod() {{ }} public class X1019_MemberDataMustReferenceMemberOfValidType { - // The base type of IEnumerable and IEnumerable trigger xUnit1042, - // which is covered below in X1042_MemberDataTheoryDataIsRecommendedForStronglyTypedAnalysis, - // so we'll only test TheoryData<> and IEnumerable> here. + const string V2AllowedTypes = "'System.Collections.Generic.IEnumerable'"; + const string V3AllowedTypes = "'System.Collections.Generic.IEnumerable', 'System.Collections.Generic.IAsyncEnumerable', 'System.Collections.Generic.IEnumerable', 'System.Collections.Generic.IAsyncEnumerable', 'System.Collections.Generic.IEnumerable', or 'System.Collections.Generic.IAsyncEnumerable'"; [Fact] - public async Task TheoryData_DoesNotTrigger() + public async Task V2_and_V3() { var source = /* lang=c#-test */ """ + #pragma warning disable xUnit1042 + + using System; using System.Collections.Generic; + using System.Threading.Tasks; using Xunit; public class TestClass { - public static TheoryData Data; + public static IEnumerable ObjectSource; + public static object NakedObjectSource; + public static object[] NakedObjectArraySource; - [MemberData(nameof(Data))] - public void TestMethod(int _) { } - } - """; + public static IEnumerable ObjectArraySource; + public static Task> TaskObjectArraySource; + public static ValueTask> ValueTaskObjectArraySource; - await Verify.VerifyAnalyzer(source); - } + public static IAsyncEnumerable AsyncObjectArraySource; + public static Task> TaskAsyncObjectArraySource; + public static ValueTask> ValueTaskAsyncObjectArraySource; - [Theory] - [InlineData(/* lang=c#-test */ "Task")] - [InlineData(/* lang=c#-test */ "ValueTask")] - public async Task Async_TheoryData_TriggersInV2_DoesNotTriggerInV3(string taskType) - { - var source = string.Format(/* lang=c#-test */ """ - using System.Collections.Generic; - using System.Threading.Tasks; - using Xunit; + public static TheoryData TheoryDataSource; + public static Task> TaskTheoryDataSource; + public static ValueTask> ValueTaskTheoryDataSource; - public class TestClass {{ - public static {0}> Data; + public static IEnumerable<(string, int)> UntypedTupleSource; + public static Task> TaskUntypedTupleSource; + public static ValueTask> ValueTaskUntypedTupleSource; - [{{|#0:MemberData(nameof(Data))|}}] - public void TestMethod(int _) {{ }} - }} - """, taskType); - var expectedV2 = Verify.Diagnostic("xUnit1019").WithLocation(0).WithArguments("'System.Collections.Generic.IEnumerable'", $"System.Threading.Tasks.{taskType}>"); + public static IAsyncEnumerable<(string, int)> AsyncUntypedTupleSource; + public static Task> TaskAsyncUntypedTupleSource; + public static ValueTask> ValueTaskAsyncUntypedTupleSource; - await Verify.VerifyAnalyzerV2(LanguageVersion.CSharp9, source, expectedV2); - await Verify.VerifyAnalyzerV3(LanguageVersion.CSharp9, source); - } + public static IEnumerable> TypedTupleSource; + public static Task>> TaskTypedTupleSource; + public static ValueTask>> ValueTaskTypedTupleSource; - [Theory] - [InlineData(/* lang=c#-test */ "List>")] - [InlineData(/* lang=c#-test */ "IAsyncEnumerable>")] - public async Task GenericTheoryDataRow_DoesNotTrigger(string dataType) - { - var source = string.Format(/* lang=c#-test */ """ - using System; - using System.Collections.Generic; - using Xunit; - using Xunit.Sdk; + public static IAsyncEnumerable> AsyncTypedTupleSource; + public static Task>> TaskAsyncTypedTupleSource; + public static ValueTask>> ValueTaskAsyncTypedTupleSource; - public class TestClass {{ - [Theory] - [MemberData(nameof(DataRowSource))] - public void SkippedDataRow(int x, string y) {{ }} + [{|#0:MemberData(nameof(ObjectSource))|}] + [{|#1:MemberData(nameof(NakedObjectSource))|}] + [{|#2:MemberData(nameof(NakedObjectArraySource))|}] - public static {0} DataRowSource() {{ - throw new NotImplementedException(); - }} - }} - """, dataType); + [MemberData(nameof(ObjectArraySource))] + [{|#10:MemberData(nameof(TaskObjectArraySource))|}] + [{|#11:MemberData(nameof(ValueTaskObjectArraySource))|}] - await Verify.VerifyAnalyzerV3(LanguageVersion.CSharp9, source); - } + [{|#20:MemberData(nameof(AsyncObjectArraySource))|}] + [{|#21:MemberData(nameof(TaskAsyncObjectArraySource))|}] + [{|#22:MemberData(nameof(ValueTaskAsyncObjectArraySource))|}] - [Theory] - [InlineData(/* lang=c#-test */ "Task>>")] - [InlineData(/* lang=c#-test */ "ValueTask>>")] - public async Task Async_GenericTheoryDataRow_DoesNotTrigger(string taskType) - { - var source = string.Format(/* lang=c#-test */ """ - using System; - using System.Collections.Generic; - using System.Threading.Tasks; - using Xunit; - using Xunit.Sdk; + [MemberData(nameof(TheoryDataSource))] + [{|#30:MemberData(nameof(TaskTheoryDataSource))|}] + [{|#31:MemberData(nameof(ValueTaskTheoryDataSource))|}] + + [{|#40:MemberData(nameof(UntypedTupleSource))|}] + [{|#41:MemberData(nameof(TaskUntypedTupleSource))|}] + [{|#42:MemberData(nameof(ValueTaskUntypedTupleSource))|}] - public class TestClass {{ - [Theory] - [MemberData(nameof(DataRowSource))] - public void SkippedDataRow(int x, string y) {{ }} + [{|#50:MemberData(nameof(AsyncUntypedTupleSource))|}] + [{|#51:MemberData(nameof(TaskAsyncUntypedTupleSource))|}] + [{|#52:MemberData(nameof(ValueTaskAsyncUntypedTupleSource))|}] - public static async {0} DataRowSource() {{ - throw new NotImplementedException(); - }} - }} - """, taskType); - - await Verify.VerifyAnalyzerV3(LanguageVersion.CSharp9, source); - } + [{|#60:MemberData(nameof(TypedTupleSource))|}] + [{|#61:MemberData(nameof(TaskTypedTupleSource))|}] + [{|#62:MemberData(nameof(ValueTaskTypedTupleSource))|}] - [Theory] - [InlineData(/* lang=c#-test */ "System.Collections.Generic.IEnumerable")] - [InlineData(/* lang=c#-test */ "object[]")] - [InlineData(/* lang=c#-test */ "object")] - public async Task InvalidMemberType_Triggers(string memberType) - { - var source = string.Format(/* lang=c#-test */ """ - public class TestClass {{ - public static {0} Data; + [{|#70:MemberData(nameof(AsyncTypedTupleSource))|}] + [{|#71:MemberData(nameof(TaskAsyncTypedTupleSource))|}] + [{|#72:MemberData(nameof(ValueTaskAsyncTypedTupleSource))|}] - [{{|#0:Xunit.MemberData(nameof(Data))|}}] - public void TestMethod() {{ }} - }} - """, memberType); - var expectedV2 = Verify.Diagnostic("xUnit1019").WithLocation(0).WithArguments("'System.Collections.Generic.IEnumerable'", memberType); - var expectedV3 = Verify.Diagnostic("xUnit1019").WithLocation(0).WithArguments("'System.Collections.Generic.IEnumerable', 'System.Collections.Generic.IAsyncEnumerable', 'System.Collections.Generic.IEnumerable', 'System.Collections.Generic.IAsyncEnumerable', 'System.Collections.Generic.IEnumerable', or 'System.Collections.Generic.IAsyncEnumerable'", memberType); + public void TestMethod(string _1, int _2) { } + } + """; + var expectedV2 = new[] { + // Generally invalid types + Verify.Diagnostic("xUnit1019").WithLocation(0).WithArguments(V2AllowedTypes, $"System.Collections.Generic.IEnumerable"), + Verify.Diagnostic("xUnit1019").WithLocation(1).WithArguments(V2AllowedTypes, $"object"), + Verify.Diagnostic("xUnit1019").WithLocation(2).WithArguments(V2AllowedTypes, $"object[]"), + + // v2 does not support tuples, wrapping in Task/ValueTask, and does not support IAsyncEnumerable + Verify.Diagnostic("xUnit1019").WithLocation(10).WithArguments(V2AllowedTypes, $"System.Threading.Tasks.Task>"), + Verify.Diagnostic("xUnit1019").WithLocation(11).WithArguments(V2AllowedTypes, $"System.Threading.Tasks.ValueTask>"), + + Verify.Diagnostic("xUnit1019").WithLocation(20).WithArguments(V2AllowedTypes, $"System.Collections.Generic.IAsyncEnumerable"), + Verify.Diagnostic("xUnit1019").WithLocation(21).WithArguments(V2AllowedTypes, $"System.Threading.Tasks.Task>"), + Verify.Diagnostic("xUnit1019").WithLocation(22).WithArguments(V2AllowedTypes, $"System.Threading.Tasks.ValueTask>"), + + Verify.Diagnostic("xUnit1019").WithLocation(30).WithArguments(V2AllowedTypes, $"System.Threading.Tasks.Task>"), + Verify.Diagnostic("xUnit1019").WithLocation(31).WithArguments(V2AllowedTypes, $"System.Threading.Tasks.ValueTask>"), + + Verify.Diagnostic("xUnit1019").WithLocation(40).WithArguments(V2AllowedTypes, $"System.Collections.Generic.IEnumerable<(string, int)>"), + Verify.Diagnostic("xUnit1019").WithLocation(41).WithArguments(V2AllowedTypes, $"System.Threading.Tasks.Task>"), + Verify.Diagnostic("xUnit1019").WithLocation(42).WithArguments(V2AllowedTypes, $"System.Threading.Tasks.ValueTask>"), + + Verify.Diagnostic("xUnit1019").WithLocation(50).WithArguments(V2AllowedTypes, $"System.Collections.Generic.IAsyncEnumerable<(string, int)>"), + Verify.Diagnostic("xUnit1019").WithLocation(51).WithArguments(V2AllowedTypes, $"System.Threading.Tasks.Task>"), + Verify.Diagnostic("xUnit1019").WithLocation(52).WithArguments(V2AllowedTypes, $"System.Threading.Tasks.ValueTask>"), + + Verify.Diagnostic("xUnit1019").WithLocation(60).WithArguments(V2AllowedTypes, $"System.Collections.Generic.IEnumerable>"), + Verify.Diagnostic("xUnit1019").WithLocation(61).WithArguments(V2AllowedTypes, $"System.Threading.Tasks.Task>>"), + Verify.Diagnostic("xUnit1019").WithLocation(62).WithArguments(V2AllowedTypes, $"System.Threading.Tasks.ValueTask>>"), + + Verify.Diagnostic("xUnit1019").WithLocation(70).WithArguments(V2AllowedTypes, $"System.Collections.Generic.IAsyncEnumerable>"), + Verify.Diagnostic("xUnit1019").WithLocation(71).WithArguments(V2AllowedTypes, $"System.Threading.Tasks.Task>>"), + Verify.Diagnostic("xUnit1019").WithLocation(72).WithArguments(V2AllowedTypes, $"System.Threading.Tasks.ValueTask>>"), + }; + var expectedV3 = new[] { + // Generally invalid types + Verify.Diagnostic("xUnit1019").WithLocation(0).WithArguments(V3AllowedTypes, $"System.Collections.Generic.IEnumerable"), + Verify.Diagnostic("xUnit1019").WithLocation(1).WithArguments(V3AllowedTypes, $"object"), + Verify.Diagnostic("xUnit1019").WithLocation(2).WithArguments(V3AllowedTypes, $"object[]"), + }; - await Verify.VerifyAnalyzerV2(source, expectedV2); - await Verify.VerifyAnalyzerV3(source, expectedV3); + await Verify.VerifyAnalyzerV2(LanguageVersion.CSharp9, source, expectedV2); + await Verify.VerifyAnalyzerV3(LanguageVersion.CSharp9, source, expectedV3); } [Fact] - public async Task Tuple_TriggersInV2_DoesNotTriggerInV3() + public async Task V3_only() { var source = /* lang=c#-test */ """ #pragma warning disable xUnit1042 - using System; using System.Collections.Generic; + using System.Threading.Tasks; using Xunit; public class TestClass { - public static IEnumerable<(string, int)> UntypedTupleSource; - public static IEnumerable> TypedTupleSource; + public static List ITheoryDataRowSource; + public static Task> TaskITheoryDataRowSource; + public static ValueTask> ValueTaskITheoryDataRowSource; - [{|#0:MemberData(nameof(UntypedTupleSource))|}] - [{|#1:MemberData(nameof(TypedTupleSource))|}] - public void TestMethod(string _1, int _2) { } + public static List> TheoryDataRowSource; + public static Task>> TaskTheoryDataRowSource; + public static ValueTask>> ValueTaskTheoryDataRowSource; + + public static IAsyncEnumerable AsyncITheoryDataRowSource; + public static Task> TaskAsyncITheoryDataRowSource; + public static ValueTask> ValueTaskAsyncITheoryDataRowSource; + + public static IAsyncEnumerable> AsyncTheoryDataRowSource; + public static Task>> TaskAsyncTheoryDataRowSource; + public static ValueTask>> ValueTaskAsyncTheoryDataRowSource; + + [MemberData(nameof(ITheoryDataRowSource))] + [MemberData(nameof(TaskITheoryDataRowSource))] + [MemberData(nameof(ValueTaskITheoryDataRowSource))] + + [MemberData(nameof(TheoryDataRowSource))] + [MemberData(nameof(TaskTheoryDataRowSource))] + [MemberData(nameof(ValueTaskTheoryDataRowSource))] + + [MemberData(nameof(AsyncITheoryDataRowSource))] + [MemberData(nameof(TaskAsyncITheoryDataRowSource))] + [MemberData(nameof(ValueTaskAsyncITheoryDataRowSource))] + + [MemberData(nameof(AsyncTheoryDataRowSource))] + [MemberData(nameof(TaskAsyncTheoryDataRowSource))] + [MemberData(nameof(ValueTaskAsyncTheoryDataRowSource))] + + public void TestMethod(int _1, string _2) { } } """; - DiagnosticResult[] expectedV2 = [ - Verify.Diagnostic("xUnit1019").WithLocation(0).WithArguments("'System.Collections.Generic.IEnumerable'", "System.Collections.Generic.IEnumerable<(string, int)>"), - Verify.Diagnostic("xUnit1019").WithLocation(1).WithArguments("'System.Collections.Generic.IEnumerable'", "System.Collections.Generic.IEnumerable>"), - ]; - await Verify.VerifyAnalyzerV2(LanguageVersion.CSharp7, source, expectedV2); - await Verify.VerifyAnalyzerV3(LanguageVersion.CSharp7, source); + await Verify.VerifyAnalyzerV3(LanguageVersion.CSharp9, source); } }