diff --git a/src/FluentAssertions.Analyzers.TestUtils/GenerateCode.cs b/src/FluentAssertions.Analyzers.TestUtils/GenerateCode.cs index 93c91aa..7f082cb 100644 --- a/src/FluentAssertions.Analyzers.TestUtils/GenerateCode.cs +++ b/src/FluentAssertions.Analyzers.TestUtils/GenerateCode.cs @@ -55,7 +55,9 @@ public static string GenericIListExpressionBodyAssertion(string assertion) => Ge .AppendLine(" {") .AppendLine(" public bool BooleanProperty { get; set; }") .AppendLine(" public string Message { get; set; }") + .AppendLine(" public TestComplexClass this[int index] => throw new NotImplementedException();") .AppendLine(" }") + .AppendLine() .AppendLine("}") .ToString(); diff --git a/src/FluentAssertions.Analyzers.Tests/Tips/CollectionTests.cs b/src/FluentAssertions.Analyzers.Tests/Tips/CollectionTests.cs index 99d0748..50edbcb 100644 --- a/src/FluentAssertions.Analyzers.Tests/Tips/CollectionTests.cs +++ b/src/FluentAssertions.Analyzers.Tests/Tips/CollectionTests.cs @@ -773,7 +773,7 @@ public void CollectionShouldContainSingle_TestAnalyzer_GenericIEnumerableShouldR [AssertionDiagnostic("actual.ElementAt(k).BooleanProperty.Should().Be(expectedItem.BooleanProperty{0});")] [AssertionDiagnostic("actual.ElementAt(6).BooleanProperty.Should().Be(expectedItem.BooleanProperty{0});")] [AssertionDiagnostic("actual.AsEnumerable().ElementAt(k).BooleanProperty.Should().Be(expectedItem.BooleanProperty{0}).And.ToString();")] - [AssertionDiagnostic("actual.AsEnumerable().ElementAt(6).BooleanProperty.Should().Be(expectedItem.BooleanProperty{0}).And.ToString();")] + [AssertionDiagnostic("actual.AsEnumerable().ElementAt(6).BooleanProperty.Should().Be(expectedItem.BooleanProperty{0}).And.ToString();")] [Implemented] public void CollectionShouldHaveElementAt_ElementAtIndexShouldBe_TestNoAnalyzer(string assertion) => DiagnosticVerifier.VerifyCSharpDiagnosticUsingAllAnalyzers(GenerateCode.GenericIListCodeBlockAssertion(assertion)); @@ -793,6 +793,11 @@ public void CollectionShouldContainSingle_TestAnalyzer_GenericIEnumerableShouldR [Implemented] public void CollectionShouldHaveElementAt_IndexerShouldBe_TestAnalyzer(string assertion) => VerifyCSharpDiagnosticCodeBlock(assertion, DiagnosticMetadata.CollectionShouldHaveElementAt_IndexerShouldBe); + [DataTestMethod] + [AssertionDiagnostic("var first = actual[0]; first[6].Should().Be(expectedItem{0});")] + [Implemented] + public void CollectionShouldHaveElementAt_IndexerShouldBe_TestNoAnalyzer(string assertion) => DiagnosticVerifier.VerifyCSharpDiagnosticUsingAllAnalyzers(GenerateCode.GenericIListCodeBlockAssertion(assertion)); + [DataTestMethod] [AssertionDiagnostic("actual.Skip(k).First().Should().Be(expectedItem{0});")] [AssertionDiagnostic("actual.Skip(6).First().Should().Be(expectedItem{0});")] diff --git a/src/FluentAssertions.Analyzers/Tips/FluentAssertionsAnalyzer.Utils.cs b/src/FluentAssertions.Analyzers/Tips/FluentAssertionsAnalyzer.Utils.cs index 99ffa47..0de31b1 100644 --- a/src/FluentAssertions.Analyzers/Tips/FluentAssertionsAnalyzer.Utils.cs +++ b/src/FluentAssertions.Analyzers/Tips/FluentAssertionsAnalyzer.Utils.cs @@ -70,6 +70,8 @@ public FluentAssertionsMetadata(Compilation compilation) IDictionaryOfT2 = compilation.GetTypeByMetadataName(typeof(IDictionary<,>).FullName); DictionaryOfT2 = compilation.GetTypeByMetadataName(typeof(Dictionary<,>).FullName); IReadonlyDictionaryOfT2 = compilation.GetTypeByMetadataName(typeof(IReadOnlyDictionary<,>).FullName); + IListOfT = compilation.GetTypeByMetadataName(typeof(IList<>).FullName); + IReadonlyListOfT = compilation.GetTypeByMetadataName(typeof(IReadOnlyList<>).FullName); Enumerable = compilation.GetTypeByMetadataName(typeof(Enumerable).FullName); IEnumerable = compilation.GetTypeByMetadataName(typeof(IEnumerable).FullName); Math = compilation.GetTypeByMetadataName(typeof(Math).FullName); @@ -87,6 +89,8 @@ public FluentAssertionsMetadata(Compilation compilation) public INamedTypeSymbol IDictionaryOfT2 { get; } public INamedTypeSymbol DictionaryOfT2 { get; } public INamedTypeSymbol IReadonlyDictionaryOfT2 { get; } + public INamedTypeSymbol IListOfT { get; } + public INamedTypeSymbol IReadonlyListOfT { get; } public INamedTypeSymbol BooleanAssertionsOfT1 { get; } public INamedTypeSymbol NumericAssertionsOfT2 { get; } public INamedTypeSymbol Enumerable { get; } diff --git a/src/FluentAssertions.Analyzers/Tips/FluentAssertionsAnalyzer.cs b/src/FluentAssertions.Analyzers/Tips/FluentAssertionsAnalyzer.cs index 4f2e644..fdbac4e 100644 --- a/src/FluentAssertions.Analyzers/Tips/FluentAssertionsAnalyzer.cs +++ b/src/FluentAssertions.Analyzers/Tips/FluentAssertionsAnalyzer.cs @@ -394,6 +394,7 @@ private static void AnalyzeInvocation(OperationAnalysisContext context, FluentAs } else if (subject.TryGetFirstDescendent(out var propertyReference) && propertyReference.Property.IsIndexer) { + if (!propertyReference.Instance.Type.ImplementsOrIsInterface(metadata.IListOfT) && !propertyReference.Instance.Type.ImplementsOrIsInterface(metadata.IReadonlyListOfT)) return; if (propertyReference.Instance.Type.ImplementsOrIsInterface(metadata.IDictionaryOfT2) || propertyReference.Instance.Type.ImplementsOrIsInterface(metadata.IReadonlyDictionaryOfT2)) return; context.ReportDiagnostic(CreateDiagnostic(assertion, DiagnosticMetadata.CollectionShouldHaveElementAt_IndexerShouldBe));