From ee345d082541d11046c82feb82e63a79723660ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Srbeck=C3=BD?= Date: Fri, 18 Jul 2008 13:04:26 +0000 Subject: [PATCH] Support creation of all primitive types git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@3238 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61 --- .../Src/Expressions/EvaluateAstVisitor.cs | 4 +- .../Project/Src/TreeModel/ValueNode.cs | 2 +- .../Debugger.Core/Project/Src/Control/Eval.cs | 26 ++---- .../Expressions/Ast/PrimitiveExpression.cs | 2 +- .../Project/Src/Metadata/DebugType-Helpers.cs | 81 +++++++++++----- .../Project/Src/Metadata/DebugType.cs | 2 +- .../Project/Src/Values/Value.Primitive.cs | 17 ++-- .../CorDebug/ICorDebugGenericValue.cs | 93 +++++++++---------- .../Project/Src/TestPrograms/DebugTypes.cs | 6 +- 9 files changed, 125 insertions(+), 108 deletions(-) diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Expressions/EvaluateAstVisitor.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Expressions/EvaluateAstVisitor.cs index 86d71068f4..45034fc739 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Expressions/EvaluateAstVisitor.cs +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Expressions/EvaluateAstVisitor.cs @@ -108,7 +108,9 @@ namespace Debugger.AddIn public override object VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data) { - return Eval.CreateValue(context.Process, primitiveExpression.Value); + Value val = Eval.NewObjectNoConstructor(DebugType.Create(context.Process, null, value.GetType().FullName)) + val.PrimitiveValue = primitiveExpression.Value; + return val; } public override object VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, object data) diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ValueNode.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ValueNode.cs index 195d000e49..acecfbd5b7 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ValueNode.cs +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ValueNode.cs @@ -138,7 +138,7 @@ namespace Debugger.AddIn.TreeModel return true; } catch (NotSupportedException) { string format = ResourceService.GetString("MainWindow.Windows.Debug.LocalVariables.CannotSetValue.BadFormat"); - string msg = String.Format(format, newText, val.Type.ManagedType.ToString()); + string msg = String.Format(format, newText, val.Type.PrimitiveType.ToString()); MessageService.ShowMessage(msg ,"${res:MainWindow.Windows.Debug.LocalVariables.CannotSetValue.Title}"); } catch (System.Runtime.InteropServices.COMException) { // COMException (0x80131330): Cannot perfrom SetValue on non-leaf frames. diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs index 13acaa8ebf..3e46efc4dd 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Eval.cs @@ -244,21 +244,14 @@ namespace Debugger ); } + // The following function create values only for the purpuse of evalutaion + // They actually do not allocate memory on the managed heap + // The advantage is that it does not continue the process public static Value CreateValue(Process process, object value) { - if (value is string) { - return NewString(process, (string)value); - } - CorElementType corElemType; - if (value is int) { - corElemType = CorElementType.I4; - } else if (value is byte) { - corElemType = CorElementType.U1; - } else if (value is char) { - corElemType = CorElementType.CHAR; - } else { - throw new NotImplementedException(); - } + if (value == null) throw new ArgumentNullException("value"); + if (value is string) throw new DebuggerException("Can not create string this way"); + CorElementType corElemType = DebugType.TypeNameToCorElementType(value.GetType().FullName); ICorDebugEval corEval = CreateCorEval(process); ICorDebugValue corValue = corEval.CreateValue((uint)corElemType, null); Value v = new Value(process, new Expressions.PrimitiveExpression(value), corValue); @@ -266,13 +259,6 @@ namespace Debugger return v; } - public static Value CreateValueForType(DebugType debugType) - { - ICorDebugEval corEval = CreateCorEval(debugType.Process); - ICorDebugValue corValue = corEval.CastTo().CreateValueForType(debugType.CorType); - return new Value(debugType.Process, new EmptyExpression(), corValue); - } - #region Convenience methods public static Value NewString(Process process, string textToCreate) diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/Ast/PrimitiveExpression.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/Ast/PrimitiveExpression.cs index 0e4535ea09..6f195b5bb8 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/Ast/PrimitiveExpression.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/Ast/PrimitiveExpression.cs @@ -39,7 +39,7 @@ namespace Debugger.Expressions protected override Value EvaluateInternal(StackFrame context) { - return Eval.CreateValue(context.Process, value); + return Eval.CreateValue(context.Process, this.Value); } #region GetHashCode and Equals diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType-Helpers.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType-Helpers.cs index d600bb3b09..4e07d8fcb8 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType-Helpers.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType-Helpers.cs @@ -275,37 +275,68 @@ namespace Debugger.MetaData #endregion - /// - /// Returns simple managed type coresponding to the debug type. - /// Any class yields System.Object - /// + /// Returns simple managed type coresponding to the primitive type. [Tests.Ignore] - public System.Type ManagedType { + public System.Type PrimitiveType { get { - switch(this.corElementType) { - case CorElementType.BOOLEAN: return typeof(System.Boolean); - case CorElementType.CHAR: return typeof(System.Char); - case CorElementType.I1: return typeof(System.SByte); - case CorElementType.U1: return typeof(System.Byte); - case CorElementType.I2: return typeof(System.Int16); - case CorElementType.U2: return typeof(System.UInt16); - case CorElementType.I4: return typeof(System.Int32); - case CorElementType.U4: return typeof(System.UInt32); - case CorElementType.I8: return typeof(System.Int64); - case CorElementType.U8: return typeof(System.UInt64); - case CorElementType.R4: return typeof(System.Single); - case CorElementType.R8: return typeof(System.Double); - case CorElementType.I: return typeof(int); - case CorElementType.U: return typeof(uint); - case CorElementType.SZARRAY: - case CorElementType.ARRAY: return typeof(System.Array); - case CorElementType.OBJECT: return typeof(System.Object); - case CorElementType.STRING: return typeof(System.String); - default: return null; + if (corElementType == CorElementType.VALUETYPE) { + CorElementType corType; + try { + corType = TypeNameToCorElementType(this.FullName); + } catch (DebuggerException) { + return null; + } + return CorElementTypeToManagedType(corType); + } else { + return CorElementTypeToManagedType(corElementType); } } } + internal static Type CorElementTypeToManagedType(CorElementType corElementType) + { + switch(corElementType) { + case CorElementType.BOOLEAN: return typeof(System.Boolean); + case CorElementType.CHAR: return typeof(System.Char); + case CorElementType.I1: return typeof(System.SByte); + case CorElementType.U1: return typeof(System.Byte); + case CorElementType.I2: return typeof(System.Int16); + case CorElementType.U2: return typeof(System.UInt16); + case CorElementType.I4: return typeof(System.Int32); + case CorElementType.U4: return typeof(System.UInt32); + case CorElementType.I8: return typeof(System.Int64); + case CorElementType.U8: return typeof(System.UInt64); + case CorElementType.R4: return typeof(System.Single); + case CorElementType.R8: return typeof(System.Double); + case CorElementType.I: return typeof(System.IntPtr); + case CorElementType.U: return typeof(System.UIntPtr); + case CorElementType.STRING: return typeof(System.String); + default: return null; + } + } + + internal static CorElementType TypeNameToCorElementType(string fullname) + { + switch (fullname) { + case "System.Boolean": return CorElementType.BOOLEAN; + case "System.Char": return CorElementType.CHAR; + case "System.SByte": return CorElementType.I1; + case "System.Byte": return CorElementType.U1; + case "System.Int16": return CorElementType.I2; + case "System.UInt16": return CorElementType.U2; + case "System.Int32": return CorElementType.I4; + case "System.UInt32": return CorElementType.U4; + case "System.Int64": return CorElementType.I8; + case "System.UInt64": return CorElementType.U8; + case "System.Single": return CorElementType.R4; + case "System.Double": return CorElementType.R8; + case "System.IntPtr": return CorElementType.I; + case "System.UIntPtr": return CorElementType.U; + case "System.String": return CorElementType.STRING; + default: throw new DebuggerException("Not a primitive type"); + } + } + /* * Find the super class manually - unused since we have ICorDebugType.GetBase() in .NET 2.0 * diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs index 683ec6eb40..ada2d31a79 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Metadata/DebugType.cs @@ -474,7 +474,7 @@ namespace Debugger.MetaData return className; } } else if (IsPrimitive) { - return this.ManagedType.ToString(); + return this.PrimitiveType.ToString(); } else if (IsPointer) { return this.ElementType.FullName + (this.corElementType == CorElementType.BYREF ? "&" : "*"); } else if (IsVoid) { diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.Primitive.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.Primitive.cs index a984f79c9c..ee987287f4 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.Primitive.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.Primitive.cs @@ -35,28 +35,27 @@ namespace Debugger /// public object PrimitiveValue { get { - if (!this.Type.IsPrimitive) throw new DebuggerException("Value is not a primitive type"); + if (this.Type.PrimitiveType == null) throw new DebuggerException("Value is not a primitive type"); if (this.Type.IsString) { if (this.IsNull) return null; return this.CorReferenceValue.Dereference().CastTo().String; } else { - return CorGenericValue.Value; + return CorGenericValue.GetValue(this.Type.PrimitiveType); } } set { + if (this.Type.PrimitiveType == null) throw new DebuggerException("Value is not a primitive type"); if (this.Type.IsString) { - throw new NotImplementedException(); + this.SetValue(Eval.NewString(this.Process, value.ToString())); } else { - if (value == null) { - throw new DebuggerException("Can not set primitive value to null"); - } + if (value == null) throw new DebuggerException("Can not set primitive value to null"); object newValue; try { - newValue = Convert.ChangeType(value, this.Type.ManagedType); + newValue = Convert.ChangeType(value, this.Type.PrimitiveType); } catch { - throw new NotSupportedException("Can not convert " + value.GetType().ToString() + " to " + this.Type.ManagedType.ToString()); + throw new NotSupportedException("Can not convert " + value.GetType().ToString() + " to " + this.Type.PrimitiveType.ToString()); } - CorGenericValue.Value = newValue; + CorGenericValue.SetValue(this.Type.PrimitiveType, newValue); } } } diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/ICorDebugGenericValue.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/ICorDebugGenericValue.cs index 51fbde9ef0..86b55de632 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/ICorDebugGenericValue.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Wrappers/CorDebug/ICorDebugGenericValue.cs @@ -32,55 +32,54 @@ namespace Debugger.Wrappers.CorDebug } } - public unsafe object Value { - get { - object retValue; - IntPtr pValue = Marshal.AllocHGlobal((int)Size); - GetValue(pValue); - switch((CorElementType)Type) - { - case CorElementType.BOOLEAN: retValue = *((System.Boolean*)pValue); break; - case CorElementType.CHAR: retValue = *((System.Char*) pValue); break; - case CorElementType.I1: retValue = *((System.SByte*) pValue); break; - case CorElementType.U1: retValue = *((System.Byte*) pValue); break; - case CorElementType.I2: retValue = *((System.Int16*) pValue); break; - case CorElementType.U2: retValue = *((System.UInt16*) pValue); break; - case CorElementType.I4: retValue = *((System.Int32*) pValue); break; - case CorElementType.U4: retValue = *((System.UInt32*) pValue); break; - case CorElementType.I8: retValue = *((System.Int64*) pValue); break; - case CorElementType.U8: retValue = *((System.UInt64*) pValue); break; - case CorElementType.R4: retValue = *((System.Single*) pValue); break; - case CorElementType.R8: retValue = *((System.Double*) pValue); break; - case CorElementType.I: retValue = *((int*) pValue); break; - case CorElementType.U: retValue = *((uint*) pValue); break; - default: throw new NotSupportedException(); - } - Marshal.FreeHGlobal(pValue); - return retValue; + public unsafe object GetValue(Type type) + { + object retValue; + IntPtr pValue = Marshal.AllocHGlobal((int)Size); + GetValue(pValue); + switch(type.FullName) { + case "System.Boolean": retValue = *((System.Boolean*)pValue); break; + case "System.Char": retValue = *((System.Char*) pValue); break; + case "System.SByte": retValue = *((System.SByte*) pValue); break; + case "System.Byte": retValue = *((System.Byte*) pValue); break; + case "System.Int16": retValue = *((System.Int16*) pValue); break; + case "System.UInt16": retValue = *((System.UInt16*) pValue); break; + case "System.Int32": retValue = *((System.Int32*) pValue); break; + case "System.UInt32": retValue = *((System.UInt32*) pValue); break; + case "System.Int64": retValue = *((System.Int64*) pValue); break; + case "System.UInt64": retValue = *((System.UInt64*) pValue); break; + case "System.Single": retValue = *((System.Single*) pValue); break; + case "System.Double": retValue = *((System.Double*) pValue); break; + case "System.IntPtr": retValue = *((System.IntPtr*) pValue); break; + case "System.UIntPtr": retValue = *((System.UIntPtr*)pValue); break; + default: throw new NotSupportedException(); } - set { - IntPtr pValue = Marshal.AllocHGlobal((int)Size); - switch((CorElementType)Type) - { - case CorElementType.BOOLEAN: *((System.Boolean*)pValue) = (System.Boolean)value; break; - case CorElementType.CHAR: *((System.Char*) pValue) = (System.Char) value; break; - case CorElementType.I1: *((System.SByte*) pValue) = (System.SByte) value; break; - case CorElementType.U1: *((System.Byte*) pValue) = (System.Byte) value; break; - case CorElementType.I2: *((System.Int16*) pValue) = (System.Int16) value; break; - case CorElementType.U2: *((System.UInt16*) pValue) = (System.UInt16) value; break; - case CorElementType.I4: *((System.Int32*) pValue) = (System.Int32) value; break; - case CorElementType.U4: *((System.UInt32*) pValue) = (System.UInt32) value; break; - case CorElementType.I8: *((System.Int64*) pValue) = (System.Int64) value; break; - case CorElementType.U8: *((System.UInt64*) pValue) = (System.UInt64) value; break; - case CorElementType.R4: *((System.Single*) pValue) = (System.Single) value; break; - case CorElementType.R8: *((System.Double*) pValue) = (System.Double) value; break; - case CorElementType.I: *((int*) pValue) = (int) value; break; - case CorElementType.U: *((uint*) pValue) = (uint) value; break; - default: throw new NotSupportedException(); - } - SetValue(pValue); - Marshal.FreeHGlobal(pValue); + Marshal.FreeHGlobal(pValue); + return retValue; + } + + public unsafe void SetValue(Type type, object value) + { + IntPtr pValue = Marshal.AllocHGlobal((int)Size); + switch(type.FullName) { + case "System.Boolean": *((System.Boolean*)pValue) = (System.Boolean)value; break; + case "System.Char": *((System.Char*) pValue) = (System.Char) value; break; + case "System.SByte": *((System.SByte*) pValue) = (System.SByte) value; break; + case "System.Byte": *((System.Byte*) pValue) = (System.Byte) value; break; + case "System.Int16": *((System.Int16*) pValue) = (System.Int16) value; break; + case "System.UInt16": *((System.UInt16*) pValue) = (System.UInt16) value; break; + case "System.Int32": *((System.Int32*) pValue) = (System.Int32) value; break; + case "System.UInt32": *((System.UInt32*) pValue) = (System.UInt32) value; break; + case "System.Int64": *((System.Int64*) pValue) = (System.Int64) value; break; + case "System.UInt64": *((System.UInt64*) pValue) = (System.UInt64) value; break; + case "System.Single": *((System.Single*) pValue) = (System.Single) value; break; + case "System.Double": *((System.Double*) pValue) = (System.Double) value; break; + case "System.IntPtr": *((System.IntPtr*) pValue) = (System.IntPtr) value; break; + case "System.UIntPtr": *((System.UIntPtr*)pValue) = (System.UIntPtr)value; break; + default: throw new NotSupportedException(); } + SetValue(pValue); + Marshal.FreeHGlobal(pValue); } } } diff --git a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/DebugTypes.cs b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/DebugTypes.cs index 5d39564c40..847283156d 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/DebugTypes.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/TestPrograms/DebugTypes.cs @@ -623,7 +623,7 @@ namespace Debugger.Tests { IsInvalid="False" IsNull="False" IsReference="True" - PrimitiveValue="{Exception: Value is not a primitive type}" + PrimitiveValue="40" Type="System.Int32">