diff options
author | Lluis Sanchez <lluis@novell.com> | 2010-01-15 05:21:55 +0300 |
---|---|---|
committer | Lluis Sanchez <lluis@novell.com> | 2010-01-15 05:21:55 +0300 |
commit | fd2b1ff216f1bfe5353cf8cbda3f730fed07611f (patch) | |
tree | 61a964ce5a92bae20e0b219f7b5815895ced68aa | |
parent | f32d1c612187d727cc32ef8b40f343c2cddd4d3a (diff) |
2009-12-15 Lluis Sanchez Gual <lluis@novell.com>
* MdbObjectValueAdaptor.cs: Improved ToString method for
primitive and class types. Improved Cast method. Allow
casting between primitive types and enums. Removed a bunch
of formatting code, now reused from the base
ObjectValueAdapter. In GetRealObject, don't dereference enum
types: we want to get the enum value and dereference only
when necessary. Other misc fixes.
* FieldReference.cs: Allow getting fields from enums and other
non-struct types.
* IndexerValueReference.cs: Added special case for string
indexer.
2009-12-11 Lluis Sanchez Gual <lluis@novell.com>
* DebuggerServer.cs:
* MdbObjectValueAdaptor.cs: Track api changes.
svn path=/branches/monodevelop/extras/MonoDevelop.Debugger.Mdb/2.2/; revision=149594
5 files changed, 135 insertions, 120 deletions
diff --git a/extras/MonoDevelop.Debugger.Mdb/Mono.Debugging.Server.Mdb/ChangeLog b/extras/MonoDevelop.Debugger.Mdb/Mono.Debugging.Server.Mdb/ChangeLog index f1fa0e340d..c348babeb7 100644 --- a/extras/MonoDevelop.Debugger.Mdb/Mono.Debugging.Server.Mdb/ChangeLog +++ b/extras/MonoDevelop.Debugger.Mdb/Mono.Debugging.Server.Mdb/ChangeLog @@ -1,8 +1,29 @@ +2009-12-15 Lluis Sanchez Gual <lluis@novell.com> + + * MdbObjectValueAdaptor.cs: Improved ToString method for + primitive and class types. Improved Cast method. Allow + casting between primitive types and enums. Removed a bunch + of formatting code, now reused from the base + ObjectValueAdapter. In GetRealObject, don't dereference enum + types: we want to get the enum value and dereference only + when necessary. Other misc fixes. + + * FieldReference.cs: Allow getting fields from enums and other + non-struct types. + + * IndexerValueReference.cs: Added special case for string + indexer. + 2009-12-14 Lluis Sanchez Gual <lluis@novell.com> * DebuggerServer.cs: Don't try to change breakpoints if the target already exited. +2009-12-11 Lluis Sanchez Gual <lluis@novell.com> + + * DebuggerServer.cs: + * MdbObjectValueAdaptor.cs: Track api changes. + 2009-12-03 Lluis Sanchez Gual <lluis@novell.com> * MdbObjectValueAdaptor.cs: Track api changes. diff --git a/extras/MonoDevelop.Debugger.Mdb/Mono.Debugging.Server.Mdb/DebuggerServer.cs b/extras/MonoDevelop.Debugger.Mdb/Mono.Debugging.Server.Mdb/DebuggerServer.cs index 880900e3cf..8fdb50a5f2 100644 --- a/extras/MonoDevelop.Debugger.Mdb/Mono.Debugging.Server.Mdb/DebuggerServer.cs +++ b/extras/MonoDevelop.Debugger.Mdb/Mono.Debugging.Server.Mdb/DebuggerServer.cs @@ -320,7 +320,7 @@ namespace DebuggerServer MdbEvaluationContext ctx = new MdbEvaluationContext (activeThread, activeThread.CurrentFrame, SessionOptions.EvaluationOptions); ML.TargetObject ob = EvaluateExp (ctx, bp.ConditionExpression); if (ob != null) - lastConditionValue [ev.Index] = evaluator.TargetObjectToExpression (ctx, ob); + lastConditionValue [ev.Index] = evaluator.TargetObjectToExpression (ctx, ob).Value; } events [ev.Index] = be; @@ -380,7 +380,7 @@ namespace DebuggerServer if (val == null) return false; if (bp.BreakIfConditionChanges) { - string current = evaluator.TargetObjectToExpression (ctx, val); + string current = evaluator.TargetObjectToExpression (ctx, val).Value; string last; bool found = lastConditionValue.TryGetValue (eventHandle, out last); lastConditionValue [eventHandle] = current; diff --git a/extras/MonoDevelop.Debugger.Mdb/Mono.Debugging.Server.Mdb/FieldReference.cs b/extras/MonoDevelop.Debugger.Mdb/Mono.Debugging.Server.Mdb/FieldReference.cs index e705fdbe93..6a66625aea 100644 --- a/extras/MonoDevelop.Debugger.Mdb/Mono.Debugging.Server.Mdb/FieldReference.cs +++ b/extras/MonoDevelop.Debugger.Mdb/Mono.Debugging.Server.Mdb/FieldReference.cs @@ -35,11 +35,11 @@ namespace DebuggerServer { public class FieldReference: ValueReference { - TargetStructType type; + TargetType type; TargetFieldInfo field; TargetStructObject thisobj; - public FieldReference (EvaluationContext ctx, TargetStructObject thisobj, TargetStructType type, TargetFieldInfo field): base (ctx) + public FieldReference (EvaluationContext ctx, TargetStructObject thisobj, TargetType type, TargetFieldInfo field): base (ctx) { this.type = type; this.field = field; @@ -62,14 +62,35 @@ namespace DebuggerServer public override object Value { get { MdbEvaluationContext ctx = (MdbEvaluationContext) Context; - if (field.HasConstValue) - return ctx.Frame.Language.CreateInstance (ctx.Thread, field.ConstValue); - TargetClass cls = type.GetClass (ctx.Thread); - return ObjectUtil.GetRealObject (ctx, cls.GetField (ctx.Thread, thisobj, field)); + if (field.HasConstValue) { + object obj = ctx.Frame.Language.CreateInstance (ctx.Thread, field.ConstValue); + if (type is TargetEnumType) + // Enum constants are integers, so they have to be converted to enum objects + return ctx.Adapter.Cast (ctx, obj, type); + else + return obj; + } + TargetClass cls; + TargetStructType tt = type as TargetStructType; + if (tt != null) + cls = tt.GetClass (ctx.Thread); + else if (type.HasClassType) + cls = type.ClassType.GetClass (ctx.Thread); + else + throw new NotSupportedException ("Can't get field '" + Name + "' from type '" + type.Name + "'"); + + return cls.GetField (ctx.Thread, thisobj, field); } set { MdbEvaluationContext ctx = (MdbEvaluationContext) Context; - TargetClass cls = type.GetClass (ctx.Thread); + TargetClass cls; + TargetStructType tt = type as TargetStructType; + if (tt != null) + cls = tt.GetClass (ctx.Thread); + else if (type.HasClassType) + cls = type.ClassType.GetClass (ctx.Thread); + else + throw new NotSupportedException ("Can't set field '" + Name + "' from type '" + type.Name + "'"); cls.SetField (ctx.Thread, thisobj, field, (TargetObject) value); } } diff --git a/extras/MonoDevelop.Debugger.Mdb/Mono.Debugging.Server.Mdb/IndexerValueReference.cs b/extras/MonoDevelop.Debugger.Mdb/Mono.Debugging.Server.Mdb/IndexerValueReference.cs index 2b07503443..6ab7ab2376 100644 --- a/extras/MonoDevelop.Debugger.Mdb/Mono.Debugging.Server.Mdb/IndexerValueReference.cs +++ b/extras/MonoDevelop.Debugger.Mdb/Mono.Debugging.Server.Mdb/IndexerValueReference.cs @@ -48,8 +48,18 @@ namespace DebuggerServer this.index = index; } - public static IndexerValueReference CreateIndexerValueReference (MdbEvaluationContext ctx, TargetObject target, TargetObject index) + public static ValueReference CreateIndexerValueReference (MdbEvaluationContext ctx, TargetObject target, TargetObject index) { + TargetFundamentalObject mstr = target as TargetFundamentalObject; + if (mstr != null && mstr.TypeName == "string") { + // Special case for strings + string name = "[" + ctx.Evaluator.TargetObjectToExpression (ctx, index) + "]"; + string val = (string) mstr.GetObject (ctx.Thread); + object oo = ctx.Adapter.TargetObjectToObject (ctx, index); + int idx = (int) Convert.ChangeType (oo, typeof(int)); + return LiteralValueReference.CreateObjectLiteral (ctx, name, val [idx]); + } + TargetStructObject sob = target as TargetStructObject; if (sob == null) return null; diff --git a/extras/MonoDevelop.Debugger.Mdb/Mono.Debugging.Server.Mdb/MdbObjectValueAdaptor.cs b/extras/MonoDevelop.Debugger.Mdb/Mono.Debugging.Server.Mdb/MdbObjectValueAdaptor.cs index fa2a00a11c..c0185c5c63 100644 --- a/extras/MonoDevelop.Debugger.Mdb/Mono.Debugging.Server.Mdb/MdbObjectValueAdaptor.cs +++ b/extras/MonoDevelop.Debugger.Mdb/Mono.Debugging.Server.Mdb/MdbObjectValueAdaptor.cs @@ -46,27 +46,60 @@ namespace DebuggerServer if (!gctx.Options.AllowTargetInvoke) return GetValueTypeName (gctx, obj); MdbEvaluationContext ctx = (MdbEvaluationContext) gctx; + obj = ctx.GetRealObject (obj); + if (obj is TargetFundamentalObject) { + object fob = ((TargetFundamentalObject)obj).GetObject (ctx.Thread); + return fob != null ? fob.ToString () : null; + } + + TargetStructObject starget = obj as TargetStructObject; + if (starget != null) { + // Optimization: if ToString is not overriden, there is no need to call it since the result is the name of the type + MemberReference mem = OverloadResolve (ctx, "ToString", starget.Type, new TargetType [0], true, false, false); + if (mem == null || mem.DeclaringType.Name == "System.Object") + return GetDisplayTypeName (ctx, starget.Type); + } + TargetObject retval = CallMethod (ctx, "ToString", (TargetStructObject) obj); object s = ((TargetFundamentalObject) retval).GetObject (ctx.Thread); return s != null ? s.ToString () : ""; } - public override object Cast (EvaluationContext gctx, object obj, object targetType) - { - MdbEvaluationContext ctx = (MdbEvaluationContext) gctx; - return TargetObjectConvert.Cast (ctx, (TargetObject) obj, (TargetType) targetType); - } - - public override object TryCast (EvaluationContext gctx, object val, object type) + public override object TryCast (EvaluationContext gctx, object val, object targetType) { MdbEvaluationContext ctx = (MdbEvaluationContext)gctx; TargetObject tval = ctx.GetRealObject (val); - if (type is TargetObjectType) + if (targetType is TargetObjectType) return val; - if (type is TargetClassType) - return TargetObjectConvert.TryCast (ctx, tval, (TargetClassType)type); - else - return null; + else if (targetType is TargetClassType) + return TargetObjectConvert.TryCast (ctx, tval, (TargetClassType)targetType); + else if (targetType is TargetEnumType) { + TargetType tt = ctx.Frame.Language.LookupType ("System.Enum"); + TargetObject typeObj = (TargetObject) GetTypeOf (ctx, ((TargetEnumType)targetType).Name); + return CallStaticMethod (ctx, "ToObject", tt, typeObj, tval); + } + else if (targetType is TargetFundamentalType) { + if (tval is TargetEnumObject) { + TargetEnumObject eob = (TargetEnumObject) tval; + return TryCast (ctx, eob.GetValue (ctx.Thread), targetType); + } + TargetFundamentalType ftype = (TargetFundamentalType) targetType; + Type tt = Type.GetType (ObjectUtil.FixTypeName (ftype.Name)); + if (tval is TargetFundamentalObject) { + TargetFundamentalObject fob = (TargetFundamentalObject) tval; + object obj = fob.GetObject (ctx.Thread); + if (tt.IsInstanceOfType (obj)) + return val; + if (tt != typeof(string) && !(obj is string)) { + try { + object res = System.Convert.ChangeType (obj, tt); + return CreateValue (ctx, res); + } catch { + } + } + } + } + return null; } @@ -76,48 +109,12 @@ namespace DebuggerServer TargetObject obj = ctx.GetRealObject (vobj); switch (obj.Kind) { - case Mono.Debugger.Languages.TargetObjectKind.Array: - TargetArrayObject arr = obj as TargetArrayObject; - if (arr == null) - return null; - StringBuilder tn = new StringBuilder (arr.Type.ElementType.Name); - tn.Append ("["); - TargetArrayBounds ab = arr.GetArrayBounds (ctx.Thread); - if (ab.IsMultiDimensional) { - for (int n=0; n<ab.Rank; n++) { - if (n>0) - tn.Append (','); - tn.Append (ab.UpperBounds [n] - ab.LowerBounds [n] + 1); - } - } - else if (!ab.IsUnbound) { - tn.Append (ab.Length.ToString ()); - } - tn.Append ("]"); - return new LiteralExp (tn.ToString ()); - + case TargetObjectKind.Array: case TargetObjectKind.GenericInstance: case TargetObjectKind.Struct: case TargetObjectKind.Class: - TypeDisplayData tdata = GetTypeDisplayData (ctx, obj.Type); - TargetStructObject co = obj as TargetStructObject; - if (co == null) - return null; - if (ctx.Options.AllowTargetInvoke) { - if (co.TypeName == "System.Decimal") - return new LiteralExp (CallToString (ctx, co)); - if (tdata.ValueDisplayString != null && ctx.Options.AllowDisplayStringEvaluation) - return new LiteralExp (EvaluateDisplayString (ctx, co, tdata.ValueDisplayString)); - } - - // Return the type name - if (tdata.TypeDisplayString != null) - return new LiteralExp ("{" + tdata.TypeDisplayString + "}"); - return new LiteralExp ("{" + obj.Type.Name + "}"); - case TargetObjectKind.Enum: - TargetEnumObject eob = (TargetEnumObject) obj; - return new LiteralExp (Server.Instance.Evaluator.TargetObjectToString (ctx, eob.GetValue (ctx.Thread))); + return base.TargetObjectToObject (ctx, vobj); case TargetObjectKind.Fundamental: TargetFundamentalObject fob = obj as TargetFundamentalObject; @@ -136,7 +133,7 @@ namespace DebuggerServer if (oob == null) return null; else - return new LiteralExp ("{" + oob.TypeName + "}"); + return new EvaluationResult ("{" + oob.TypeName + "}"); case TargetObjectKind.Nullable: TargetNullableObject nob = (TargetNullableObject) obj; @@ -145,7 +142,7 @@ namespace DebuggerServer else return null; } - return new LiteralExp ("?"); + return new EvaluationResult ("?"); } @@ -525,7 +522,7 @@ namespace DebuggerServer TargetObject obj = ctx.GetRealObject (vobj); if (obj == null) - return ObjectValue.CreateObject (null, path, "", null, flags | ObjectValueFlags.ReadOnly, null); + return ObjectValue.CreateObject (null, path, "", "", flags | ObjectValueFlags.ReadOnly, null); if (obj.HasAddress && obj.GetAddress (ctx.Thread).IsNull) return ObjectValue.CreateObject (null, path, obj.TypeName, ctx.Evaluator.ToExpression (null), flags, null); @@ -535,29 +532,10 @@ namespace DebuggerServer case TargetObjectKind.Struct: case TargetObjectKind.GenericInstance: case TargetObjectKind.Class: - TypeDisplayData tdata = GetTypeDisplayData (ctx, obj.Type); - - TargetStructObject co = obj as TargetStructObject; - if (co == null) - return ObjectValue.CreateUnknown (path.LastName); - else { - string tvalue; - if (!string.IsNullOrEmpty (tdata.ValueDisplayString) && ctx.Options.AllowDisplayStringEvaluation) - tvalue = EvaluateDisplayString (ctx, co, tdata.ValueDisplayString); - else - tvalue = ctx.Evaluator.TargetObjectToExpression (ctx, obj); - - string tname; - if (!string.IsNullOrEmpty (tdata.TypeDisplayString) && ctx.Options.AllowDisplayStringEvaluation) - tname = EvaluateDisplayString (ctx, co, tdata.TypeDisplayString); - else - tname = obj.TypeName; - - ObjectValue val = ObjectValue.CreateObject (source, path, tname, tvalue, flags, null); - if (!string.IsNullOrEmpty (tdata.NameDisplayString) && ctx.Options.AllowDisplayStringEvaluation) - val.Name = EvaluateDisplayString (ctx, co, tdata.NameDisplayString); - return val; - } + case TargetObjectKind.Array: + case TargetObjectKind.Fundamental: + case TargetObjectKind.Enum: + return base.CreateObjectValueImpl (gctx, source, path, vobj, flags); case TargetObjectKind.Object: TargetObjectObject oob = obj as TargetObjectObject; @@ -566,18 +544,6 @@ namespace DebuggerServer else return ObjectValue.CreateObject (source, path, obj.TypeName, Server.Instance.Evaluator.TargetObjectToExpression (ctx, obj), flags, null); - case TargetObjectKind.Array: - return ObjectValue.CreateObject (source, path, obj.TypeName, Server.Instance.Evaluator.TargetObjectToExpression (ctx, obj), flags, null); - - case TargetObjectKind.Fundamental: - TargetFundamentalObject fob = (TargetFundamentalObject) obj; - return ObjectValue.CreatePrimitive (source, path, obj.TypeName, Server.Instance.Evaluator.TargetObjectToExpression (ctx, fob), flags); - - case TargetObjectKind.Enum: - Console.WriteLine ("pp ??? ENUM: " + obj.GetType ()); - TargetEnumObject enumobj = (TargetEnumObject) obj; - return CreateObjectValue (ctx, source, path, enumobj.GetValue (ctx.Thread), flags); - case TargetObjectKind.Pointer: return ObjectValue.CreateObject (source, path, obj.TypeName, Server.Instance.Evaluator.TargetObjectToExpression (ctx, obj), flags, null); @@ -643,10 +609,10 @@ namespace DebuggerServer MemberReference mem = OverloadResolve (ctx, name, starget.Type, types, true, false, true); TargetFunctionType function = (TargetFunctionType) ((TargetMethodInfo) mem.Member).Type; - while (target.Type != mem.DeclaringType) { + while (starget.Type != mem.DeclaringType) { TargetStructObject par = starget.GetParentObject (ctx.Thread); if (par != null) - target = par; + starget = par; else break; } @@ -688,7 +654,7 @@ namespace DebuggerServer for (int n=0; n<types.Length; n++) types [n] = args [n].Type; - MemberReference mem = OverloadResolve (ctx, name, (TargetStructType) type, types, false, true, true); + MemberReference mem = OverloadResolve (ctx, name, type, types, false, true, true); TargetFunctionType function = (TargetFunctionType) ((TargetMethodInfo) mem.Member).Type; TargetMethodSignature sig = function.GetSignature (ctx.Thread); @@ -701,7 +667,7 @@ namespace DebuggerServer return Server.Instance.RuntimeInvoke (ctx, function, null, objs); } - public static MemberReference OverloadResolve (MdbEvaluationContext ctx, string methodName, TargetStructType type, TargetType[] argtypes, bool allowInstance, bool allowStatic, bool throwIfNotFound) + public static MemberReference OverloadResolve (MdbEvaluationContext ctx, string methodName, TargetType type, TargetType[] argtypes, bool allowInstance, bool allowStatic, bool throwIfNotFound) { List<MemberReference> candidates = new List<MemberReference> (); @@ -847,10 +813,6 @@ namespace DebuggerServer TargetObject res = co.GetCurrentObject (ctx.Thread); return res ?? obj; - case TargetObjectKind.Enum: - TargetEnumObject eob = (TargetEnumObject) obj; - return eob.GetValue (ctx.Thread); - case TargetObjectKind.Object: TargetObjectObject oob = obj as TargetObjectObject; if (oob == null) @@ -873,16 +835,15 @@ namespace DebuggerServer // must be retrieved before we can do anything with them. List<MemberReference> members = new List<MemberReference> (); - TargetStructType type = t as TargetStructType; Dictionary<string,string> foundMethods = new Dictionary<string,string> (); - while (type != null) { + while (t != null) { TargetFieldInfo[] fields = null; TargetPropertyInfo[] properties = null; TargetMethodInfo[] methods = null; - TargetClass cls = type.GetClass (ctx.Thread); + TargetClass cls = t.HasClassType ? t.ClassType.GetClass (ctx.Thread) : null; if (cls != null) { if (includeFields) fields = cls.GetFields (ctx.Thread); @@ -892,9 +853,9 @@ namespace DebuggerServer methods = cls.GetMethods (ctx.Thread); } else { - TargetClassType ct = type as TargetClassType; - if (ct == null && type.HasClassType) - ct = type.ClassType; + TargetClassType ct = t as TargetClassType; + if (ct == null && t.HasClassType) + ct = t.ClassType; if (ct != null) { if (includeFields) fields = ct.Fields; @@ -917,7 +878,7 @@ namespace DebuggerServer continue; if (!field.IsStatic && (flags & BindingFlags.Instance) == 0) continue; - members.Add (new MemberReference (field, type)); + members.Add (new MemberReference (field, t)); } } @@ -931,7 +892,7 @@ namespace DebuggerServer continue; if (!prop.IsStatic && (flags & BindingFlags.Instance) == 0) continue; - members.Add (new MemberReference (prop, type)); + members.Add (new MemberReference (prop, t)); } } @@ -948,13 +909,14 @@ namespace DebuggerServer string sig = met.FullName; if (!foundMethods.ContainsKey (sig)) { foundMethods [sig] = sig; - members.Add (new MemberReference (met, type)); + members.Add (new MemberReference (met, t)); } } } - if (type.HasParent && (flags & BindingFlags.DeclaredOnly) == 0) - type = type.GetParentType (ctx.Thread); + TargetStructType type = t as TargetStructType; + if (type != null && type.HasParent && (flags & BindingFlags.DeclaredOnly) == 0) + t = type.GetParentType (ctx.Thread); else break; } @@ -1012,6 +974,7 @@ namespace DebuggerServer sb.Remove (sb.Length - 1, 1); sb.Append (']'); + sb.Append (typeName.Substring (e+1)); return sb.ToString (); } @@ -1042,9 +1005,9 @@ namespace DebuggerServer public class MemberReference { public readonly TargetMemberInfo Member; - public readonly TargetStructType DeclaringType; + public readonly TargetType DeclaringType; - public MemberReference (TargetMemberInfo member, TargetStructType type) + public MemberReference (TargetMemberInfo member, TargetType type) { Member = member; DeclaringType = type; @@ -1060,7 +1023,7 @@ namespace DebuggerServer TargetFieldInfo field = (TargetFieldInfo) Member; if (field.HasConstValue) return ctx.Frame.Language.CreateInstance (ctx.Thread, field.ConstValue); - TargetClass cls = DeclaringType.GetClass (ctx.Thread); + TargetClass cls = DeclaringType.ClassType.GetClass (ctx.Thread); return ObjectUtil.GetRealObject (ctx, cls.GetField (ctx.Thread, thisObj, field)); } else { |