Skip to content

Commit

Permalink
workaround for ImmutableArray<T>
Browse files Browse the repository at this point in the history
  • Loading branch information
paulomorgado committed Aug 13, 2019
1 parent 7659926 commit f3be974
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 38 deletions.
Expand Up @@ -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<INamedTypeSymbol> _immutableArrayType;
////private /*readonly*/ Lazy<INamedTypeSymbol> _immutableArrayType;
private readonly Lazy<IPropertySymbol> _iCollectionCountProperty;
private readonly Lazy<INamedTypeSymbol> _iCollectionOfType;
private readonly Lazy<IPropertySymbol> _iCollectionOfTCountProperty;

public OperationActionsContext(Compilation compilation, INamedTypeSymbol enumerableType)
{
Compilation = compilation;
EnumerableType = enumerableType;
_immutableArrayType = new Lazy<INamedTypeSymbol>(() => Compilation.GetTypeByMetadataName("System.Collections.Immutable.ImmutableArray`1"), true);
////_immutableArrayType = new Lazy<INamedTypeSymbol>(() => Compilation.GetTypeByMetadataName("System.Collections.Immutable.ImmutableArray`1"), true);
_iCollectionCountProperty = new Lazy<IPropertySymbol>(() => WellKnownTypes.ICollection(Compilation)?.GetMembers(CountPropertyName).OfType<IPropertySymbol>().Single(), true);
_iCollectionOfType = new Lazy<INamedTypeSymbol>(() => WellKnownTypes.GenericICollection(Compilation), true);
_iCollectionOfTCountProperty = new Lazy<IPropertySymbol>(() => ICollectionOfTType?.GetMembers(CountPropertyName).OfType<IPropertySymbol>().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<INamedTypeSymbol>(() => 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 &&
Expand Down Expand Up @@ -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);
}

/// <summary>
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
Expand Up @@ -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;
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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))]
Expand Down

0 comments on commit f3be974

Please sign in to comment.