Replace SymbolLookupCache with comparing FullNames for symbols.

This commit is contained in:
Pranav K 2015-09-11 11:56:49 -07:00
parent 381c055e2f
commit 0376550f2d
5 changed files with 59 additions and 123 deletions

View File

@ -28,33 +28,29 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
/// </summary> /// </summary>
/// <typeparam name="TAttribute">The <see cref="Attribute"/> type.</typeparam> /// <typeparam name="TAttribute">The <see cref="Attribute"/> type.</typeparam>
/// <param name="symbol">The <see cref="ISymbol"/> to find attributes on.</param> /// <param name="symbol">The <see cref="ISymbol"/> to find attributes on.</param>
/// <param name="symbolLookup">The <see cref="CodeAnalysisSymbolLookupCache"/>.</param>
/// <returns></returns> /// <returns></returns>
public static IEnumerable<TAttribute> GetCustomAttributes<TAttribute>( public static IEnumerable<TAttribute> GetCustomAttributes<TAttribute>([NotNull] ISymbol symbol)
[NotNull] ISymbol symbol,
[NotNull] CodeAnalysisSymbolLookupCache symbolLookup)
where TAttribute : Attribute where TAttribute : Attribute
{ {
var attributes = symbol.GetAttributes(); var attributes = symbol.GetAttributes();
if (attributes.Length > 0) if (attributes.Length > 0)
{ {
var attributeSymbol = symbolLookup.GetSymbol(typeof(TAttribute).GetTypeInfo());
return attributes return attributes
.Where(attribute => attribute.AttributeClass == attributeSymbol) .Where(attribute => CodeAnalysisSymbolBasedTypeInfo.IsType(
.Select(attribute => CreateAttribute<TAttribute>(attribute, symbolLookup)) attribute.AttributeClass,
typeof(TAttribute).GetTypeInfo()))
.Select(attribute => CreateAttribute<TAttribute>(attribute))
.ToArray(); .ToArray();
} }
return Enumerable.Empty<TAttribute>(); return Enumerable.Empty<TAttribute>();
} }
private static TAttribute CreateAttribute<TAttribute>( private static TAttribute CreateAttribute<TAttribute>(AttributeData attributeData)
AttributeData attributeData,
CodeAnalysisSymbolLookupCache symbolLookup)
where TAttribute : Attribute where TAttribute : Attribute
{ {
TAttribute attribute; TAttribute attribute;
var matchInfo = MatchConstructor(typeof(TAttribute), attributeData.ConstructorArguments, symbolLookup); var matchInfo = MatchConstructor(typeof(TAttribute), attributeData.ConstructorArguments);
Func<object[], Attribute> constructorDelegate; Func<object[], Attribute> constructorDelegate;
if (!_constructorCache.TryGetValue(matchInfo.Constructor, out constructorDelegate)) if (!_constructorCache.TryGetValue(matchInfo.Constructor, out constructorDelegate))
{ {
@ -80,8 +76,7 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
var propertyValue = ConvertTypedConstantValue( var propertyValue = ConvertTypedConstantValue(
helper.Property.PropertyType, helper.Property.PropertyType,
item.Value, item.Value);
symbolLookup);
helper.SetValue(attribute, propertyValue); helper.SetValue(attribute, propertyValue);
} }
} }
@ -117,10 +112,9 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
private static ConstructorMatchInfo MatchConstructor( private static ConstructorMatchInfo MatchConstructor(
Type type, Type type,
ImmutableArray<TypedConstant> symbolConstructorArguments, ImmutableArray<TypedConstant> symbolConstructorArguments)
CodeAnalysisSymbolLookupCache symbolLookup)
{ {
var constructor = FindConstructor(type, symbolConstructorArguments, symbolLookup); var constructor = FindConstructor(type, symbolConstructorArguments);
var constructorParmaters = constructor.GetParameters(); var constructorParmaters = constructor.GetParameters();
var arguments = new object[symbolConstructorArguments.Length]; var arguments = new object[symbolConstructorArguments.Length];
@ -128,8 +122,7 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
{ {
var value = ConvertTypedConstantValue( var value = ConvertTypedConstantValue(
constructorParmaters[i].ParameterType, constructorParmaters[i].ParameterType,
symbolConstructorArguments[i], symbolConstructorArguments[i]);
symbolLookup);
arguments[i] = value; arguments[i] = value;
} }
@ -143,8 +136,7 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
private static ConstructorInfo FindConstructor( private static ConstructorInfo FindConstructor(
Type type, Type type,
ImmutableArray<TypedConstant> symbolConstructorArguments, ImmutableArray<TypedConstant> symbolConstructorArguments)
CodeAnalysisSymbolLookupCache symbolLookup)
{ {
var constructors = type.GetConstructors(); var constructors = type.GetConstructors();
foreach (var constructor in constructors) foreach (var constructor in constructors)
@ -163,8 +155,9 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
runtimeParameter.IsArray) runtimeParameter.IsArray)
{ {
var arrayType = (IArrayTypeSymbol)symbolConstructorArguments[index].Type; var arrayType = (IArrayTypeSymbol)symbolConstructorArguments[index].Type;
if (symbolLookup.GetSymbol(runtimeParameter.GetElementType().GetTypeInfo()) != if (!CodeAnalysisSymbolBasedTypeInfo.IsType(
arrayType.ElementType) arrayType.ElementType,
runtimeParameter.GetElementType().GetTypeInfo()))
{ {
parametersMatched = false; parametersMatched = false;
break; break;
@ -172,8 +165,9 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
} }
else else
{ {
var parameterSymbol = symbolLookup.GetSymbol(runtimeParameter.GetTypeInfo()); if (!CodeAnalysisSymbolBasedTypeInfo.IsType(
if (symbolConstructorArguments[index].Type != parameterSymbol) symbolConstructorArguments[index].Type,
runtimeParameter.GetTypeInfo()))
{ {
parametersMatched = false; parametersMatched = false;
break; break;
@ -192,8 +186,7 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
private static object ConvertTypedConstantValue( private static object ConvertTypedConstantValue(
Type type, Type type,
TypedConstant constructorArgument, TypedConstant constructorArgument)
CodeAnalysisSymbolLookupCache symbolLookup)
{ {
switch (constructorArgument.Kind) switch (constructorArgument.Kind)
{ {
@ -212,7 +205,7 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
for (var index = 0; index < values.Length; index++) for (var index = 0; index < values.Length; index++)
{ {
values.SetValue( values.SetValue(
ConvertTypedConstantValue(elementType, constructorArgument.Values[index], symbolLookup), ConvertTypedConstantValue(elementType, constructorArgument.Values[index]),
index); index);
} }
return values; return values;

View File

@ -17,20 +17,15 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
public class CodeAnalysisSymbolBasedPropertyInfo : IPropertyInfo public class CodeAnalysisSymbolBasedPropertyInfo : IPropertyInfo
{ {
private readonly IPropertySymbol _propertySymbol; private readonly IPropertySymbol _propertySymbol;
private readonly CodeAnalysisSymbolLookupCache _symbolLookup;
/// <summary> /// <summary>
/// Initializes a new instance of <see cref="CodeAnalysisSymbolBasedPropertyInfo"/>. /// Initializes a new instance of <see cref="CodeAnalysisSymbolBasedPropertyInfo"/>.
/// </summary> /// </summary>
/// <param name="propertySymbol">The <see cref="IPropertySymbol"/>.</param> /// <param name="propertySymbol">The <see cref="IPropertySymbol"/>.</param>
/// <param name="symbolLookup">The <see cref="CodeAnalysisSymbolLookupCache"/>.</param> public CodeAnalysisSymbolBasedPropertyInfo([NotNull] IPropertySymbol propertySymbol)
public CodeAnalysisSymbolBasedPropertyInfo(
[NotNull] IPropertySymbol propertySymbol,
[NotNull] CodeAnalysisSymbolLookupCache symbolLookup)
{ {
_symbolLookup = symbolLookup;
_propertySymbol = propertySymbol; _propertySymbol = propertySymbol;
PropertyType = new CodeAnalysisSymbolBasedTypeInfo(_propertySymbol.Type, _symbolLookup); PropertyType = new CodeAnalysisSymbolBasedTypeInfo(_propertySymbol.Type);
} }
/// <inheritdoc /> /// <inheritdoc />
@ -63,7 +58,7 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
public IEnumerable<TAttribute> GetCustomAttributes<TAttribute>() public IEnumerable<TAttribute> GetCustomAttributes<TAttribute>()
where TAttribute : Attribute where TAttribute : Attribute
{ {
return CodeAnalysisAttributeUtilities.GetCustomAttributes<TAttribute>(_propertySymbol, _symbolLookup); return CodeAnalysisAttributeUtilities.GetCustomAttributes<TAttribute>(_propertySymbol);
} }
} }
} }

View File

@ -24,7 +24,8 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
/// </summary> /// </summary>
public static readonly System.Reflection.TypeInfo OpenGenericDictionaryTypeInfo = public static readonly System.Reflection.TypeInfo OpenGenericDictionaryTypeInfo =
typeof(IDictionary<,>).GetTypeInfo(); typeof(IDictionary<,>).GetTypeInfo();
private readonly CodeAnalysisSymbolLookupCache _symbolLookup; private static readonly System.Reflection.TypeInfo TagHelperTypeInfo =
typeof(ITagHelper).GetTypeInfo();
private readonly ITypeSymbol _type; private readonly ITypeSymbol _type;
private readonly ITypeSymbol _underlyingType; private readonly ITypeSymbol _underlyingType;
private string _fullName; private string _fullName;
@ -34,12 +35,8 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
/// Initializes a new instance of <see cref="CodeAnalysisSymbolBasedTypeInfo"/>. /// Initializes a new instance of <see cref="CodeAnalysisSymbolBasedTypeInfo"/>.
/// </summary> /// </summary>
/// <param name="propertySymbol">The <see cref="IPropertySymbol"/>.</param> /// <param name="propertySymbol">The <see cref="IPropertySymbol"/>.</param>
/// <param name="symbolLookup">The <see cref="CodeAnalysisSymbolLookupCache"/>.</param> public CodeAnalysisSymbolBasedTypeInfo([NotNull] ITypeSymbol type)
public CodeAnalysisSymbolBasedTypeInfo(
[NotNull] ITypeSymbol type,
[NotNull] CodeAnalysisSymbolLookupCache symbolLookup)
{ {
_symbolLookup = symbolLookup;
_type = type; _type = type;
_underlyingType = UnwrapArrayType(type); _underlyingType = UnwrapArrayType(type);
} }
@ -110,7 +107,7 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
{ {
if (_properties == null) if (_properties == null)
{ {
_properties = GetProperties(_type, _symbolLookup); _properties = GetProperties(_type);
} }
return _properties; return _properties;
@ -122,8 +119,8 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
{ {
get get
{ {
var interfaceSymbol = _symbolLookup.GetSymbol(typeof(ITagHelper).GetTypeInfo()); return _type.AllInterfaces.Any(
return _type.AllInterfaces.Any(implementedInterface => implementedInterface == interfaceSymbol); implementedInterface => IsType(implementedInterface, TagHelperTypeInfo));
} }
} }
@ -131,17 +128,15 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
public IEnumerable<TAttribute> GetCustomAttributes<TAttribute>() public IEnumerable<TAttribute> GetCustomAttributes<TAttribute>()
where TAttribute : Attribute where TAttribute : Attribute
{ {
return CodeAnalysisAttributeUtilities.GetCustomAttributes<TAttribute>(_type, _symbolLookup); return CodeAnalysisAttributeUtilities.GetCustomAttributes<TAttribute>(_type);
} }
/// <inheritdoc /> /// <inheritdoc />
public ITypeInfo[] GetGenericDictionaryParameters() public ITypeInfo[] GetGenericDictionaryParameters()
{ {
var dictionarySymbol = _symbolLookup.GetSymbol(OpenGenericDictionaryTypeInfo);
INamedTypeSymbol dictionaryInterface; INamedTypeSymbol dictionaryInterface;
if (_type.Kind == SymbolKind.NamedType && if (_type.Kind == SymbolKind.NamedType &&
((INamedTypeSymbol)_type).ConstructedFrom == dictionarySymbol) IsType(((INamedTypeSymbol)_type).ConstructedFrom, OpenGenericDictionaryTypeInfo))
{ {
dictionaryInterface = (INamedTypeSymbol)_type; dictionaryInterface = (INamedTypeSymbol)_type;
} }
@ -149,7 +144,8 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
{ {
dictionaryInterface = _type dictionaryInterface = _type
.AllInterfaces .AllInterfaces
.FirstOrDefault(implementedInterface => implementedInterface.ConstructedFrom == dictionarySymbol); .FirstOrDefault(implementedInterface =>
IsType(implementedInterface.ConstructedFrom, OpenGenericDictionaryTypeInfo));
} }
if (dictionaryInterface != null) if (dictionaryInterface != null)
@ -158,14 +154,32 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
return new[] return new[]
{ {
new CodeAnalysisSymbolBasedTypeInfo(dictionaryInterface.TypeArguments[0], _symbolLookup), new CodeAnalysisSymbolBasedTypeInfo(dictionaryInterface.TypeArguments[0]),
new CodeAnalysisSymbolBasedTypeInfo(dictionaryInterface.TypeArguments[1], _symbolLookup), new CodeAnalysisSymbolBasedTypeInfo(dictionaryInterface.TypeArguments[1]),
}; };
} }
return null; return null;
} }
/// <summary>
/// Gets a value that indicates if <paramref name="targetTypeInfo"/> is represented using
/// <paramref name="sourceTypeSymbol"/> in the symbol graph.
/// </summary>
/// <param name="sourceTypeSymbol">The <see cref="ITypeSymbol"/>.</param>
/// <param name="targetTypeInfo">The <see cref="System.Reflection.TypeInfo"/>.</param>
/// <returns><c>true</c> if <paramref name="targetTypeInfo"/> is a symbol for
/// <paramref name="sourceTypeSymbol"/>.</returns>
public static bool IsType(
ITypeSymbol sourceTypeSymbol,
System.Reflection.TypeInfo targetTypeInfo)
{
return string.Equals(
targetTypeInfo.FullName,
GetFullName(sourceTypeSymbol),
StringComparison.Ordinal);
}
/// <summary> /// <summary>
/// Gets the assembly qualified named of the specified <paramref name="symbol"/>. /// Gets the assembly qualified named of the specified <paramref name="symbol"/>.
/// </summary> /// </summary>
@ -205,9 +219,7 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
/// <inheritdoc /> /// <inheritdoc />
public override int GetHashCode() => FullName.GetHashCode(); public override int GetHashCode() => FullName.GetHashCode();
private static List<IPropertyInfo> GetProperties( private static List<IPropertyInfo> GetProperties(ITypeSymbol typeSymbol)
ITypeSymbol typeSymbol,
CodeAnalysisSymbolLookupCache symbolLookup)
{ {
var properties = new List<IPropertyInfo>(); var properties = new List<IPropertyInfo>();
var overridenProperties = new HashSet<IPropertySymbol>(); var overridenProperties = new HashSet<IPropertySymbol>();
@ -219,7 +231,7 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
var propertySymbol = (IPropertySymbol)member; var propertySymbol = (IPropertySymbol)member;
if (!propertySymbol.IsIndexer && !overridenProperties.Contains(propertySymbol)) if (!propertySymbol.IsIndexer && !overridenProperties.Contains(propertySymbol))
{ {
var propertyInfo = new CodeAnalysisSymbolBasedPropertyInfo(propertySymbol, symbolLookup); var propertyInfo = new CodeAnalysisSymbolBasedPropertyInfo(propertySymbol);
properties.Add(propertyInfo); properties.Add(propertyInfo);
} }

View File

@ -1,62 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.CodeAnalysis;
using Microsoft.Framework.Internal;
namespace Microsoft.AspNet.Razor.Runtime.Precompilation
{
/// <summary>
/// Caches mapping of <see cref="System.Reflection.TypeInfo"/> to <see cref="INamedTypeSymbol"/>.
/// </summary>
public class CodeAnalysisSymbolLookupCache
{
private readonly Dictionary<System.Reflection.TypeInfo, INamedTypeSymbol> _symbolLookup =
new Dictionary<System.Reflection.TypeInfo, INamedTypeSymbol>();
private readonly object _lookupLock = new object();
private readonly Compilation _compilation;
private INamedTypeSymbol _dictionarySymbol;
/// <summary>
/// Initialzes a new instance of <see cref="CodeAnalysisSymbolLookupCache"/>.
/// </summary>
/// <param name="compilation">The <see cref="Compilation"/> instance.</param>
public CodeAnalysisSymbolLookupCache([NotNull] Compilation compilation)
{
_compilation = compilation;
}
/// <summary>
/// Gets a <see cref="INamedTypeSymbol"/> that corresponds to <paramref name="typeInfo"/>.
/// </summary>
/// <param name="typeInfo">The <see cref="System.Reflection.TypeInfo"/> to lookup.</param>
/// <returns></returns>
public INamedTypeSymbol GetSymbol([NotNull] System.Reflection.TypeInfo typeInfo)
{
if (typeInfo == CodeAnalysisSymbolBasedTypeInfo.OpenGenericDictionaryTypeInfo)
{
if (_dictionarySymbol == null)
{
// Allow safe races
_dictionarySymbol = _compilation.GetTypeByMetadataName(
CodeAnalysisSymbolBasedTypeInfo.OpenGenericDictionaryTypeInfo.FullName);
}
return _dictionarySymbol;
}
lock (_lookupLock)
{
INamedTypeSymbol typeSymbol;
if (!_symbolLookup.TryGetValue(typeInfo, out typeSymbol))
{
typeSymbol = _compilation.GetTypeByMetadataName(typeInfo.FullName);
_symbolLookup[typeInfo] = typeSymbol;
}
return typeSymbol;
}
}
}
}

View File

@ -19,7 +19,6 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
private readonly Dictionary<string, IEnumerable<ITypeInfo>> _assemblyLookup private readonly Dictionary<string, IEnumerable<ITypeInfo>> _assemblyLookup
= new Dictionary<string, IEnumerable<ITypeInfo>>(StringComparer.Ordinal); = new Dictionary<string, IEnumerable<ITypeInfo>>(StringComparer.Ordinal);
private readonly Compilation _compilation; private readonly Compilation _compilation;
private readonly CodeAnalysisSymbolLookupCache _symbolLookup;
/// <summary> /// <summary>
/// Initializes a new instance of <see cref="PrecompilationTagHelperTypeResolver"/>. /// Initializes a new instance of <see cref="PrecompilationTagHelperTypeResolver"/>.
@ -28,11 +27,10 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
public PrecompilationTagHelperTypeResolver([NotNull] Compilation compilation) public PrecompilationTagHelperTypeResolver([NotNull] Compilation compilation)
{ {
_compilation = compilation; _compilation = compilation;
_symbolLookup = new CodeAnalysisSymbolLookupCache(compilation);
} }
/// <inheritdoc /> /// <inheritdoc />
protected override IEnumerable<ITypeInfo> GetTopLevelExportedTypes([NotNull] AssemblyName assemblyName) protected override IEnumerable<ITypeInfo> GetTopLevelExportedTypes([NotNull] AssemblyName assemblyName)
{ {
lock (_assemblyLookupLock) lock (_assemblyLookupLock)
{ {
@ -83,21 +81,21 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
Resources.FormatCodeAnalysis_UnableToLoadAssemblyReference(assemblyName)); Resources.FormatCodeAnalysis_UnableToLoadAssemblyReference(assemblyName));
} }
private List<ITypeInfo> GetExportedTypes(IAssemblySymbol assembly) private static List<ITypeInfo> GetExportedTypes(IAssemblySymbol assembly)
{ {
var exportedTypes = new List<ITypeInfo>(); var exportedTypes = new List<ITypeInfo>();
GetExportedTypes(assembly.GlobalNamespace, exportedTypes); GetExportedTypes(assembly.GlobalNamespace, exportedTypes);
return exportedTypes; return exportedTypes;
} }
private void GetExportedTypes(INamespaceSymbol namespaceSymbol, List<ITypeInfo> exportedTypes) private static void GetExportedTypes(INamespaceSymbol namespaceSymbol, List<ITypeInfo> exportedTypes)
{ {
foreach (var type in namespaceSymbol.GetTypeMembers()) foreach (var type in namespaceSymbol.GetTypeMembers())
{ {
if (type.TypeKind == TypeKind.Class && if (type.TypeKind == TypeKind.Class &&
type.DeclaredAccessibility == Accessibility.Public) type.DeclaredAccessibility == Accessibility.Public)
{ {
exportedTypes.Add(new CodeAnalysisSymbolBasedTypeInfo(type, _symbolLookup)); exportedTypes.Add(new CodeAnalysisSymbolBasedTypeInfo(type));
} }
} }