Browse Source

Add ITypeResolveContext.GetKnownTypeDefinition() for efficiently retrieving built-in types.

newNRvisualizers
Daniel Grunwald 15 years ago
parent
commit
2b3d66998b
  1. 43
      ICSharpCode.NRefactory/CSharp/Analysis/MinimalResolveContext.cs
  2. 9
      ICSharpCode.NRefactory/Documentation/IDStringProvider.cs
  3. 10
      ICSharpCode.NRefactory/TypeSystem/ITypeResolveContext.cs
  4. 30
      ICSharpCode.NRefactory/TypeSystem/Implementation/CompositeTypeResolveContext.cs
  5. 32
      ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs
  6. 6
      ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs
  7. 10
      ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs
  8. 6
      ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs
  9. 71
      ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs
  10. 45
      ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs

43
ICSharpCode.NRefactory/CSharp/Analysis/MinimalResolveContext.cs

@ -44,14 +44,21 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
private MinimalResolveContext() private MinimalResolveContext()
{ {
List<ITypeDefinition> types = new List<ITypeDefinition>(); List<ITypeDefinition> types = new List<ITypeDefinition>();
types.Add(systemObject = new DefaultTypeDefinition(this, "System", "Object") {
Accessibility = Accessibility.Public systemObject = new DefaultTypeDefinition(this, "System", "Object") {
}); Accessibility = Accessibility.Public
types.Add(systemValueType = new DefaultTypeDefinition(this, "System", "ValueType") { };
Accessibility = Accessibility.Public, systemValueType = new DefaultTypeDefinition(this, "System", "ValueType") {
BaseTypes = { systemObject } Accessibility = Accessibility.Public,
}); BaseTypes = { systemObject }
};
// TypeCode.Empty = void
types.Add(new VoidTypeDefinition(this));
// types are added in the order they are defined in the TypeCode enum
types.Add(systemObject);
types.Add(CreateClass("System", "DBNull"));
types.Add(CreateStruct("System", "Boolean")); types.Add(CreateStruct("System", "Boolean"));
types.Add(CreateStruct("System", "Char"));
types.Add(CreateStruct("System", "SByte")); types.Add(CreateStruct("System", "SByte"));
types.Add(CreateStruct("System", "Byte")); types.Add(CreateStruct("System", "Byte"));
types.Add(CreateStruct("System", "Int16")); types.Add(CreateStruct("System", "Int16"));
@ -63,16 +70,23 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
types.Add(CreateStruct("System", "Single")); types.Add(CreateStruct("System", "Single"));
types.Add(CreateStruct("System", "Double")); types.Add(CreateStruct("System", "Double"));
types.Add(CreateStruct("System", "Decimal")); types.Add(CreateStruct("System", "Decimal"));
types.Add(new DefaultTypeDefinition(this, "System", "String") { types.Add(CreateStruct("System", "DateTime"));
Accessibility = Accessibility.Public, types.Add(systemValueType); // misuse unused enum value (TypeCode)17 for System.ValueType
BaseTypes = { systemObject } types.Add(CreateClass("System", "String"));
});
types.Add(new VoidTypeDefinition(this));
foreach (ITypeDefinition type in types) foreach (ITypeDefinition type in types)
type.Freeze(); type.Freeze();
this.types = types.AsReadOnly(); this.types = types.AsReadOnly();
} }
ITypeDefinition CreateClass(string nameSpace, string name)
{
return new DefaultTypeDefinition(this, nameSpace, name) {
Kind = TypeKind.Class,
Accessibility = Accessibility.Public,
BaseTypes = { systemObject }
};
}
ITypeDefinition CreateStruct(string nameSpace, string name) ITypeDefinition CreateStruct(string nameSpace, string name)
{ {
return new DefaultTypeDefinition(this, nameSpace, name) { return new DefaultTypeDefinition(this, nameSpace, name) {
@ -91,6 +105,11 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis
return null; return null;
} }
public ITypeDefinition GetKnownTypeDefinition(TypeCode typeCode)
{
return types[(int)typeCode];
}
public IEnumerable<ITypeDefinition> GetTypes() public IEnumerable<ITypeDefinition> GetTypes()
{ {
return types; return types;

9
ICSharpCode.NRefactory/Documentation/IDStringProvider.cs

@ -240,6 +240,15 @@ namespace ICSharpCode.NRefactory.Documentation
static int AppendParameterizedTypeName(StringBuilder b, ITypeReference type, IList<ITypeReference> typeArguments, ITypeResolveContext context) static int AppendParameterizedTypeName(StringBuilder b, ITypeReference type, IList<ITypeReference> typeArguments, ITypeResolveContext context)
{ {
KnownTypeReference knownType = type as KnownTypeReference;
if (knownType != null) {
if (!string.IsNullOrEmpty(knownType.Namespace)) {
b.Append(knownType.Namespace);
b.Append('.');
}
b.Append(knownType.Name);
return 0;
}
GetClassTypeReference gctr = type as GetClassTypeReference; GetClassTypeReference gctr = type as GetClassTypeReference;
if (gctr != null) { if (gctr != null) {
if (!string.IsNullOrEmpty(gctr.Namespace)) { if (!string.IsNullOrEmpty(gctr.Namespace)) {

10
ICSharpCode.NRefactory/TypeSystem/ITypeResolveContext.cs

@ -32,6 +32,16 @@ namespace ICSharpCode.NRefactory.TypeSystem
#endif #endif
public interface ITypeResolveContext public interface ITypeResolveContext
{ {
/// <summary>
/// Gets the definition for a known type.
/// </summary>
/// <returns>Returns the type definition; or null if the type was not found</returns>
/// <remarks>
/// This method will may only be called with the 'known types' (see members of KnownTypeReference).
/// As a special case, TypeCode.Empty is used to represent System.Void.
/// </remarks>
ITypeDefinition GetKnownTypeDefinition(TypeCode typeCode);
/// <summary> /// <summary>
/// Retrieves a type. /// Retrieves a type.
/// </summary> /// </summary>

30
ICSharpCode.NRefactory/TypeSystem/Implementation/CompositeTypeResolveContext.cs

@ -66,6 +66,17 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
this.children = children; this.children = children;
} }
/// <inheritdoc/>
public virtual ITypeDefinition GetKnownTypeDefinition(TypeCode typeCode)
{
foreach (ITypeResolveContext context in children) {
ITypeDefinition d = context.GetKnownTypeDefinition(typeCode);
if (d != null)
return d;
}
return null;
}
/// <inheritdoc/> /// <inheritdoc/>
public ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) public ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer)
{ {
@ -117,7 +128,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
if (sync[i] == null) if (sync[i] == null)
throw new InvalidOperationException(children[i] + ".Synchronize() returned null"); throw new InvalidOperationException(children[i] + ".Synchronize() returned null");
} }
ISynchronizedTypeResolveContext r = new CompositeSynchronizedTypeResolveContext(sync, new CacheManager(), true); var knownTypeDefinitions = new ITypeDefinition[ReflectionHelper.ByTypeCodeArraySize];
var r = new CompositeSynchronizedTypeResolveContext(sync, knownTypeDefinitions, new CacheManager(), true);
success = true; success = true;
return r; return r;
} finally { } finally {
@ -141,12 +153,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{ {
readonly CacheManager cacheManager; readonly CacheManager cacheManager;
readonly bool isTopLevel; readonly bool isTopLevel;
readonly ITypeDefinition[] knownTypeDefinitions;
public CompositeSynchronizedTypeResolveContext(ITypeResolveContext[] children, CacheManager cacheManager, bool isTopLevel) public CompositeSynchronizedTypeResolveContext(ITypeResolveContext[] children, ITypeDefinition[] knownTypeDefinitions, CacheManager cacheManager, bool isTopLevel)
: base(children) : base(children)
{ {
Debug.Assert(cacheManager != null); Debug.Assert(cacheManager != null);
this.cacheManager = cacheManager; this.cacheManager = cacheManager;
this.knownTypeDefinitions = knownTypeDefinitions;
this.isTopLevel = isTopLevel; this.isTopLevel = isTopLevel;
} }
@ -167,11 +181,21 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
get { return cacheManager; } get { return cacheManager; }
} }
public override ITypeDefinition GetKnownTypeDefinition(TypeCode typeCode)
{
ITypeDefinition typeDef = knownTypeDefinitions[(int)typeCode];
if (typeDef != null)
return typeDef;
typeDef = base.GetKnownTypeDefinition(typeCode);
knownTypeDefinitions[(int)typeCode] = typeDef;
return typeDef;
}
public override ISynchronizedTypeResolveContext Synchronize() public override ISynchronizedTypeResolveContext Synchronize()
{ {
// re-use the same cache manager for nested synchronized contexts // re-use the same cache manager for nested synchronized contexts
if (isTopLevel) if (isTopLevel)
return new CompositeSynchronizedTypeResolveContext(children, cacheManager, false); return new CompositeSynchronizedTypeResolveContext(children, knownTypeDefinitions, cacheManager, false);
else else
return this; return this;
} }

32
ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs

@ -81,29 +81,17 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
if (context == null) if (context == null)
throw new ArgumentNullException("context"); throw new ArgumentNullException("context");
/* TODO PERF: caching disabled until we measure how much of an advantage it is // CacheManager cache = context.CacheManager;
* (and whether other approaches like caching only the last N resolve calls in a thread-static cache would work better) // if (cache != null) {
* Maybe even make a distinction between the really common type references (e.g. primitiveTypeReferences) and // IType cachedType = cache.GetShared(this) as IType;
* normal GetClassTypeReferences? // if (cachedType != null)
CacheManager cacheManager = context.CacheManager; // return cachedType;
if (cacheManager != null) { // }
CachedResult result = this.v_cachedResult;
if (result != null && result.CacheManager == cacheManager)
return result.Result;
IType newResult = DoResolve(context);
this.v_cachedResult = new CachedResult(cacheManager, newResult);
cacheManager.Disposed += delegate { v_cachedResult = null; }; // maybe optimize this to use interface call instead of delegate?
return newResult;
} else {
return DoResolve(context);
}
} IType type = context.GetTypeDefinition(nameSpace, name, typeParameterCount, StringComparer.Ordinal) ?? SharedTypes.UnknownType;
// if (cache != null)
IType DoResolve(ITypeResolveContext context) // cache.SetShared(this, type);
{ return type;
*/
return context.GetTypeDefinition(nameSpace, name, typeParameterCount, StringComparer.Ordinal) ?? SharedTypes.UnknownType;
} }
public override string ToString() public override string ToString()

6
ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs

@ -82,5 +82,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
// it might not be cache-safe. // it might not be cache-safe.
get { return null; } get { return null; }
} }
/// <inheritdoc/>
public virtual ITypeDefinition GetKnownTypeDefinition(TypeCode typeCode)
{
return target.GetKnownTypeDefinition(typeCode);
}
} }
} }

