diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DynamicTreeDebuggerRow.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DynamicTreeDebuggerRow.cs index 31a13da551..3343c801f1 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DynamicTreeDebuggerRow.cs +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DynamicTreeDebuggerRow.cs @@ -94,11 +94,6 @@ namespace ICSharpCode.SharpDevelop.Services this[3].Text = val.AsString; } this[3].AllowLabelEdit = val.IsInteger && !ShowValuesInHexadecimal; - if (val.IsObject) { - val.ObjectToString.Changed -= Update; - val.ObjectToString.Changed += Update; - this[3].Text = val.ObjectToString.AsString; - } this.ShowPlus = val.IsObject || val.IsArray; this.ShowMinusWhileExpanded = true; diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/ManagedCallback.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/ManagedCallback.cs index a5f0595c72..0c25f275c2 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/ManagedCallback.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/ManagedCallback.cs @@ -229,8 +229,7 @@ namespace Debugger void HandleEvalComplete(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugEval corEval, bool exception) { - // Let the eval know it that the CorEval has finished - // this will also remove the eval form PendingEvals collection + // Let the eval know that the CorEval has finished Eval eval = process.GetEval(corEval); eval.NotifyEvaluationComplete(!exception); process.NotifyEvaluationComplete(eval); diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/Eval.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/Eval.cs index 0fe3129f1f..f67b8e2d25 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/Eval.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/Eval.cs @@ -12,7 +12,7 @@ using Debugger.Wrappers.CorDebug; namespace Debugger { - public enum EvalState {WaitingForRequest, EvaluationScheduled, Evaluating, EvaluatedSuccessfully, EvaluatedException, EvaluatedNoResult, EvaluatedError}; + public enum EvalState {EvaluationScheduled, Evaluating, EvaluatedSuccessfully, EvaluatedException, EvaluatedNoResult, EvaluatedError}; /// /// This class holds information about function evaluation. @@ -29,14 +29,13 @@ namespace Debugger } Process process; - Value val; - string description; + Value result; + string description; EvaluationInvoker evaluationInvoker; - EvalState state = EvalState.WaitingForRequest; + EvalState state = EvalState.EvaluationScheduled; ICorDebugEval corEval; string errorMsg; - ICorDebugValue result; public Process Process { get { @@ -46,7 +45,15 @@ namespace Debugger public Value Result { get { - return val; + switch(this.State) { + case EvalState.EvaluationScheduled: throw new CannotGetValueException("Evaluation pending"); + case EvalState.Evaluating: throw new CannotGetValueException("Evaluating..."); + case EvalState.EvaluatedSuccessfully: return result; + case EvalState.EvaluatedException: return result; + case EvalState.EvaluatedNoResult: throw new CannotGetValueException("No return value"); + case EvalState.EvaluatedError: throw new CannotGetValueException(errorMsg); + default: throw new DebuggerException("Unknown state"); + } } } @@ -73,18 +80,14 @@ namespace Debugger Eval(Process process, string description, - IExpirable[] expireDependencies, - IMutable[] mutateDependencies, EvaluationInvoker evaluationInvoker) { this.process = process; this.description = description; - this.val = new Value(process, - expireDependencies, - mutateDependencies, - delegate { return GetCorValue(); }); - this.val.Changed += delegate { SetState(EvalState.WaitingForRequest, null, null); }; this.evaluationInvoker = evaluationInvoker; + + process.ScheduleEval(this); + process.Debugger.MTA2STA.AsyncCall(delegate { process.StartEvaluation(); }); } internal bool IsCorEval(ICorDebugEval corEval) @@ -92,33 +95,6 @@ namespace Debugger return this.corEval == corEval; } - public ICorDebugValue GetCorValue() - { - switch(this.State) { - case EvalState.WaitingForRequest: RequestEvaluation(); goto case EvalState.EvaluationScheduled; - case EvalState.EvaluationScheduled: throw new CannotGetValueException("Evaluation pending"); - case EvalState.Evaluating: throw new CannotGetValueException("Evaluating..."); - case EvalState.EvaluatedSuccessfully: return result; - case EvalState.EvaluatedException: return result; - case EvalState.EvaluatedNoResult: throw new CannotGetValueException("No return value"); - case EvalState.EvaluatedError: throw new CannotGetValueException(errorMsg); - default: throw new DebuggerException("Unknown state"); - } - } - - void SetState(EvalState state, string errorMsg, ICorDebugValue result) - { - this.state = state; - this.errorMsg = errorMsg; - this.result = result; - } - - void ChangeState(EvalState state, string errorMsg, ICorDebugValue result) - { - SetState(state, errorMsg, result); - this.Result.NotifyChange(); - } - /// Synchronously calls a function and returns its return value public static Value InvokeMethod(Process process, System.Type type, string name, Value thisValue, Value[] args) { @@ -133,15 +109,9 @@ namespace Debugger public static Eval AsyncInvokeMethod(MethodInfo method, Value thisValue, Value[] args) { -// string moduleName = System.IO.Path.GetFileName(type.Assembly.Location); -// Module module = process.GetModule(moduleName); -// string containgType = type.FullName; -// ICorDebugFunction corFunction = module.GetMethod(containgType, functionName, args.Length); return new Eval( method.Process, "Function call: " + method.DeclaringType.Name + "." + method.Name, - new IExpirable[] {}, // TODO - new IMutable[] {}, delegate(ICorDebugEval corEval) { StartMethodInvoke(corEval, method, thisValue, args); } ); } @@ -180,8 +150,6 @@ namespace Debugger return new Eval( process, "New string: " + textToCreate, - new IExpirable[] {}, - new IMutable[] {}, delegate(ICorDebugEval corEval) { corEval.NewString(textToCreate); } ); } @@ -196,22 +164,10 @@ namespace Debugger return new Eval( process, "New object: " + classToCreate.Token, - new IExpirable[] {}, - new IMutable[] {}, delegate(ICorDebugEval corEval) { corEval.NewObjectNoConstructor(classToCreate); } ); } - - public void RequestEvaluation() - { - if (Evaluated || State == EvalState.WaitingForRequest) { - process.ScheduleEval(this); - process.Debugger.MTA2STA.AsyncCall(delegate { process.StartEvaluation(); }); - ChangeState(EvalState.EvaluationScheduled, null, null); - } - } - /// True if setup was successful internal bool SetupEvaluation(Thread targetThread) { @@ -243,19 +199,21 @@ namespace Debugger } } - ChangeState(EvalState.Evaluating, null, null); + state = EvalState.Evaluating; return true; } catch (EvalSetupException e) { - ChangeState(EvalState.EvaluatedError, e.Message, null); + state = EvalState.EvaluatedError; + errorMsg = e.Message; return false; } } public Value EvaluateNow() { - while (State == EvalState.WaitingForRequest) { - RequestEvaluation(); - process.WaitForPause(); + while (!Evaluated) { + if (process.IsPaused) { + process.StartEvaluation(); + } process.WaitForPause(); } return this.Result; @@ -266,13 +224,17 @@ namespace Debugger // Eval result should be ICorDebugHandleValue so it should survive Continue() if (corEval.Result == null) { - ChangeState(EvalState.EvaluatedNoResult, null, null); + state = EvalState.EvaluatedNoResult; } else { if (successful) { - ChangeState(EvalState.EvaluatedSuccessfully, null, corEval.Result); + state = EvalState.EvaluatedSuccessfully; } else { - ChangeState(EvalState.EvaluatedException, null, corEval.Result); + state = EvalState.EvaluatedException; } + result = new Value(process, + new IExpirable[] {}, + new IMutable[] {}, + delegate { return corEval.Result; }); } } } diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/BindingFlags.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/BindingFlags.cs index 71866dd52c..4e94c856ce 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/BindingFlags.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/BindingFlags.cs @@ -19,13 +19,13 @@ namespace Debugger [Flags] public enum BindingFlags { /// Return instance (ie non-static members) members - Instance, + Instance = 1, /// Return static members - Static, + Static = 2, /// Return public members - Public, + Public = 4, /// Return members which are not public - NonPublic, + NonPublic = 8, /// Return all members All = Instance | Static | Public | NonPublic }; diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/DebugType.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/DebugType.cs index cfdbe830ae..edcf57599c 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/DebugType.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Types/DebugType.cs @@ -200,7 +200,7 @@ namespace Debugger { DebugType type = this.BaseType; while (type != null) { - if (this.Equals(type)) return true; + if (type.Equals(superType)) return true; type = type.BaseType; } return false; @@ -210,8 +210,8 @@ namespace Debugger /// current type or can be implicitly cast to it public bool IsInstanceOfType(Value objectInstance) { - return this.Equals(objectInstance.Type) || - this.IsSubclassOf(objectInstance.Type); + return objectInstance.Type.Equals(this) || + objectInstance.Type.IsSubclassOf(this); } void LoadType() @@ -292,8 +292,24 @@ namespace Debugger /// Compares two types public override bool Equals(object obj) { - return obj is DebugType && - ((DebugType)obj).CorType == this.CorType; + DebugType other = obj as DebugType; + if (other != null) { + if (this.IsArray) { + throw new NotImplementedException(); // TODO + } + if (this.IsPrimitive) { + return other.IsPrimitive && + other.corElementType == this.corElementType; + } + if (this.IsClass || this.IsValueType) { + return (other.IsClass || other.IsValueType) && + other.Module == this.Module && + other.MetadataToken == this.MetadataToken; + } + throw new DebuggerException("Unknown type"); + } else { + return false; + } } /// Get hash code of the object diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/Value-Object.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/Value-Object.cs index 825709ebc2..a7285bdc1d 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/Value-Object.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/Value-Object.cs @@ -31,17 +31,6 @@ namespace Debugger } } - /// Returns a text which is produced by calling object.ToString() - public Value ObjectToString { - get { - return Eval.AsyncInvokeMethod( - MethodInfo.GetFromName(Process, typeof(object), "ToString", 0), - this, - null - ).Result; - } - } - /// /// Get a field or property of an object with a given name. /// diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/Value.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/Value.cs index e08f419b51..b87d94aacf 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/Value.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Values/Value.cs @@ -76,14 +76,15 @@ namespace Debugger cache.Type = DebugType.Create(process, RawCorValue.As().ExactType); // AsString representation - if (IsNull) cache.AsString = ""; + if (IsNull) cache.AsString = ""; if (IsArray) cache.AsString = "{" + this.Type.Name + "}"; if (IsObject) cache.AsString = "{" + this.Type.Name + "}"; + //if (IsObject) cache.AsString = Eval.InvokeMethod(Process, typeof(object), "ToString", this, new Value[] {}).AsString; if (IsPrimitive) cache.AsString = PrimitiveValue != null ? PrimitiveValue.ToString() : String.Empty; - TimeSpan totalTime = Util.HighPrecisionTimer.Now - startTime; - process.TraceMessage("Obtained value: " + cache.AsString + " (" + totalTime.TotalMilliseconds + " ms)"); + string name = this is NamedValue ? ((NamedValue)this).Name + " = " : String.Empty; + process.TraceMessage("Obtained value: " + name + cache.AsString + " (" + totalTime.TotalMilliseconds + " ms)"); } return cache; }