diff --git a/src/Microsoft.NetCore.Analyzers/Core/Performance/UsePropertyInsteadOfCountMethodWhenAvailable.cs b/src/Microsoft.NetCore.Analyzers/Core/Performance/UsePropertyInsteadOfCountMethodWhenAvailable.cs index 8744b7f84e..b156ab8a71 100644 --- a/src/Microsoft.NetCore.Analyzers/Core/Performance/UsePropertyInsteadOfCountMethodWhenAvailable.cs +++ b/src/Microsoft.NetCore.Analyzers/Core/Performance/UsePropertyInsteadOfCountMethodWhenAvailable.cs @@ -79,57 +79,40 @@ private static void OnCompilationStart(CompilationStartAnalysisContext context) } } - private void AnalyzeInvocationOperation(OperationAnalysisContext obj) - { - throw new NotImplementedException(); - } - private sealed class OperationActionsContext { - private /*readonly*/ Lazy _immutableArrayType; + ////private /*readonly*/ Lazy _immutableArrayType; private readonly Lazy _iCollectionCountProperty; private readonly Lazy _iCollectionOfType; - private readonly Lazy _iCollectionOfTCountProperty; public OperationActionsContext(Compilation compilation, INamedTypeSymbol enumerableType) { Compilation = compilation; EnumerableType = enumerableType; - _immutableArrayType = new Lazy(() => Compilation.GetTypeByMetadataName("System.Collections.Immutable.ImmutableArray`1"), true); + ////_immutableArrayType = new Lazy(() => Compilation.GetTypeByMetadataName("System.Collections.Immutable.ImmutableArray`1"), true); _iCollectionCountProperty = new Lazy(() => WellKnownTypes.ICollection(Compilation)?.GetMembers(CountPropertyName).OfType().Single(), true); _iCollectionOfType = new Lazy(() => WellKnownTypes.GenericICollection(Compilation), true); - _iCollectionOfTCountProperty = new Lazy(() => ICollectionOfTType?.GetMembers(CountPropertyName).OfType().Single(), true); } internal Compilation Compilation { get; } - internal INamedTypeSymbol EnumerableType { get; } - - internal IPropertySymbol ICollectionCountProperty => _iCollectionCountProperty.Value; + private INamedTypeSymbol EnumerableType { get; } - internal IPropertySymbol ICollectionOfTCountProperty => _iCollectionOfTCountProperty.Value; + private IPropertySymbol ICollectionCountProperty => _iCollectionCountProperty.Value; - internal INamedTypeSymbol ICollectionOfTType => _iCollectionOfType.Value; + private INamedTypeSymbol ICollectionOfTType => _iCollectionOfType.Value; - internal INamedTypeSymbol ImmutableArrayType => _immutableArrayType.Value; + ////internal INamedTypeSymbol ImmutableArrayType => _immutableArrayType.Value; +#pragma warning disable CA1822 internal bool IsImmutableArrayType(ITypeSymbol typeSymbol) - { - if (typeSymbol is INamedTypeSymbol namedTypeSymbol && namedTypeSymbol.ConstructedFrom is INamedTypeSymbol constructedFrom) - { - if (ImmutableArrayType is null && - constructedFrom.MetadataName.ToString().Equals("ImmutableArray`1", StringComparison.Ordinal) && - constructedFrom.ContainingNamespace.ToString().Equals("System.Collections.Immutable", StringComparison.Ordinal)) - { - _immutableArrayType = new Lazy(() => constructedFrom, true); - return true; - } - - return constructedFrom.Equals(ImmutableArrayType); - } - - return false; - } + => typeSymbol is INamedTypeSymbol namedTypeSymbol && + namedTypeSymbol.MetadataName.Equals("ImmutableArray`1", StringComparison.Ordinal) && + namedTypeSymbol.ContainingNamespace.ToDisplayString().Equals("System.Collections.Immutable", StringComparison.Ordinal) && + namedTypeSymbol.ConstructedFrom is INamedTypeSymbol constructedFrom && + constructedFrom.MetadataName.Equals("ImmutableArray`1", StringComparison.Ordinal) && + constructedFrom.ContainingNamespace.ToDisplayString().Equals("System.Collections.Immutable", StringComparison.Ordinal); +#pragma warning restore CA1822 internal bool IsICollectionImplementation(ITypeSymbol invocationTarget) => this.ICollectionCountProperty is object && @@ -183,10 +166,11 @@ internal bool IsICollectionOfTImplementation(ITypeSymbol invocationTarget) return false; bool isCollectionOfTInterface(ITypeSymbol type) - { - return type.OriginalDefinition?.Equals(this.ICollectionOfTType) ?? false; - } + => this.ICollectionOfTType.Equals(type.OriginalDefinition); } + + internal bool IsEnumerableType(ISymbol symbol) + => this.EnumerableType.Equals(symbol); } /// @@ -257,7 +241,7 @@ protected override ITypeSymbol GetEnumerableCountInvocationTargetType(IInvocatio if (invocationOperation.Arguments.Length == 1 && method.Name.Equals(nameof(Enumerable.Count), StringComparison.Ordinal) && - method.ContainingSymbol.Equals(this.Context.EnumerableType) && + this.Context.IsEnumerableType(method.ContainingSymbol) && ((INamedTypeSymbol)(method.Parameters[0].Type)).TypeArguments[0] is ITypeSymbol methodSourceItemType) { return invocationOperation.Arguments[0].Value is IConversionOperation convertionOperation @@ -287,7 +271,7 @@ protected override ITypeSymbol GetEnumerableCountInvocationTargetType(IInvocatio if (invocationOperation.Arguments.Length == 0 && method.Name.Equals(nameof(Enumerable.Count), StringComparison.Ordinal) && - method.ContainingSymbol.Equals(this.Context.EnumerableType) && + this.Context.IsEnumerableType(method.ContainingSymbol) && ((INamedTypeSymbol)(invocationOperation.Instance.Type)).TypeArguments[0] is ITypeSymbol methodSourceItemType) { return invocationOperation.Instance is IConversionOperation convertionOperation diff --git a/src/Microsoft.NetCore.Analyzers/UnitTests/Performance/UsePropertyInsteadOfCountMethodWhenAvailableTests.cs b/src/Microsoft.NetCore.Analyzers/UnitTests/Performance/UsePropertyInsteadOfCountMethodWhenAvailableTests.cs index 32cb97aabf..137b47824a 100644 --- a/src/Microsoft.NetCore.Analyzers/UnitTests/Performance/UsePropertyInsteadOfCountMethodWhenAvailableTests.cs +++ b/src/Microsoft.NetCore.Analyzers/UnitTests/Performance/UsePropertyInsteadOfCountMethodWhenAvailableTests.cs @@ -5,7 +5,9 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Dynamic; +using System.Reflection; using System.Threading.Tasks; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Operations; using Microsoft.NetCore.Analyzers.Runtime; using Xunit; @@ -22,7 +24,12 @@ public static partial class UsePropertyInsteadOfCountMethodWhenAvailableTests { [Fact] public static Task CSharp_ImmutableArray_Tests() - => VerifyCS.VerifyCodeFixAsync( + => new VerifyCS.Test + { + TestState = + { + Sources= + { $@"using System; using System.Linq; public static class C @@ -32,6 +39,16 @@ public static class C public static int N() => {{|{UsePropertyInsteadOfCountMethodWhenAvailableAnalyzer.RuleId}:GetData().Count()|}}; }} ", + }, + AdditionalReferences = + { + MetadataReference.CreateFromFile(typeof(ImmutableArray<>).GetTypeInfo().Assembly.Location, default(MetadataReferenceProperties), null), + }, + }, + FixedState = + { + Sources= + { $@"using System; using System.Linq; public static class C @@ -40,7 +57,11 @@ public static class C public static int M() => GetData().Length; public static int N() => GetData().Length; }} -"); +" , + }, + }, + IncludeImmutableCollectionsReference = false, + }.RunAsync(); [Theory] [InlineData("string[]", nameof(Array.Length))]