10
ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs

@ -177,6 +177,16 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
#endregion #endregion
#region IProjectContent implementation #region IProjectContent implementation
public ITypeDefinition GetKnownTypeDefinition(TypeCode typeCode)
{
readerWriterLock.EnterReadLock();
try {
return types.GetKnownTypeDefinition(typeCode);
} finally {
readerWriterLock.ExitReadLock();
}
}
public ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) public ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer)
{ {
readerWriterLock.EnterReadLock(); readerWriterLock.EnterReadLock();

6
ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs

@ -236,6 +236,12 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
return null; return null;
} }
/// <inheritdoc/>
public ITypeDefinition GetKnownTypeDefinition(TypeCode typeCode)
{
return GetTypeDefinition("System", ReflectionHelper.GetShortNameByTypeCode(typeCode), 0, StringComparer.Ordinal);
}
/// <inheritdoc/> /// <inheritdoc/>
public IEnumerable<ITypeDefinition> GetTypes() public IEnumerable<ITypeDefinition> GetTypes()
{ {

71
ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs

@ -25,87 +25,88 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <summary> /// <summary>
/// Contains well-known type references. /// Contains well-known type references.
/// </summary> /// </summary>
public static class KnownTypeReference [Serializable]
public sealed class KnownTypeReference : ITypeReference
{ {
/// <summary> /// <summary>
/// Gets a type reference pointing to the <c>void</c> type. /// Gets a type reference pointing to the <c>void</c> type.
/// </summary> /// </summary>
public static readonly ITypeReference Void = new GetClassTypeReference("System", "Void", 0); public static readonly KnownTypeReference Void = new KnownTypeReference(TypeCode.Empty);
/// <summary> /// <summary>
/// Gets a type reference pointing to the <c>object</c> type. /// Gets a type reference pointing to the <c>object</c> type.
/// </summary> /// </summary>
public static readonly ITypeReference Object = new GetClassTypeReference("System", "Object", 0); public static readonly KnownTypeReference Object = new KnownTypeReference(TypeCode.Object);
/// <summary> /// <summary>
/// Gets a type reference pointing to the <c>bool</c> type. /// Gets a type reference pointing to the <c>bool</c> type.
/// </summary> /// </summary>
public static readonly ITypeReference Boolean = new GetClassTypeReference("System", "Boolean", 0); public static readonly KnownTypeReference Boolean = new KnownTypeReference(TypeCode.Boolean);
/// <summary>
/// Gets a type reference pointing to the <c>char</c> type.
/// </summary>
public static readonly KnownTypeReference Char = new KnownTypeReference(TypeCode.Char);
/// <summary> /// <summary>
/// Gets a type reference pointing to the <c>sbyte</c> type. /// Gets a type reference pointing to the <c>sbyte</c> type.
/// </summary> /// </summary>
public static readonly ITypeReference SByte = new GetClassTypeReference("System", "SByte", 0); public static readonly KnownTypeReference SByte = new KnownTypeReference(TypeCode.SByte);
/// <summary> /// <summary>
/// Gets a type reference pointing to the <c>byte</c> type. /// Gets a type reference pointing to the <c>byte</c> type.
/// </summary> /// </summary>
public static readonly ITypeReference Byte = new GetClassTypeReference("System", "Byte", 0); public static readonly KnownTypeReference Byte = new KnownTypeReference(TypeCode.Byte);
/// <summary> /// <summary>
/// Gets a type reference pointing to the <c>short</c> type. /// Gets a type reference pointing to the <c>short</c> type.
/// </summary> /// </summary>
public static readonly ITypeReference Int16 = new GetClassTypeReference("System", "Int16", 0); public static readonly KnownTypeReference Int16 = new KnownTypeReference(TypeCode.Int16);
/// <summary> /// <summary>
/// Gets a type reference pointing to the <c>ushort</c> type. /// Gets a type reference pointing to the <c>ushort</c> type.
/// </summary> /// </summary>
public static readonly ITypeReference UInt16 = new GetClassTypeReference("System", "UInt16", 0); public static readonly KnownTypeReference UInt16 = new KnownTypeReference(TypeCode.UInt16);
/// <summary> /// <summary>
/// Gets a type reference pointing to the <c>int</c> type. /// Gets a type reference pointing to the <c>int</c> type.
/// </summary> /// </summary>
public static readonly ITypeReference Int32 = new GetClassTypeReference("System", "Int32", 0); public static readonly KnownTypeReference Int32 = new KnownTypeReference(TypeCode.Int32);
/// <summary> /// <summary>
/// Gets a type reference pointing to the <c>uint</c> type. /// Gets a type reference pointing to the <c>uint</c> type.
/// </summary> /// </summary>
public static readonly ITypeReference UInt32 = new GetClassTypeReference("System", "UInt32", 0); public static readonly KnownTypeReference UInt32 = new KnownTypeReference(TypeCode.UInt32);
/// <summary> /// <summary>
/// Gets a type reference pointing to the <c>long</c> type. /// Gets a type reference pointing to the <c>long</c> type.
/// </summary> /// </summary>
public static readonly ITypeReference Int64 = new GetClassTypeReference("System", "Int64", 0); public static readonly KnownTypeReference Int64 = new KnownTypeReference(TypeCode.Int64);
/// <summary> /// <summary>
/// Gets a type reference pointing to the <c>ulong</c> type. /// Gets a type reference pointing to the <c>ulong</c> type.
/// </summary> /// </summary>
public static readonly ITypeReference UInt64 = new GetClassTypeReference("System", "UInt64", 0); public static readonly KnownTypeReference UInt64 = new KnownTypeReference(TypeCode.UInt64);
/// <summary>
/// Gets a type reference pointing to the <c>string</c> type.
/// </summary>
public static readonly ITypeReference String = new GetClassTypeReference("System", "String", 0);
/// <summary>
/// Gets a type reference pointing to the <c>char</c> type.
/// </summary>
public static readonly ITypeReference Char = new GetClassTypeReference("System", "Char", 0);
/// <summary> /// <summary>
/// Gets a type reference pointing to the <c>float</c> type. /// Gets a type reference pointing to the <c>float</c> type.
/// </summary> /// </summary>
public static readonly ITypeReference Single = new GetClassTypeReference("System", "Single", 0); public static readonly KnownTypeReference Single = new KnownTypeReference(TypeCode.Single);
/// <summary> /// <summary>
/// Gets a type reference pointing to the <c>double</c> type. /// Gets a type reference pointing to the <c>double</c> type.
/// </summary> /// </summary>
public static readonly ITypeReference Double = new GetClassTypeReference("System", "Double", 0); public static readonly KnownTypeReference Double = new KnownTypeReference(TypeCode.Double);
/// <summary> /// <summary>
/// Gets a type reference pointing to the <c>decimal</c> type. /// Gets a type reference pointing to the <c>decimal</c> type.
/// </summary> /// </summary>
public static readonly ITypeReference Decimal = new GetClassTypeReference("System", "Decimal", 0); public static readonly KnownTypeReference Decimal = new KnownTypeReference(TypeCode.Decimal);
/// <summary>
/// Gets a type reference pointing to the <c>string</c> type.
/// </summary>
public static readonly KnownTypeReference String = new KnownTypeReference(TypeCode.String);
/// <summary> /// <summary>
/// Gets a type reference pointing to the <c>System.Type</c> type. /// Gets a type reference pointing to the <c>System.Type</c> type.
@ -125,5 +126,25 @@ namespace ICSharpCode.NRefactory.TypeSystem
}; };
} }
} }
readonly TypeCode typeCode;
public KnownTypeReference(TypeCode typeCode)
{
this.typeCode = typeCode;
}
public IType Resolve(ITypeResolveContext context)
{
return context.GetKnownTypeDefinition(typeCode) ?? SharedTypes.UnknownType;
}
public string Namespace {
get { return "System"; }
}
public string Name {
get { return ReflectionHelper.GetShortNameByTypeCode(typeCode); }
}
} }
} }

