Skip to content

Commit

Permalink
Added GetVisibleTypeByMetadataName extensions to Compilation.
Browse files Browse the repository at this point in the history
  • Loading branch information
paulomorgado committed Aug 28, 2019
1 parent c9835b7 commit 02b30d5
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,15 @@ private static void OnCompilationStart(CompilationStartAnalysisContext context)

private sealed class OperationActionsContext
{
////private /*readonly*/ Lazy<INamedTypeSymbol> _immutableArrayType;
private readonly Lazy<INamedTypeSymbol> _immutableArrayType;
private readonly Lazy<IPropertySymbol> _iCollectionCountProperty;
private readonly Lazy<INamedTypeSymbol> _iCollectionOfType;

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>(() => WellKnownTypes.ImmutableArray(Compilation), true);
_iCollectionCountProperty = new Lazy<IPropertySymbol>(() => WellKnownTypes.ICollection(Compilation)?.GetMembers(CountPropertyName).OfType<IPropertySymbol>().Single(), true);
_iCollectionOfType = new Lazy<INamedTypeSymbol>(() => WellKnownTypes.GenericICollection(Compilation), true);
}
Expand All @@ -102,17 +102,13 @@ public OperationActionsContext(Compilation compilation, INamedTypeSymbol enumera

private INamedTypeSymbol ICollectionOfTType => _iCollectionOfType.Value;

////internal INamedTypeSymbol ImmutableArrayType => _immutableArrayType.Value;
internal INamedTypeSymbol ImmutableArrayType => _immutableArrayType.Value;

#pragma warning disable CA1822
internal bool IsImmutableArrayType(ITypeSymbol typeSymbol)
=> typeSymbol is INamedTypeSymbol namedTypeSymbol &&
namedTypeSymbol.MetadataName.Equals("ImmutableArray`1", StringComparison.Ordinal) &&
namedTypeSymbol.ContainingNamespace.ToDisplayString().Equals("System.Collections.Immutable", StringComparison.Ordinal) &&
=> this.ImmutableArrayType is object &&
typeSymbol is INamedTypeSymbol namedTypeSymbol &&
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
constructedFrom.Equals(this.ImmutableArrayType);

internal bool IsICollectionImplementation(ITypeSymbol invocationTarget)
=> this.ICollectionCountProperty is object &&
Expand Down
1 change: 1 addition & 0 deletions src/Utilities/Compiler/Analyzer.Utilities.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
<Compile Include="$(MSBuildThisFileDirectory)CodeMetrics\SemanticModelProvider.cs" />
<Compile Include="$(MSBuildThisFileDirectory)CommonAccessibilityUtilities.cs" />
<Compile Include="$(MSBuildThisFileDirectory)DoNotCatchGeneralUnlessRethrown.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\CompilationExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\ImmutableArrayExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\KeyValuePairExtensions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\MethodKindEx.cs" />
Expand Down
66 changes: 66 additions & 0 deletions src/Utilities/Compiler/Extensions/CompilationExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System.Linq;
using Microsoft.CodeAnalysis;

namespace Analyzer.Utilities.Extensions
{
/// <summary>
/// Provides extensions to <see cref="Compilation"/>.
/// </summary>
internal static class CompilationExtensions
{
/// <summary>
/// Gets the type within the compilation's assembly using its canonical CLR metadata name. If not found, gets the first public type from all referenced assemblies. If not found, gets the first type from all referenced assemblies.
/// </summary>
/// <param name="compilation">The compilation.</param>
/// <param name="fullyQualifiedMetadataName">The fully qualified metadata name.</param>
/// <returns>A <see cref="INamedTypeSymbol"/> if found; <see langword="null"/> otherwise.</returns>
internal static INamedTypeSymbol GetVisibleTypeByMetadataName(this Compilation compilation, string fullyQualifiedMetadataName)
{
var typeSymbol = compilation.GetTypeByMetadataName(fullyQualifiedMetadataName);
if (typeSymbol is object)
{
return typeSymbol;
}

var segments = fullyQualifiedMetadataName.Split('.');

var @namespace = compilation.GlobalNamespace;

for (var s = 0; s < segments.Length - 1; s++)
{
@namespace = @namespace.GetMembers(segments[s]).OfType<INamespaceSymbol>().SingleOrDefault();

if (@namespace is null)
{
return null;
}
}

var metadataName = segments[segments.Length - 1];
INamedTypeSymbol publicType = null;
INamedTypeSymbol anyType = null;

foreach (var member in @namespace.GetMembers())
{
if (member is INamedTypeSymbol type && type.MetadataName == metadataName)
{
if (type.ContainingAssembly.Equals(compilation.Assembly))
{
return type;
}
else if (publicType is null && type.DeclaredAccessibility == Accessibility.Public)
{
publicType = type;
break;
}
else if (anyType is null)
{
anyType = type;
}
}
}

return publicType ?? anyType;
}
}
}
11 changes: 11 additions & 0 deletions src/Utilities/Compiler/WellKnownTypeNames.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,17 @@ internal static class WellKnownTypeNames
public const string SystemCollectionsIList = "System.Collections.IList";
public const string SystemCollectionsGenericIList1 = "System.Collections.Generic.IList`1";
public const string SystemCollectionsSpecializedNameValueCollection = "System.Collections.Specialized.NameValueCollection";
public const string SystemCollectionsImmutableImmutableArray = "System.Collections.Immutable.ImmutableArray`1";
public const string SystemCollectionsImmutableImmutableList = "System.Collections.Immutable.ImmutableList`1";
public const string SystemCollectionsImmutableImmutableHashSet = "System.Collections.Immutable.ImmutableHashSet`1";
public const string SystemCollectionsImmutableImmutableSortedSet = "System.Collections.Immutable.ImmutableSortedSet`1";
public const string SystemCollectionsImmutableImmutableDictionary = "System.Collections.Immutable.ImmutableDictionary`2";
public const string SystemCollectionsImmutableImmutableSortedDictionary = "System.Collections.Immutable.ImmutableSortedDictionary`2";
public const string SystemCollectionsImmutableIImmutableDictionary = "System.Collections.Immutable.IImmutableDictionary`2";
public const string SystemCollectionsImmutableIImmutableList = "System.Collections.Immutable.IImmutableList`1";
public const string SystemCollectionsImmutableIImmutableQueue = "System.Collections.Immutable.IImmutableQueue`1";
public const string SystemCollectionsImmutableIImmutableSet = "System.Collections.Immutable.IImmutableSet`1";
public const string SystemCollectionsImmutableIImmutableStack = "System.Collections.Immutable.IImmutableStack`1";
public const string SystemRuntimeSerializationFormattersBinaryBinaryFormatter = "System.Runtime.Serialization.Formatters.Binary.BinaryFormatter";
public const string SystemWebUILosFormatter = "System.Web.UI.LosFormatter";
public const string SystemReflectionAssemblyFullName = "System.Reflection.Assembly";
Expand Down
13 changes: 7 additions & 6 deletions src/Utilities/Compiler/WellKnownTypes.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using Analyzer.Utilities.Extensions;
using Microsoft.CodeAnalysis;

namespace Analyzer.Utilities
Expand Down Expand Up @@ -530,32 +531,32 @@ public static INamedTypeSymbol HttpVerbs(Compilation compilation)

public static INamedTypeSymbol ImmutableArray(Compilation compilation)
{
return compilation.GetTypeByMetadataName(typeof(System.Collections.Immutable.ImmutableArray<>).FullName);
return compilation.GetVisibleTypeByMetadataName(WellKnownTypeNames.SystemCollectionsImmutableImmutableArray);
}

public static INamedTypeSymbol IImmutableDictionary(Compilation compilation)
{
return compilation.GetTypeByMetadataName(typeof(System.Collections.Immutable.IImmutableDictionary<,>).FullName);
return compilation.GetTypeByMetadataName(WellKnownTypeNames.SystemCollectionsImmutableIImmutableDictionary);
}

public static INamedTypeSymbol IImmutableList(Compilation compilation)
{
return compilation.GetTypeByMetadataName(typeof(System.Collections.Immutable.IImmutableList<>).FullName);
return compilation.GetTypeByMetadataName(WellKnownTypeNames.SystemCollectionsImmutableIImmutableList);
}

public static INamedTypeSymbol IImmutableQueue(Compilation compilation)
{
return compilation.GetTypeByMetadataName(typeof(System.Collections.Immutable.IImmutableQueue<>).FullName);
return compilation.GetTypeByMetadataName(WellKnownTypeNames.SystemCollectionsImmutableIImmutableQueue);
}

public static INamedTypeSymbol IImmutableSet(Compilation compilation)
{
return compilation.GetTypeByMetadataName(typeof(System.Collections.Immutable.IImmutableSet<>).FullName);
return compilation.GetTypeByMetadataName(WellKnownTypeNames.SystemCollectionsImmutableIImmutableSet);
}

public static INamedTypeSymbol IImmutableStack(Compilation compilation)
{
return compilation.GetTypeByMetadataName(typeof(System.Collections.Immutable.IImmutableStack<>).FullName);
return compilation.GetTypeByMetadataName(WellKnownTypeNames.SystemCollectionsImmutableIImmutableStack);
}

public static INamedTypeSymbol SystemIOFile(Compilation compilation)
Expand Down

0 comments on commit 02b30d5

Please sign in to comment.