Browse Source

properly implement typeof expressions in debugger evaluation

pull/297/head
Siegfried Pammer 12 years ago
parent
commit
89d4c7a3df
  1. 9
      src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluationVisitor.cs
  2. 95
      src/AddIns/Debugger/Debugger.Core/Eval.cs

9
src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluationVisitor.cs

@ -294,7 +294,10 @@ namespace Debugger.AddIn @@ -294,7 +294,10 @@ namespace Debugger.AddIn
Value Visit(TypeOfResolveResult result)
{
return Eval.NewObjectNoConstructor(evalThread, debuggerTypeSystem.Import(result.ReferencedType));
var type = debuggerTypeSystem.Import(result.ReferencedType);
if (type == null)
throw new GetValueException("Error: cannot find '{0}'.", result.ReferencedType.FullName);
return Eval.TypeOf(evalThread, type);
}
Value Visit(TypeResolveResult result)
@ -397,7 +400,7 @@ namespace Debugger.AddIn @@ -397,7 +400,7 @@ namespace Debugger.AddIn
return "null";
} else if (val.Type.Kind == TypeKind.Array) {
StringBuilder sb = new StringBuilder();
sb.Append(val.Type.Name);
sb.Append(new CSharpAmbience().ConvertType(val.Type));
sb.Append(" {");
bool first = true;
int size = val.ArrayLength;
@ -410,7 +413,7 @@ namespace Debugger.AddIn @@ -410,7 +413,7 @@ namespace Debugger.AddIn
return sb.ToString();
} else if (val.Type.GetAllBaseTypeDefinitions().Any(def => def.IsKnownType(KnownTypeCode.ICollection))) {
StringBuilder sb = new StringBuilder();
sb.Append(val.Type.Name);
sb.Append(new CSharpAmbience().ConvertType(val.Type));
sb.Append(" {");
val = val.GetPermanentReference(evalThread);
var countProp = val.Type.GetProperties(p => p.Name == "Count" && !p.IsExplicitInterfaceImplementation).Single();

95
src/AddIns/Debugger/Debugger.Core/Eval.cs

@ -5,6 +5,7 @@ using System; @@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using Debugger.MetaData;
using Debugger.Interop.CorDebug;
using ICSharpCode.NRefactory.TypeSystem;
@ -231,7 +232,7 @@ namespace Debugger @@ -231,7 +232,7 @@ namespace Debugger
arg.Type.GetDefinition() != null &&
paramType.GetDefinition() != null &&
!arg.Type.GetDefinition().IsDerivedFrom(paramType.GetDefinition())) {
throw new GetValueException("Inncorrect parameter type. Expected " + paramType.ToString());
throw new GetValueException("Incorrect parameter type. Expected " + paramType.ToString());
}
// It is importatnt to pass the parameter in the correct form (boxed/unboxed)
if (paramType.IsReferenceType == true) {
@ -355,5 +356,97 @@ namespace Debugger @@ -355,5 +356,97 @@ namespace Debugger
}
return valuesAsCorDebug;
}
public static Value TypeOf(Thread evalThread, IType type)
{
switch (type.Kind) {
case TypeKind.Unknown:
throw new GetValueException("Cannot find type '{0}'", type.FullName);
case TypeKind.Class:
case TypeKind.Interface:
case TypeKind.Struct:
case TypeKind.Delegate:
case TypeKind.Enum:
case TypeKind.Module:
case TypeKind.Void:
return ConvertTypeDefOrParameterizedType(evalThread, type);
case TypeKind.Array:
{
var arrayType = (ArrayType)type;
var elementType = TypeOf(evalThread, arrayType.ElementType);
return InvokeMakeArrayType(evalThread, elementType, arrayType.Dimensions);
}
case TypeKind.Pointer:
{
var pointerType = (TypeWithElementType)type;
var elementType = TypeOf(evalThread, pointerType.ElementType);
return InvokeMakePointerType(evalThread, elementType);
}
case TypeKind.ByReference:
{
var pointerType = (TypeWithElementType)type;
var elementType = TypeOf(evalThread, pointerType.ElementType);
return InvokeMakeByRefType(evalThread, elementType);
}
default:
throw new System.Exception("Invalid value for TypeKind: " + type.Kind);
}
}
static Value ConvertTypeDefOrParameterizedType(Thread evalThread, IType type)
{
var definition = type.GetDefinition();
if (definition == null)
throw new GetValueException("Cannot find type '{0}'", type.FullName);
var foundType = InvokeGetType(evalThread, new AssemblyQualifiedTypeName(definition));
ParameterizedType pt = type as ParameterizedType;
if (pt != null) {
var typeParams = new List<Value>();
foreach (var typeArg in pt.TypeArguments) {
typeParams.Add(TypeOf(evalThread, typeArg));
}
return InvokeMakeGenericType(evalThread, foundType, typeParams.ToArray());
}
return foundType;
}
static Value InvokeGetType(Thread evalThread, AssemblyQualifiedTypeName name)
{
var sysType = evalThread.AppDomain.Compilation.FindType(KnownTypeCode.Type);
var getType = sysType.GetMethods(m => m.Name == "GetType" && m.Parameters.Count == 2).FirstOrDefault();
return InvokeMethod(evalThread, getType, null, new[] { NewString(evalThread, name.ToString()), CreateValue(evalThread, false) });
}
static Value InvokeMakeArrayType(Thread evalThread, Value type, int rank = 1)
{
var sysType = evalThread.AppDomain.Compilation.FindType(KnownTypeCode.Type);
var makeArrayType = sysType.GetMethods(m => m.Name == "MakeArrayType" && m.Parameters.Count == 1).FirstOrDefault();
return InvokeMethod(evalThread, makeArrayType, type, new[] { CreateValue(evalThread, rank) });
}
static Value InvokeMakePointerType(Thread evalThread, Value type)
{
var sysType = evalThread.AppDomain.Compilation.FindType(KnownTypeCode.Type);
var makePointerType = sysType.GetMethods(m => m.Name == "MakePointerType" && m.Parameters.Count == 0).FirstOrDefault();
return InvokeMethod(evalThread, makePointerType, type, new Value[0]);
}
static Value InvokeMakeByRefType(Thread evalThread, Value type)
{
var sysType = evalThread.AppDomain.Compilation.FindType(KnownTypeCode.Type);
var makeByRefType = sysType.GetMethods(m => m.Name == "MakeByRefType" && m.Parameters.Count == 0).FirstOrDefault();
return InvokeMethod(evalThread, makeByRefType, type, new Value[0]);
}
static Value InvokeMakeGenericType(Thread evalThread, Value type, Value[] typeParams)
{
var sysType = evalThread.AppDomain.Compilation.FindType(KnownTypeCode.Type);
var makeByRefType = sysType.GetMethods(m => m.Name == "MakeGenericType" && m.Parameters.Count == 1).FirstOrDefault();
var tp = Eval.NewArray(evalThread, sysType, (uint)typeParams.Length, 0);
for (int i = 0; i < typeParams.Length; i++) {
tp.SetArrayElement(evalThread, new[] { (uint)i }, typeParams[i]);
}
return InvokeMethod(evalThread, makeByRefType, type, new[] { tp });
}
}
}

Loading…
Cancel
Save