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

9
ICSharpCode.NRefactory/Documentation/IDStringProvider.cs

@ -240,6 +240,15 @@ namespace ICSharpCode.NRefactory.Documentation @@ -240,6 +240,15 @@ namespace ICSharpCode.NRefactory.Documentation
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;
if (gctr != null) {
if (!string.IsNullOrEmpty(gctr.Namespace)) {

10
ICSharpCode.NRefactory/TypeSystem/ITypeResolveContext.cs

@ -32,6 +32,16 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -32,6 +32,16 @@ namespace ICSharpCode.NRefactory.TypeSystem
#endif
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>
/// Retrieves a type.
/// </summary>

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

@ -66,6 +66,17 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -66,6 +66,17 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
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/>
public ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer)
{
@ -117,7 +128,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -117,7 +128,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
if (sync[i] == 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;
return r;
} finally {
@ -141,12 +153,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -141,12 +153,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
readonly CacheManager cacheManager;
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)
{
Debug.Assert(cacheManager != null);
this.cacheManager = cacheManager;
this.knownTypeDefinitions = knownTypeDefinitions;
this.isTopLevel = isTopLevel;
}
@ -167,11 +181,21 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -167,11 +181,21 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
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()
{
// re-use the same cache manager for nested synchronized contexts
if (isTopLevel)
return new CompositeSynchronizedTypeResolveContext(children, cacheManager, false);
return new CompositeSynchronizedTypeResolveContext(children, knownTypeDefinitions, cacheManager, false);
else
return this;
}

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

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

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

@ -82,5 +82,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -82,5 +82,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
// it might not be cache-safe.
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 @@ -177,6 +177,16 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
#endregion
#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)
{
readerWriterLock.EnterReadLock();

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

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

71
ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs

@ -25,87 +25,88 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -25,87 +25,88 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <summary>
/// Contains well-known type references.
/// </summary>
public static class KnownTypeReference
[Serializable]
public sealed class KnownTypeReference : ITypeReference
{
/// <summary>
/// Gets a type reference pointing to the <c>void</c> type.
/// </summary>
public static readonly ITypeReference Void = new GetClassTypeReference("System", "Void", 0);
public static readonly KnownTypeReference Void = new KnownTypeReference(TypeCode.Empty);
/// <summary>
/// Gets a type reference pointing to the <c>object</c> type.
/// </summary>
public static readonly ITypeReference Object = new GetClassTypeReference("System", "Object", 0);
public static readonly KnownTypeReference Object = new KnownTypeReference(TypeCode.Object);
/// <summary>
/// Gets a type reference pointing to the <c>bool</c> type.
/// </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>
/// Gets a type reference pointing to the <c>sbyte</c> type.
/// </summary>
public static readonly ITypeReference SByte = new GetClassTypeReference("System", "SByte", 0);
public static readonly KnownTypeReference SByte = new KnownTypeReference(TypeCode.SByte);
/// <summary>
/// Gets a type reference pointing to the <c>byte</c> type.
/// </summary>
public static readonly ITypeReference Byte = new GetClassTypeReference("System", "Byte", 0);
public static readonly KnownTypeReference Byte = new KnownTypeReference(TypeCode.Byte);
/// <summary>
/// Gets a type reference pointing to the <c>short</c> type.
/// </summary>
public static readonly ITypeReference Int16 = new GetClassTypeReference("System", "Int16", 0);
public static readonly KnownTypeReference Int16 = new KnownTypeReference(TypeCode.Int16);
/// <summary>
/// Gets a type reference pointing to the <c>ushort</c> type.
/// </summary>
public static readonly ITypeReference UInt16 = new GetClassTypeReference("System", "UInt16", 0);
public static readonly KnownTypeReference UInt16 = new KnownTypeReference(TypeCode.UInt16);
/// <summary>
/// Gets a type reference pointing to the <c>int</c> type.
/// </summary>
public static readonly ITypeReference Int32 = new GetClassTypeReference("System", "Int32", 0);
public static readonly KnownTypeReference Int32 = new KnownTypeReference(TypeCode.Int32);
/// <summary>
/// Gets a type reference pointing to the <c>uint</c> type.
/// </summary>
public static readonly ITypeReference UInt32 = new GetClassTypeReference("System", "UInt32", 0);
public static readonly KnownTypeReference UInt32 = new KnownTypeReference(TypeCode.UInt32);
/// <summary>
/// Gets a type reference pointing to the <c>long</c> type.
/// </summary>
public static readonly ITypeReference Int64 = new GetClassTypeReference("System", "Int64", 0);
public static readonly KnownTypeReference Int64 = new KnownTypeReference(TypeCode.Int64);
/// <summary>
/// Gets a type reference pointing to the <c>ulong</c> type.
/// </summary>
public static readonly ITypeReference UInt64 = new GetClassTypeReference("System", "UInt64", 0);
/// <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);
public static readonly KnownTypeReference UInt64 = new KnownTypeReference(TypeCode.UInt64);
/// <summary>
/// Gets a type reference pointing to the <c>float</c> type.
/// </summary>
public static readonly ITypeReference Single = new GetClassTypeReference("System", "Single", 0);
public static readonly KnownTypeReference Single = new KnownTypeReference(TypeCode.Single);
/// <summary>
/// Gets a type reference pointing to the <c>double</c> type.
/// </summary>
public static readonly ITypeReference Double = new GetClassTypeReference("System", "Double", 0);
public static readonly KnownTypeReference Double = new KnownTypeReference(TypeCode.Double);
/// <summary>
/// Gets a type reference pointing to the <c>decimal</c> type.
/// </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>
/// Gets a type reference pointing to the <c>System.Type</c> type.
@ -125,5 +126,25 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -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 @@ -220,37 +220,36 @@ namespace ICSharpCode.NRefactory.TypeSystem
#endregion
#region GetTypeCode
static readonly Dictionary<string, TypeCode> typeNameToCodeDict = new Dictionary<string, TypeCode> {
{ "Object", TypeCode.Object },
{ "DBNull", TypeCode.DBNull },
{ "Boolean", TypeCode.Boolean },
{ "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 }
static readonly string[] typeNamesByTypeCode = {
"Void", "Object", "DBNull", "Boolean", "Char",
"SByte", "Byte", "Int16", "UInt16", "Int32", "UInt32", "Int64", "UInt64",
"Single", "Double", "Decimal", "DateTime", null, "String"
};
internal static int ByTypeCodeArraySize {
get { return typeNamesByTypeCode.Length; }
}
internal static string GetShortNameByTypeCode(TypeCode typeCode)
{
return typeNamesByTypeCode[(int)typeCode];
}
/// <summary>
/// Gets the type code for the specified type, or TypeCode.Empty if none of the other type codes matches.
/// </summary>
public static TypeCode GetTypeCode(IType type)
{
ITypeDefinition def = type as ITypeDefinition;
TypeCode typeCode;
if (def != null && def.TypeParameterCount == 0 && def.Namespace == "System" && typeNameToCodeDict.TryGetValue(def.Name, out typeCode))
return typeCode;
else
return TypeCode.Empty;
if (def != null && def.TypeParameterCount == 0 && def.Namespace == "System") {
string[] typeNames = typeNamesByTypeCode;
string name = def.Name;
for (int i = 1; i < typeNames.Length; i++) {
if (name == typeNames[i])
return (TypeCode)i;
}
}
return TypeCode.Empty;
}
#endregion

Loading…
Cancel
Save