45
ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs

@ -220,37 +220,36 @@ namespace ICSharpCode.NRefactory.TypeSystem
#endregion #endregion
#region GetTypeCode #region GetTypeCode
static readonly Dictionary<string, TypeCode> typeNameToCodeDict = new Dictionary<string, TypeCode> { static readonly string[] typeNamesByTypeCode = {
{ "Object", TypeCode.Object }, "Void", "Object", "DBNull", "Boolean", "Char",
{ "DBNull", TypeCode.DBNull }, "SByte", "Byte", "Int16", "UInt16", "Int32", "UInt32", "Int64", "UInt64",
{ "Boolean", TypeCode.Boolean }, "Single", "Double", "Decimal", "DateTime", null, "String"
{ "Char", TypeCode.Char },
{ "SByte", TypeCode.SByte },
{ "Byte", TypeCode.Byte },
{ "Int16", TypeCode.Int16 },
{ "UInt16", TypeCode.UInt16 },
{ "Int32", TypeCode.Int32 },
{ "UInt32", TypeCode.UInt32 },
{ "Int64", TypeCode.Int64 },
{ "UInt64", TypeCode.UInt64 },
{ "Single", TypeCode.Single },
{ "Double", TypeCode.Double },
{ "Decimal", TypeCode.Decimal },
{ "DateTime", TypeCode.DateTime },
{ "String", TypeCode.String }
}; };
internal static int ByTypeCodeArraySize {
get { return typeNamesByTypeCode.Length; }
}
internal static string GetShortNameByTypeCode(TypeCode typeCode)
{
return typeNamesByTypeCode[(int)typeCode];
}
/// <summary> /// <summary>
/// Gets the type code for the specified type, or TypeCode.Empty if none of the other type codes matches. /// Gets the type code for the specified type, or TypeCode.Empty if none of the other type codes matches.
/// </summary> /// </summary>
public static TypeCode GetTypeCode(IType type) public static TypeCode GetTypeCode(IType type)
{ {
ITypeDefinition def = type as ITypeDefinition; ITypeDefinition def = type as ITypeDefinition;
TypeCode typeCode; if (def != null && def.TypeParameterCount == 0 && def.Namespace == "System") {
if (def != null && def.TypeParameterCount == 0 && def.Namespace == "System" && typeNameToCodeDict.TryGetValue(def.Name, out typeCode)) string[] typeNames = typeNamesByTypeCode;
return typeCode; string name = def.Name;
else for (int i = 1; i < typeNames.Length; i++) {
return TypeCode.Empty; if (name == typeNames[i])
return (TypeCode)i;
}
}
return TypeCode.Empty;
} }
#endregion #endregion

Loading…
Cancel
Save