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

View File

@ -17,20 +17,15 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
public class CodeAnalysisSymbolBasedPropertyInfo : IPropertyInfo
{
private readonly IPropertySymbol _propertySymbol;
private readonly CodeAnalysisSymbolLookupCache _symbolLookup;
/// <summary>
/// Initializes a new instance of <see cref="CodeAnalysisSymbolBasedPropertyInfo"/>.
/// </summary>
/// <param name="propertySymbol">The <see cref="IPropertySymbol"/>.</param>
/// <param name="symbolLookup">The <see cref="CodeAnalysisSymbolLookupCache"/>.</param>
public CodeAnalysisSymbolBasedPropertyInfo(
[NotNull] IPropertySymbol propertySymbol,
[NotNull] CodeAnalysisSymbolLookupCache symbolLookup)
public CodeAnalysisSymbolBasedPropertyInfo([NotNull] IPropertySymbol propertySymbol)
{
_symbolLookup = symbolLookup;
_propertySymbol = propertySymbol;
PropertyType = new CodeAnalysisSymbolBasedTypeInfo(_propertySymbol.Type, _symbolLookup);
PropertyType = new CodeAnalysisSymbolBasedTypeInfo(_propertySymbol.Type);
}
/// <inheritdoc />
@ -63,7 +58,7 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
public IEnumerable<TAttribute> GetCustomAttributes<TAttribute>()
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>
public static readonly System.Reflection.TypeInfo OpenGenericDictionaryTypeInfo =
typeof(IDictionary<,>).GetTypeInfo();
private readonly CodeAnalysisSymbolLookupCache _symbolLookup;
private static readonly System.Reflection.TypeInfo TagHelperTypeInfo =
typeof(ITagHelper).GetTypeInfo();
private readonly ITypeSymbol _type;
private readonly ITypeSymbol _underlyingType;
private string _fullName;
@ -34,12 +35,8 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
/// Initializes a new instance of <see cref="CodeAnalysisSymbolBasedTypeInfo"/>.
/// </summary>
/// <param name="propertySymbol">The <see cref="IPropertySymbol"/>.</param>
/// <param name="symbolLookup">The <see cref="CodeAnalysisSymbolLookupCache"/>.</param>
public CodeAnalysisSymbolBasedTypeInfo(
[NotNull] ITypeSymbol type,
[NotNull] CodeAnalysisSymbolLookupCache symbolLookup)
public CodeAnalysisSymbolBasedTypeInfo([NotNull] ITypeSymbol type)
{
_symbolLookup = symbolLookup;
_type = type;
_underlyingType = UnwrapArrayType(type);
}
@ -110,7 +107,7 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
{
if (_properties == null)
{
_properties = GetProperties(_type, _symbolLookup);
_properties = GetProperties(_type);
}
return _properties;
@ -122,8 +119,8 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
{
get
{
var interfaceSymbol = _symbolLookup.GetSymbol(typeof(ITagHelper).GetTypeInfo());
return _type.AllInterfaces.Any(implementedInterface => implementedInterface == interfaceSymbol);
return _type.AllInterfaces.Any(
implementedInterface => IsType(implementedInterface, TagHelperTypeInfo));
}
}
@ -131,17 +128,15 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
public IEnumerable<TAttribute> GetCustomAttributes<TAttribute>()
where TAttribute : Attribute
{
return CodeAnalysisAttributeUtilities.GetCustomAttributes<TAttribute>(_type, _symbolLookup);
return CodeAnalysisAttributeUtilities.GetCustomAttributes<TAttribute>(_type);
}
/// <inheritdoc />
public ITypeInfo[] GetGenericDictionaryParameters()
{
var dictionarySymbol = _symbolLookup.GetSymbol(OpenGenericDictionaryTypeInfo);
INamedTypeSymbol dictionaryInterface;
if (_type.Kind == SymbolKind.NamedType &&
((INamedTypeSymbol)_type).ConstructedFrom == dictionarySymbol)
IsType(((INamedTypeSymbol)_type).ConstructedFrom, OpenGenericDictionaryTypeInfo))
{
dictionaryInterface = (INamedTypeSymbol)_type;
}
@ -149,7 +144,8 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
{
dictionaryInterface = _type
.AllInterfaces
.FirstOrDefault(implementedInterface => implementedInterface.ConstructedFrom == dictionarySymbol);
.FirstOrDefault(implementedInterface =>
IsType(implementedInterface.ConstructedFrom, OpenGenericDictionaryTypeInfo));
}
if (dictionaryInterface != null)
@ -158,14 +154,32 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
return new[]
{
new CodeAnalysisSymbolBasedTypeInfo(dictionaryInterface.TypeArguments[0], _symbolLookup),
new CodeAnalysisSymbolBasedTypeInfo(dictionaryInterface.TypeArguments[1], _symbolLookup),
new CodeAnalysisSymbolBasedTypeInfo(dictionaryInterface.TypeArguments[0]),
new CodeAnalysisSymbolBasedTypeInfo(dictionaryInterface.TypeArguments[1]),
};
}
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>
/// Gets the assembly qualified named of the specified <paramref name="symbol"/>.
/// </summary>
@ -205,9 +219,7 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
/// <inheritdoc />
public override int GetHashCode() => FullName.GetHashCode();
private static List<IPropertyInfo> GetProperties(
ITypeSymbol typeSymbol,
CodeAnalysisSymbolLookupCache symbolLookup)
private static List<IPropertyInfo> GetProperties(ITypeSymbol typeSymbol)
{
var properties = new List<IPropertyInfo>();
var overridenProperties = new HashSet<IPropertySymbol>();
@ -219,7 +231,7 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
var propertySymbol = (IPropertySymbol)member;
if (!propertySymbol.IsIndexer && !overridenProperties.Contains(propertySymbol))
{
var propertyInfo = new CodeAnalysisSymbolBasedPropertyInfo(propertySymbol, symbolLookup);
var propertyInfo = new CodeAnalysisSymbolBasedPropertyInfo(propertySymbol);
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
= new Dictionary<string, IEnumerable<ITypeInfo>>(StringComparer.Ordinal);
private readonly Compilation _compilation;
private readonly CodeAnalysisSymbolLookupCache _symbolLookup;
/// <summary>
/// Initializes a new instance of <see cref="PrecompilationTagHelperTypeResolver"/>.
@ -28,11 +27,10 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
public PrecompilationTagHelperTypeResolver([NotNull] Compilation compilation)
{
_compilation = compilation;
_symbolLookup = new CodeAnalysisSymbolLookupCache(compilation);
}
/// <inheritdoc />
protected override IEnumerable<ITypeInfo> GetTopLevelExportedTypes([NotNull] AssemblyName assemblyName)
protected override IEnumerable<ITypeInfo> GetTopLevelExportedTypes([NotNull] AssemblyName assemblyName)
{
lock (_assemblyLookupLock)
{
@ -83,21 +81,21 @@ namespace Microsoft.AspNet.Razor.Runtime.Precompilation
Resources.FormatCodeAnalysis_UnableToLoadAssemblyReference(assemblyName));
}
private List<ITypeInfo> GetExportedTypes(IAssemblySymbol assembly)
private static List<ITypeInfo> GetExportedTypes(IAssemblySymbol assembly)
{
var exportedTypes = new List<ITypeInfo>();
GetExportedTypes(assembly.GlobalNamespace, 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())
{
if (type.TypeKind == TypeKind.Class &&
type.DeclaredAccessibility == Accessibility.Public)
{
exportedTypes.Add(new CodeAnalysisSymbolBasedTypeInfo(type, _symbolLookup));
exportedTypes.Add(new CodeAnalysisSymbolBasedTypeInfo(type));
}
}