diff --git a/SharpDevelop.Tests.sln b/SharpDevelop.Tests.sln index a4c13fad46..308757e312 100644 --- a/SharpDevelop.Tests.sln +++ b/SharpDevelop.Tests.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 -# SharpDevelop 4.3.0.8807-alpha +# SharpDevelop 4.2.0.8717-Beta 2 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Main", "Main", "{256F5C28-532C-44C0-8AB8-D8EC5E492E01}" ProjectSection(SolutionItems) = postProject EndProjectSection diff --git a/src/AddIns/Analysis/UnitTesting/Test/Utils/MockDebugger.cs b/src/AddIns/Analysis/UnitTesting/Test/Utils/MockDebugger.cs index 3caf49a6c6..dd99f8d047 100644 --- a/src/AddIns/Analysis/UnitTesting/Test/Utils/MockDebugger.cs +++ b/src/AddIns/Analysis/UnitTesting/Test/Utils/MockDebugger.cs @@ -154,12 +154,7 @@ namespace UnitTesting.Tests.Utils throw new NotImplementedException(); } - public bool CanSetInstructionPointer(string filename, int line, int column) - { - throw new NotImplementedException(); - } - - public bool SetInstructionPointer(string filename, int line, int column) + public bool SetInstructionPointer(string filename, int line, int column, bool dryRun) { throw new NotImplementedException(); } diff --git a/src/AddIns/BackendBindings/Scripting/Test/Utils/MockDebugger.cs b/src/AddIns/BackendBindings/Scripting/Test/Utils/MockDebugger.cs index 43bcfcacd6..fd6a91f501 100644 --- a/src/AddIns/BackendBindings/Scripting/Test/Utils/MockDebugger.cs +++ b/src/AddIns/BackendBindings/Scripting/Test/Utils/MockDebugger.cs @@ -128,12 +128,7 @@ namespace ICSharpCode.Scripting.Tests.Utils throw new NotImplementedException(); } - public bool CanSetInstructionPointer(string filename, int line, int column) - { - throw new NotImplementedException(); - } - - public bool SetInstructionPointer(string filename, int line, int column) + public bool SetInstructionPointer(string filename, int line, int column, bool dryRun) { throw new NotImplementedException(); } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin index 79c009707e..b79f5d4de9 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin +++ b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.addin @@ -15,13 +15,6 @@ - - - - - - - - - - - - - - - - - - @@ -198,44 +168,6 @@ /> - - - - - - - - - - - - - diff --git a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj index bd536316c0..14bc2e885c 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj +++ b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj @@ -97,30 +97,19 @@ + + DebuggingOptionsPanel.xaml Code - - CallStackPad.xaml + Code - - - - ConditionCell.xaml - - - - WatchList.xaml - - - WatchListAutoCompleteCell.xaml - - + DrawSurface.xaml Code @@ -133,10 +122,6 @@ ThreadStack.xaml Code - - WatchInputBox.xaml - Code - @@ -150,18 +135,16 @@ DebuggingSymbolsPanel.cs - UserControl - + Component - Form @@ -175,28 +158,13 @@ EditBreakpointScriptWindow.xaml Code - DebuggerTooltipControl.xaml - - - PinCloseControl.xaml - - - PinDebuggerControl.xaml - - - - VisualizerPicker.xaml - - - - - + @@ -209,7 +177,7 @@ - + @@ -223,6 +191,7 @@ + @@ -253,12 +222,10 @@ - - TextVisualizerWindow.xaml Code @@ -274,7 +241,6 @@ DebuggeeExceptionForm.cs - @@ -284,14 +250,7 @@ Properties\GlobalAssemblyInfo.cs - - - - - - - - + @@ -312,9 +271,6 @@ GridVisualizerWindow.xaml Code - - - @@ -324,7 +280,6 @@ - @@ -379,18 +334,11 @@ - - - - + - - - - @@ -408,8 +356,9 @@ ICSharpCode.Core.WinForms False + - + @@ -423,7 +372,6 @@ - diff --git a/src/AddIns/Debugger/Debugger.Core/NRefactory/Visitors/ExpressionEvaluator.cs b/src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluator.cs similarity index 92% rename from src/AddIns/Debugger/Debugger.Core/NRefactory/Visitors/ExpressionEvaluator.cs rename to src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluator.cs index 633d7563ab..d0e693f100 100644 --- a/src/AddIns/Debugger/Debugger.Core/NRefactory/Visitors/ExpressionEvaluator.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluator.cs @@ -6,17 +6,17 @@ using System.Collections; using System.Collections.Generic; using System.Reflection; using System.Text; - using Debugger; using Debugger.MetaData; using ICSharpCode.NRefactory.Ast; +using ICSharpCode.SharpDevelop.Services; namespace ICSharpCode.NRefactory.Visitors { public class EvaluateException: GetValueException { - public EvaluateException(INode code, string msg):base(code, msg) {} - public EvaluateException(INode code, string msgFmt, params string[] msgArgs):base(code, string.Format(msgFmt, msgArgs)) {} + public EvaluateException(INode code, string msg):base(msg) {} + public EvaluateException(INode code, string msgFmt, params string[] msgArgs):base(string.Format(msgFmt, msgArgs)) {} } class TypedValue @@ -51,6 +51,10 @@ namespace ICSharpCode.NRefactory.Visitors get { return context; } } + public Thread EvalThread { + get { return this.Context.Thread; } + } + ExpressionEvaluator(StackFrame context) { this.context = context; @@ -76,19 +80,12 @@ namespace ICSharpCode.NRefactory.Visitors return Evaluate(Parse(code, language), context, data); } - public static Value Evaluate(INode code, Process context) - { - if (context.SelectedStackFrame == null && context.SelectedThread.MostRecentStackFrame == null) - // This can happen when needed 'dll' is missing. This causes an exception dialog to be shown even before the applicaiton starts - throw new GetValueException("Can not evaluate because the process has no managed stack frames"); - - return Evaluate(code, context.GetCurrentExecutingFrame()); - } - public static Value Evaluate(INode code, StackFrame context, object data = null) { - if (context == null) throw new ArgumentNullException("context"); - if (context.IsInvalid) throw new DebuggerException("The context is no longer valid"); + if (context == null) + throw new GetValueException("Invalid stackframe"); + if (context.IsInvalid) + throw new DebuggerException("The context is no longer valid"); TypedValue val = new ExpressionEvaluator(context).Evaluate(code, false, data); if (val == null) @@ -113,7 +110,7 @@ namespace ICSharpCode.NRefactory.Visitors return astExpression; } - public static string FormatValue(Value val) + public static string FormatValue(Thread evalThread, Value val) { if (val == null) { return null; @@ -127,7 +124,7 @@ namespace ICSharpCode.NRefactory.Visitors foreach(Value item in val.GetArrayElements()) { if (!first) sb.Append(", "); first = false; - sb.Append(FormatValue(item)); + sb.Append(FormatValue(evalThread, item)); } sb.Append("}"); return sb.ToString(); @@ -135,13 +132,13 @@ namespace ICSharpCode.NRefactory.Visitors StringBuilder sb = new StringBuilder(); sb.Append(val.Type.Name); sb.Append(" {"); - val = val.GetPermanentReference(); - int count = (int)val.GetMemberValue("Count").PrimitiveValue; + val = val.GetPermanentReference(evalThread); + int count = (int)val.GetMemberValue(evalThread, "Count").PrimitiveValue; for(int i = 0; i < count; i++) { if (i > 0) sb.Append(", "); DebugPropertyInfo itemProperty = (DebugPropertyInfo)val.Type.GetProperty("Item"); - Value item = val.GetPropertyValue(itemProperty, Eval.CreateValue(val.AppDomain, i)); - sb.Append(FormatValue(item)); + Value item = val.GetPropertyValue(evalThread, itemProperty, Eval.CreateValue(evalThread, i)); + sb.Append(FormatValue(evalThread, item)); } sb.Append("}"); return sb.ToString(); @@ -152,7 +149,7 @@ namespace ICSharpCode.NRefactory.Visitors } else if (val.Type.IsPrimitive) { return val.PrimitiveValue.ToString(); } else { - return val.InvokeToString(); + return val.InvokeToString(evalThread); } } @@ -163,25 +160,16 @@ namespace ICSharpCode.NRefactory.Visitors TypedValue Evaluate(INode expression, bool permRef, object data = null) { - // Try to get the value from cache - // (the cache is cleared when the process is resumed) TypedValue val; - if (context.Process.ExpressionsCache.TryGetValue(expression, out val)) { - if (val == null || !val.Value.IsInvalid) - return val; - } System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch(); watch.Start(); try { val = (TypedValue)expression.AcceptVisitor(this, data); if (val != null && permRef) - val = new TypedValue(val.Value.GetPermanentReference(), val.Type); - } catch (GetValueException e) { - e.Expression = expression; - throw; + val = new TypedValue(val.Value.GetPermanentReference(this.EvalThread), val.Type); } catch (NotImplementedException e) { - throw new GetValueException(expression, "Language feature not implemented: " + e.Message); + throw new EvaluateException(expression, "Language feature not implemented: " + e.Message); } finally { watch.Stop(); context.Process.TraceMessage("Evaluated: {0} in {1} ms total", expression.PrettyPrint(), watch.ElapsedMilliseconds); @@ -190,9 +178,6 @@ namespace ICSharpCode.NRefactory.Visitors if (val != null && val.Value.IsInvalid) throw new DebuggerException("Expression \"" + expression.PrettyPrint() + "\" is invalid right after evaluation"); - // Add the result to cache - context.Process.ExpressionsCache[expression] = val; - return val; } @@ -266,7 +251,7 @@ namespace ICSharpCode.NRefactory.Visitors TypedValue CreateValue(object primitiveValue) { - Value val = Eval.CreateValue(context.AppDomain, primitiveValue); + Value val = Eval.CreateValue(this.EvalThread, primitiveValue); return new TypedValue(val, val.Type); } @@ -312,7 +297,7 @@ namespace ICSharpCode.NRefactory.Visitors if (!left.Value.IsReference && left.Type.FullName != right.Type.FullName) { throw new GetValueException(string.Format("Type {0} expected, {1} seen", left.Type.FullName, right.Type.FullName)); } - left.Value.SetValue(right.Value); + left.Value.SetValue(this.EvalThread, right.Value); return right; } @@ -367,17 +352,6 @@ namespace ICSharpCode.NRefactory.Visitors { string identifier = identifierExpression.Identifier; - if (identifier == "__exception") { - if (context.Thread.CurrentException != null) { - return new TypedValue( - context.Thread.CurrentException.Value, - DebugType.CreateFromType(context.AppDomain.Mscorlib, typeof(System.Exception)) - ); - } else { - throw new GetValueException("No current exception"); - } - } - DebugParameterInfo par = context.MethodInfo.GetParameter(identifier); if (par != null) return new TypedValue(par.GetValue(context), (DebugType)par.ParameterType); @@ -400,14 +374,14 @@ namespace ICSharpCode.NRefactory.Visitors if (thisValue != null) { IDebugMemberInfo instMember = (IDebugMemberInfo)thisValue.Type.GetMember(identifier, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, DebugType.IsFieldOrNonIndexedProperty); if (instMember != null) - return new TypedValue(Value.GetMemberValue(thisValue.Value, (MemberInfo)instMember), instMember.MemberType); + return new TypedValue(Value.GetMemberValue(this.EvalThread, thisValue.Value, (MemberInfo)instMember), instMember.MemberType); } // Static class members foreach(DebugType declaringType in ((DebugType)context.MethodInfo.DeclaringType).GetSelfAndDeclaringTypes()) { IDebugMemberInfo statMember = (IDebugMemberInfo)declaringType.GetMember(identifier, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static, DebugType.IsFieldOrNonIndexedProperty); if (statMember != null) - return new TypedValue(Value.GetMemberValue(null, (MemberInfo)statMember), statMember.MemberType); + return new TypedValue(Value.GetMemberValue(this.EvalThread, null, (MemberInfo)statMember), statMember.MemberType); } throw new GetValueException("Identifier \"" + identifier + "\" not found in this context"); @@ -441,7 +415,7 @@ namespace ICSharpCode.NRefactory.Visitors if (pi == null) throw new GetValueException("The object does not have an indexer property"); return new TypedValue( - target.Value.GetPropertyValue(pi, GetValues(indexes)), + target.Value.GetPropertyValue(this.EvalThread, pi, GetValues(indexes)), (DebugType)pi.PropertyType ); } @@ -479,7 +453,7 @@ namespace ICSharpCode.NRefactory.Visitors MethodInfo method = targetType.GetMethod(methodName, DebugType.BindingFlagsAllInScope, null, GetTypes(args), null); if (method == null) throw new GetValueException("Method " + methodName + " not found"); - Value retVal = Value.InvokeMethod(target != null ? target.Value : null, method, GetValues(args)); + Value retVal = Value.InvokeMethod(this.EvalThread, target != null ? target.Value : null, method, GetValues(args)); if (retVal == null) return null; return new TypedValue(retVal, (DebugType)method.ReturnType); @@ -492,10 +466,10 @@ namespace ICSharpCode.NRefactory.Visitors DebugType type = objectCreateExpression.CreateType.ResolveType(context.AppDomain); List ctorArgs = EvaluateAll(objectCreateExpression.Parameters); - ConstructorInfo ctor = type.GetConstructor(BindingFlags.Default, null, CallingConventions.Any, GetTypes(ctorArgs), null); + DebugConstructorInfo ctor = (DebugConstructorInfo)type.GetConstructor(BindingFlags.Default, null, CallingConventions.Any, GetTypes(ctorArgs), null); if (ctor == null) throw new EvaluateException(objectCreateExpression, "Constructor not found"); - Value val = (Value)ctor.Invoke(GetValues(ctorArgs)); + Value val = Value.InvokeMethod(this.EvalThread, null, ctor.MethodInfo, GetValues(ctorArgs)); return new TypedValue(val, type); } @@ -511,14 +485,14 @@ namespace ICSharpCode.NRefactory.Visitors } else if (!arrayCreateExpression.ArrayInitializer.IsNull) { length = arrayCreateExpression.ArrayInitializer.CreateExpressions.Count; } - Value array = Eval.NewArray((DebugType)type.GetElementType(), (uint)length, null); + Value array = Eval.NewArray(this.EvalThread, (DebugType)type.GetElementType(), (uint)length, null); if (!arrayCreateExpression.ArrayInitializer.IsNull) { List inits = arrayCreateExpression.ArrayInitializer.CreateExpressions; if (inits.Count != length) throw new EvaluateException(arrayCreateExpression, "Incorrect initializer length"); for(int i = 0; i < length; i++) { TypedValue init = EvaluateAs(inits[i], (DebugType)type.GetElementType()); - array.SetArrayElement(new int[] { i }, init.Value); + array.SetArrayElement(this.EvalThread, new int[] { i }, init.Value); } } return new TypedValue(array, type); @@ -545,7 +519,7 @@ namespace ICSharpCode.NRefactory.Visitors if (memberInfos.Length == 0) throw new GetValueException("Member \"" + memberReferenceExpression.MemberName + "\" not found"); return new TypedValue( - Value.GetMemberValue(target != null ? target.Value : null, memberInfos[0]), + Value.GetMemberValue(this.EvalThread, target != null ? target.Value : null, memberInfos[0]), ((IDebugMemberInfo)memberInfos[0]).MemberType ); } @@ -772,8 +746,8 @@ namespace ICSharpCode.NRefactory.Visitors if (op == BinaryOperatorType.Add) { if (left.Type.Is() || right.Type.Is()) { - string a = left.Value.IsNull ? string.Empty : left.Value.InvokeToString(); - string b = right.Value.IsNull ? string.Empty : right.Value.InvokeToString(); + string a = left.Value.IsNull ? string.Empty : left.Value.InvokeToString(this.EvalThread); + string b = right.Value.IsNull ? string.Empty : right.Value.InvokeToString(this.EvalThread); return CreateValue(a + b); } } diff --git a/src/AddIns/Debugger/Debugger.Core/NRefactory/Ast/ExpressionExtensionMethods.cs b/src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionExtensionMethods.cs similarity index 97% rename from src/AddIns/Debugger/Debugger.Core/NRefactory/Ast/ExpressionExtensionMethods.cs rename to src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionExtensionMethods.cs index a7cc14f177..f111bc4812 100644 --- a/src/AddIns/Debugger/Debugger.Core/NRefactory/Ast/ExpressionExtensionMethods.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionExtensionMethods.cs @@ -4,20 +4,21 @@ using System; using System.Collections.Generic; using System.Reflection; - using Debugger; using Debugger.MetaData; using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.PrettyPrinter; using ICSharpCode.NRefactory.Visitors; +using ICSharpCode.SharpDevelop.Services; namespace ICSharpCode.NRefactory.Ast { public static class ExpressionExtensionMethods { - public static Value Evaluate(this Expression expression, Process process) + // EXPR-EVAL (To be removed when ExpressionEvaluator is deprecated) + public static Value Evaluate(this Expression expression) { - return ExpressionEvaluator.Evaluate(expression, process); + return ExpressionEvaluator.Evaluate(expression, WindowsDebugger.CurrentStackFrame); } static M SetStaticType(this M expr, DebugType type) where M: INode diff --git a/src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptions.cs b/src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptions.cs index 9632eb7b95..72199e81bd 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptions.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptions.cs @@ -4,13 +4,13 @@ using System; using System.Drawing; using System.Windows.Forms; - +using System.Xml.Serialization; using Debugger; using ICSharpCode.Core; namespace ICSharpCode.SharpDevelop.Services { - public enum ShowIntegersAs { Auto, Decimal, Hexadecimal }; + public enum ShowIntegersAs { Decimal, Hexadecimal, Both, Auto }; [Serializable] public class DebuggingOptions: Options @@ -28,7 +28,6 @@ namespace ICSharpCode.SharpDevelop.Services DebuggeeExceptionWindowState = FormWindowState.Normal; } - public bool ICorDebugVisualizerEnabled { get; set; } public ShowIntegersAs ShowIntegersAs { get; set; } public bool ShowArgumentNames { get; set; } public bool ShowArgumentValues { get; set; } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/BreakPointsPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/BreakPointsPad.cs index c93bc25bfb..97179860ed 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/BreakPointsPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/BreakPointsPad.cs @@ -17,51 +17,16 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads { public class BreakPointsPad : BookmarkPadBase { - WindowsDebugger debugger; - NDebugger debuggerCore; - public BreakPointsPad() { - InitializeComponents(); + var res = new CommonResources(); + res.InitializeComponent(); - myPanel.Children.Add(CreateToolBar()); + Grid grid = (Grid)this.Control; + ToolBar toolbar = ToolBarService.CreateToolBar(grid, this, "/SharpDevelop/Pads/BreakpointPad/Toolbar"); + grid.Children.Add(toolbar); - CreateColumns(); - } - - void InitializeComponents() - { - debugger = (WindowsDebugger)DebuggerService.CurrentDebugger; - - if (debugger.ServiceInitialized) { - InitializeDebugger(); - } else { - debugger.Initialize += delegate { - InitializeDebugger(); - }; - } - } - - public void InitializeDebugger() - { - debuggerCore = debugger.DebuggerCore; - } - - protected override ToolBar CreateToolBar() - { - ToolBar toolbar = ToolBarService.CreateToolBar(myPanel, this, "/SharpDevelop/Pads/BreakpointPad/Toolbar"); - toolbar.SetValue(Grid.RowProperty, 0); - return toolbar; - } - - protected override void CreateColumns() - { - string conditionHeader = StringParser.Parse("${res:MainWindow.Windows.Debug.Conditional.Breakpoints.ConditionalColumnHeader}"); - - // HACK - DataTemplate cellTemplate = new ConditionCell().FindResource("ConditionCellTemplate") as DataTemplate; - - listView.AddColumn(conditionHeader, cellTemplate); + this.control.listView.View = (GridView)res["breakpointsGridView"]; } protected override bool ShowBookmarkInThisPad(SDBookmark mark) @@ -69,27 +34,16 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads return mark.IsVisibleInBookmarkPad && mark is BreakpointBookmark; } - protected override void OnItemActivated(object sender, EventArgs e) + protected override void OnItemActivated(SDBookmark bookmark) { - var node = CurrentItem; - if (node == null) - return; - SDBookmark mark = node.Mark as SDBookmark; - if (mark == null) - return; - - string fileName = mark.FileName; - if (mark is DecompiledBreakpointBookmark) { + if (bookmark is DecompiledBreakpointBookmark) { // get information from breakpoint and navigate to the decompiled type string assemblyFile, typeName; - if (DecompiledBreakpointBookmark.GetAssemblyAndType(fileName, out assemblyFile, out typeName)) { - NavigationService.NavigateTo(assemblyFile, typeName, string.Empty, mark.LineNumber, false); + if (DecompiledBreakpointBookmark.GetAssemblyAndType(bookmark.FileName, out assemblyFile, out typeName)) { + NavigationService.NavigateTo(assemblyFile, typeName, string.Empty, bookmark.LineNumber, false); } } else { - // jump to normal breakpoint - FileService.JumpToFilePosition(fileName, mark.LineNumber, 1); - - // TODO: if other types of breakpoint bookmarks are available, one should do jumping/navigation here + base.OnItemActivated(bookmark); } } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.cs new file mode 100644 index 0000000000..f7fd70f8d6 --- /dev/null +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.cs @@ -0,0 +1,210 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using Debugger; +using Debugger.AddIn.TreeModel; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Services; + +namespace ICSharpCode.SharpDevelop.Gui.Pads +{ + public class CallStackPad : AbstractPadContent + { + ListView listView; + + public override object Control { + get { return this.listView; } + } + + public CallStackPad() + { + var res = new CommonResources(); + res.InitializeComponent(); + + listView = new ListView(); + listView.View = (GridView)res["callstackGridView"]; + listView.MouseDoubleClick += listView_MouseDoubleClick; + + listView.ContextMenu = CreateMenu(); + + WindowsDebugger.RefreshingPads += RefreshPad; + RefreshPad(); + } + + ContextMenu CreateMenu() + { + MenuItem extMethodsItem = new MenuItem(); + extMethodsItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ShowExternalMethods"); + extMethodsItem.IsChecked = DebuggingOptions.Instance.ShowExternalMethods; + extMethodsItem.Click += delegate { + extMethodsItem.IsChecked = DebuggingOptions.Instance.ShowExternalMethods = !DebuggingOptions.Instance.ShowExternalMethods; + WindowsDebugger.RefreshPads(); + }; + + MenuItem moduleItem = new MenuItem(); + moduleItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ShowModuleNames"); + moduleItem.IsChecked = DebuggingOptions.Instance.ShowModuleNames; + moduleItem.Click += delegate { + moduleItem.IsChecked = DebuggingOptions.Instance.ShowModuleNames = !DebuggingOptions.Instance.ShowModuleNames; + WindowsDebugger.RefreshPads(); + }; + + MenuItem argNamesItem = new MenuItem(); + argNamesItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ShowArgumentNames"); + argNamesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentNames; + argNamesItem.Click += delegate { + argNamesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentNames = !DebuggingOptions.Instance.ShowArgumentNames; + WindowsDebugger.RefreshPads(); + }; + + MenuItem argValuesItem = new MenuItem(); + argValuesItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ShowArgumentValues"); + argValuesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentValues; + argValuesItem.Click += delegate { + argValuesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentValues = !DebuggingOptions.Instance.ShowArgumentValues; + WindowsDebugger.RefreshPads(); + }; + + MenuItem lineItem = new MenuItem(); + lineItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ShowLineNumber"); + lineItem.IsChecked = DebuggingOptions.Instance.ShowLineNumbers; + lineItem.Click += delegate { + lineItem.IsChecked = DebuggingOptions.Instance.ShowLineNumbers = !DebuggingOptions.Instance.ShowLineNumbers; + WindowsDebugger.RefreshPads(); + }; + + return new ContextMenu() { + Items = { + extMethodsItem, + new Separator(), + moduleItem, + argNamesItem, + argValuesItem, + lineItem + } + }; + } + + void listView_MouseDoubleClick(object sender, MouseButtonEventArgs e) + { + CallStackItem item = listView.SelectedItem as CallStackItem; + if (item == null) + return; + + if (item.Frame.Process.IsPaused) { + if (item.Frame != null) { + // check for options - if these options are enabled, selecting the frame should not continue + if (!item.Frame.HasSymbols && !item.Frame.Process.Options.DecompileCodeWithoutSymbols) { + MessageService.ShowMessage("${res:MainWindow.Windows.Debug.CallStack.CannotSwitchWithoutSymbolsOrDecompiledCodeOptions}", + "${res:MainWindow.Windows.Debug.CallStack.FunctionSwitch}"); + return; + } + WindowsDebugger.CurrentStackFrame = item.Frame; + WindowsDebugger.Instance.JumpToCurrentLine(); + WindowsDebugger.RefreshPads(); + } + } else { + MessageService.ShowMessage("${res:MainWindow.Windows.Debug.CallStack.CannotSwitchWhileRunning}", "${res:MainWindow.Windows.Debug.CallStack.FunctionSwitch}"); + } + } + + void RefreshPad() + { + Thread thead = WindowsDebugger.CurrentThread; + if (thead == null) { + listView.ItemsSource = null; + } else { + var items = new ObservableCollection(); + bool previousItemIsExternalMethod = false; + WindowsDebugger.CurrentProcess.EnqueueForEach( + listView.Dispatcher, + thead.GetCallstack(100), + f => items.AddIfNotNull(CreateItem(f, ref previousItemIsExternalMethod)) + ); + listView.ItemsSource = items; + } + } + + CallStackItem CreateItem(StackFrame frame, ref bool previousItemIsExternalMethod) + { + bool showExternalMethods = DebuggingOptions.Instance.ShowExternalMethods; + if (frame.HasSymbols || showExternalMethods) { + // Show the method in the list + previousItemIsExternalMethod = false; + return new CallStackItem() { + Frame = frame, + ImageSource = new ResourceServiceImage("Icons.16x16.Method").ImageSource, + Name = GetFullName(frame) + }; + } else { + // Show [External methods] in the list + if (previousItemIsExternalMethod) + return null; + previousItemIsExternalMethod = true; + return new CallStackItem() { + Name = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ExternalMethods") + }; + } + } + + internal static string GetFullName(StackFrame frame) + { + StringBuilder name = new StringBuilder(64); + if (DebuggingOptions.Instance.ShowModuleNames) { + name.Append(frame.MethodInfo.DebugModule.ToString()); + name.Append('!'); + } + name.Append(frame.MethodInfo.DeclaringType.FullName); + name.Append('.'); + name.Append(frame.MethodInfo.Name); + if (DebuggingOptions.Instance.ShowArgumentNames || DebuggingOptions.Instance.ShowArgumentValues) { + name.Append('('); + for (int i = 0; i < frame.ArgumentCount; i++) { + if (DebuggingOptions.Instance.ShowArgumentNames) { + name.Append(frame.MethodInfo.GetParameters()[i].Name); + if (DebuggingOptions.Instance.ShowArgumentValues) { + name.Append('='); + } + } + if (DebuggingOptions.Instance.ShowArgumentValues) { + try { + name.Append(frame.GetArgumentValue(i).AsString(100)); + } catch (GetValueException) { + name.Append(ResourceService.GetString("Global.NA")); + } + } + if (i < frame.ArgumentCount - 1) { + name.Append(", "); + } + } + name.Append(')'); + } + if (DebuggingOptions.Instance.ShowLineNumbers) { + if (frame.NextStatement != null) { + name.Append(':'); + name.Append(frame.NextStatement.StartLine.ToString()); + } + } + return name.ToString(); + } + } + + public class CallStackItem + { + public StackFrame Frame { get; set; } + public ImageSource ImageSource { get; set; } + public string Name { get; set; } + + public Brush FontColor { + get { return this.Frame == null || this.Frame.HasSymbols ? Brushes.Black : Brushes.Gray; } + } + } +} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.xaml b/src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.xaml deleted file mode 100644 index 794898464c..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.xaml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.xaml.cs deleted file mode 100644 index 960339446d..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.xaml.cs +++ /dev/null @@ -1,306 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using System.Text; -using System.Windows.Controls; -using System.Windows.Input; -using System.Windows.Media; -using Debugger; -using Debugger.AddIn.TreeModel; -using ICSharpCode.Core; -using ICSharpCode.SharpDevelop.Gui.Pads; -using ICSharpCode.SharpDevelop.Services; - -namespace ICSharpCode.SharpDevelop.Gui.Pads -{ - /// - /// Interaction logic for CallStackPadContent.xaml - /// - public partial class CallStackPadContent : UserControl - { - CallStackPad callStackPad; - Process debuggedProcess; - - public CallStackPadContent(CallStackPad pad) - { - this.callStackPad = pad; - InitializeComponent(); - - view.ContextMenu = CreateMenu(); - - ((GridView)view.View).Columns[0].Width = DebuggingOptions.Instance.ShowModuleNames ? 100d : 0d; - ((GridView)view.View).Columns[2].Width = DebuggingOptions.Instance.ShowLineNumbers ? 50d : 0d; - } - - ContextMenu CreateMenu() - { - MenuItem extMethodsItem = new MenuItem(); - extMethodsItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ShowExternalMethods"); - extMethodsItem.IsChecked = DebuggingOptions.Instance.ShowExternalMethods; - extMethodsItem.Click += delegate { - extMethodsItem.IsChecked = DebuggingOptions.Instance.ShowExternalMethods = !DebuggingOptions.Instance.ShowExternalMethods; - callStackPad.InvalidatePad(); - }; - - MenuItem moduleItem = new MenuItem(); - moduleItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ShowModuleNames"); - moduleItem.IsChecked = DebuggingOptions.Instance.ShowModuleNames; - moduleItem.Click += delegate { - moduleItem.IsChecked = DebuggingOptions.Instance.ShowModuleNames = !DebuggingOptions.Instance.ShowModuleNames; - ((GridView)view.View).Columns[0].Width = DebuggingOptions.Instance.ShowModuleNames ? 100d : 0d; - callStackPad.InvalidatePad(); - }; - - MenuItem argNamesItem = new MenuItem(); - argNamesItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ShowArgumentNames"); - argNamesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentNames; - argNamesItem.Click += delegate { - argNamesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentNames = !DebuggingOptions.Instance.ShowArgumentNames; - callStackPad.InvalidatePad(); - }; - - MenuItem argValuesItem = new MenuItem(); - argValuesItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ShowArgumentValues"); - argValuesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentValues; - argValuesItem.Click += delegate { - argValuesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentValues = !DebuggingOptions.Instance.ShowArgumentValues; - callStackPad.InvalidatePad(); - }; - - MenuItem lineItem = new MenuItem(); - lineItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ShowLineNumber"); - lineItem.IsChecked = DebuggingOptions.Instance.ShowLineNumbers; - lineItem.Click += delegate { - lineItem.IsChecked = DebuggingOptions.Instance.ShowLineNumbers = !DebuggingOptions.Instance.ShowLineNumbers; - ((GridView)view.View).Columns[2].Width = DebuggingOptions.Instance.ShowLineNumbers ? 50d : 0d; - callStackPad.InvalidatePad(); - }; - - return new ContextMenu() { - Items = { - extMethodsItem, - new Separator(), - moduleItem, - argNamesItem, - argValuesItem, - lineItem - } - }; - } - - public void SelectProcess(Process process) - { - if (debuggedProcess != null) { - debuggedProcess.Paused -= debuggedProcess_Paused; - } - debuggedProcess = process; - if (debuggedProcess != null) { - debuggedProcess.Paused += debuggedProcess_Paused; - } - callStackPad.InvalidatePad(); - } - - void debuggedProcess_Paused(object sender, ProcessEventArgs e) - { - callStackPad.InvalidatePad(); - } - - void View_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) - { - if (debuggedProcess == null) - return; - if (debuggedProcess.IsPaused) { - CallStackItem item = view.SelectedItem as CallStackItem; - - if (item == null) - return; - - if (item.Frame != null && debuggedProcess.SelectedThread != null) { - // check for options - if these options are enabled, selecting the frame should not continue - if (!item.Frame.HasSymbols && !debuggedProcess.Options.DecompileCodeWithoutSymbols) { - MessageService.ShowMessage("${res:MainWindow.Windows.Debug.CallStack.CannotSwitchWithoutSymbolsOrDecompiledCodeOptions}", - "${res:MainWindow.Windows.Debug.CallStack.FunctionSwitch}"); - return; - } - debuggedProcess.SelectedThread.SelectedStackFrame = item.Frame; - debuggedProcess.PauseSession.PausedReason = PausedReason.CurrentFunctionChanged; - debuggedProcess.OnPaused(); // Force refresh of pads - artificial pause - } - } else { - MessageService.ShowMessage("${res:MainWindow.Windows.Debug.CallStack.CannotSwitchWhileRunning}", "${res:MainWindow.Windows.Debug.CallStack.FunctionSwitch}"); - } - } - - void View_KeyDown(object sender, KeyEventArgs e) - { - if (e.Key == Key.Enter) { - View_MouseLeftButtonUp(sender, null); - e.Handled = true; - } - } - - internal void RefreshPad() - { - if (debuggedProcess == null || debuggedProcess.IsRunning || debuggedProcess.SelectedThread == null) { - view.ItemsSource = null; - return; - } - - var items = new ObservableCollection(); - using(new PrintTimes("Callstack refresh")) { - bool showExternalMethods = DebuggingOptions.Instance.ShowExternalMethods; - bool previousItemIsExternalMethod = false; - - debuggedProcess.EnqueueForEach( - Dispatcher, - debuggedProcess.SelectedThread.GetCallstack(100), - f => items.AddIfNotNull(CreateItem(f, showExternalMethods, ref previousItemIsExternalMethod)) - ); - } - view.ItemsSource = items; - } - - CallStackItem CreateItem(StackFrame frame, bool showExternalMethods, ref bool previousItemIsExternalMethod) - { - CallStackItem item; - - // line number - string lineNumber = string.Empty; - if (DebuggingOptions.Instance.ShowLineNumbers) { - if (frame.NextStatement != null) - lineNumber = frame.NextStatement.StartLine.ToString(); - } - - // show modules names - string moduleName = string.Empty; - if (DebuggingOptions.Instance.ShowModuleNames) { - moduleName = frame.MethodInfo.DebugModule.ToString(); - } - - if (frame.HasSymbols || showExternalMethods) { - // Show the method in the list - - item = new CallStackItem() { - Name = GetFullName(frame), Language = "", Line = lineNumber, ModuleName = moduleName - }; - previousItemIsExternalMethod = false; - item.Frame = frame; - } else { - // Show [External methods] in the list - if (previousItemIsExternalMethod) return null; - item = new CallStackItem() { - Name = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ExternalMethods"), - Language = "" - }; - previousItemIsExternalMethod = true; - } - - return item; - } - - internal static string GetFullName(StackFrame frame) - { - bool showArgumentNames = DebuggingOptions.Instance.ShowArgumentNames; - bool showArgumentValues = DebuggingOptions.Instance.ShowArgumentValues; - bool showLineNumber = DebuggingOptions.Instance.ShowLineNumbers; - bool showModuleNames = DebuggingOptions.Instance.ShowModuleNames; - - StringBuilder name = new StringBuilder(); - name.Append(frame.MethodInfo.DeclaringType.FullName); - name.Append('.'); - name.Append(frame.MethodInfo.Name); - if (showArgumentNames || showArgumentValues) { - name.Append("("); - for (int i = 0; i < frame.ArgumentCount; i++) { - string parameterName = null; - string argValue = null; - if (showArgumentNames) { - try { - parameterName = frame.MethodInfo.GetParameters()[i].Name; - } catch { } - if (parameterName == "") parameterName = null; - } - if (showArgumentValues) { - try { - argValue = frame.GetArgumentValue(i).AsString(100); - } catch { } - } - if (parameterName != null && argValue != null) { - name.Append(parameterName); - name.Append("="); - name.Append(argValue); - } - if (parameterName != null && argValue == null) { - name.Append(parameterName); - } - if (parameterName == null && argValue != null) { - name.Append(argValue); - } - if (parameterName == null && argValue == null) { - name.Append(ResourceService.GetString("Global.NA")); - } - if (i < frame.ArgumentCount - 1) { - name.Append(", "); - } - } - name.Append(")"); - } - - return name.ToString(); - } - } - - public class CallStackItem - { - public string Name { get; set; } - public string Language { get; set; } - public StackFrame Frame { get; set; } - public string Line { get; set; } - public string ModuleName { get; set; } - - public Brush FontColor { - get { return Frame == null || Frame.HasSymbols ? Brushes.Black : Brushes.Gray; } - } - } - - public class CallStackPad : DebuggerPad - { - CallStackPadContent callStackList; - - static CallStackPad instance; - - public static CallStackPad Instance { - get { return instance; } - } - - public CallStackPad() - { - instance = this; - } - - public override object Control { - get { - return callStackList; - } - } - - protected override void InitializeComponents() - { - callStackList = new CallStackPadContent(this); - } - - protected override void SelectProcess(Process process) - { - callStackList.SelectProcess(process); - } - - protected override void RefreshPad() - { - callStackList.RefreshPad(); - } - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/MemoryPadCommands.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/MemoryPadCommands.cs deleted file mode 100644 index c234d50292..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/MemoryPadCommands.cs +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) -using System; -using System.Windows.Controls; -using System.Windows.Input; - -using ICSharpCode.Core; - -namespace ICSharpCode.SharpDevelop.Gui.Pads -{ - public sealed class JumpToAddressCommand : AbstractComboBoxCommand - { - MemoryPad pad; - ComboBox comboBox; - - protected override void OnOwnerChanged(EventArgs e) - { - this.pad = this.Owner as MemoryPad; - if (this.pad == null) - return; - - comboBox = this.ComboBox as ComboBox; - - if (this.comboBox == null) - return; - - comboBox.KeyUp += (s, ea) => { if (ea.Key == Key.Enter) Run(); }; - comboBox.IsEditable = true; - comboBox.Width = 130; - - base.OnOwnerChanged(e); - } - - public override void Run() - { - if (this.pad != null && this.comboBox != null) { - pad.JumpToAddress(comboBox.Text); - } - base.Run(); - } - } - - public abstract class ItemMemoryCommand : AbstractCommand - { - protected MemoryPad pad; - - protected override void OnOwnerChanged(EventArgs e) - { - this.pad = this.Owner as MemoryPad; - if (this.pad == null) - return; - - base.OnOwnerChanged(e); - } - } - - public sealed class RefreshAddressCommand : ItemMemoryCommand - { - public override void Run() - { - if (this.pad == null) - return; - - this.pad.Refresh(); - } - } - - public sealed class NextAddressCommand : ItemMemoryCommand - { - public override void Run() - { - if (this.pad == null) - return; - - this.pad.MoveToNextAddress(); - } - } - - public sealed class PreviousAddressCommand : ItemMemoryCommand - { - public override void Run() - { - if (this.pad == null) - return; - - this.pad.MoveToPreviousAddress(); - } - } - - public sealed class DisplayByteSizeCommand : AbstractComboBoxCommand - { - MemoryPad pad; - ComboBox comboBox; - - protected override void OnOwnerChanged(EventArgs e) - { - this.pad = this.Owner as MemoryPad; - if (this.pad == null) - return; - - comboBox = this.ComboBox as ComboBox; - - if (this.comboBox == null) - return; - - comboBox.SelectionChanged += (s, ea) => { Run(); }; - - comboBox.Items.Add(1); - comboBox.Items.Add(2); - comboBox.Items.Add(4); - comboBox.Text = "1"; - comboBox.Width = 30; - comboBox.IsEditable = false; - - base.OnOwnerChanged(e); - } - - public override void Run() - { - if (this.pad != null && this.comboBox != null) { - pad.DisplayByteSize = Convert.ToByte(this.comboBox.SelectedValue); - pad.DisplayMemory(); - } - base.Run(); - } - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs index 051113efa6..14ff79c339 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs @@ -2,20 +2,15 @@ // This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) using System; -using System.Collections.Generic; using System.Linq; -using System.Windows.Forms; - using Debugger.AddIn.Pads; using Debugger.AddIn.Pads.Controls; using Debugger.AddIn.TreeModel; using ICSharpCode.Core; -using ICSharpCode.Core.Presentation; using ICSharpCode.Core.WinForms; -using ICSharpCode.NRefactory; -using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Gui.Pads; using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.SharpDevelop.Services; namespace Debugger.AddIn { @@ -25,24 +20,9 @@ namespace Debugger.AddIn { if (this.Owner is WatchPad) { WatchPad pad = (WatchPad)this.Owner; - - var inputWindow = new WatchInputBox(StringParser.Parse("${res:MainWindow.Windows.Debug.Watch.AddWatch}"), - StringParser.Parse("${res:MainWindow.Windows.Debug.Watch.EnterExpression}")); - inputWindow.Owner = ICSharpCode.SharpDevelop.Gui.WorkbenchSingleton.MainWindow; - if (inputWindow.ShowDialog() != true) - return; - - string input = inputWindow.CommandText; - - if (!string.IsNullOrEmpty(input)) { - var text = new TextNode(null, input, inputWindow.ScriptLanguage).ToSharpTreeNode(); - var list = pad.WatchList; - - if(!list.WatchItems.Any(n => text.Node.FullName == ((TreeNodeWrapper)n).Node.FullName)) - list.WatchItems.Add(text); - } - - pad.InvalidatePad(); + var node = new TreeNode(string.Empty, null).ToSharpTreeNode(); + pad.Items.Add(node); + pad.Tree.FocusNode(node); } } } @@ -53,24 +33,8 @@ namespace Debugger.AddIn { if (this.Owner is WatchPad) { WatchPad pad = (WatchPad)this.Owner; - var list = pad.WatchList; - var node = list.SelectedNode; - - if (node == null) - return; - - list.WatchItems.Remove(node); - ((WatchPad)this.Owner).InvalidatePad(); - } - } - } - - public class RefreshWatchesCommand : AbstractMenuCommand - { - public override void Run() - { - if (this.Owner is WatchPad) { - ((WatchPad)this.Owner).InvalidatePad(); + pad.Items.Remove(pad.Tree.SelectedItem as SharpTreeNodeAdapter); + WindowsDebugger.RefreshPads(); } } } @@ -81,86 +45,8 @@ namespace Debugger.AddIn { if (this.Owner is WatchPad) { WatchPad pad = (WatchPad)this.Owner; - var list = pad.WatchList; - list.WatchItems.Clear(); + pad.Items.Clear(); } } } - - public class CopyToClipboardCommand : AbstractMenuCommand - { - public override void Run() - { - if (this.Owner is WatchPad) { - WatchPad pad = (WatchPad)this.Owner; - var node = pad.WatchList.SelectedNode; - if (node != null && node.Node is ExpressionNode) { - string text = ((ExpressionNode)node.Node).FullText; - ClipboardWrapper.SetText(text); - } - } - } - } - - public class WatchScriptingLanguageMenuBuilder : ISubmenuBuilder, IMenuItemBuilder - { - public ToolStripItem[] BuildSubmenu(Codon codon, object owner) - { - List items = new List(); - - if (owner is WatchPad) { - WatchPad pad = (WatchPad)owner; - - if (pad.WatchList.SelectedNode == null) - return items.ToArray(); - - var node = pad.WatchList.SelectedNode.Node; - - while (node.Parent != null && node.Parent.Parent != null) - { - node = node.Parent; - } - - if (!(node is TextNode)) - return items.ToArray(); - - foreach (string item in SupportedLanguage.GetNames(typeof(SupportedLanguage))) { - items.Add(MakeItem(item, item, node as TextNode, (sender, e) => HandleItem(sender))); - } - } - - return items.ToArray(); - } - - ToolStripMenuItem MakeItem(string title, string name, TextNode tag, EventHandler onClick) - { - ToolStripMenuItem menuItem = new ToolStripMenuItem(StringParser.Parse(title)); - menuItem.Click += onClick; - menuItem.Name = name; - menuItem.Tag = tag; - - if (name == tag.Language.ToString()) - menuItem.Checked = true; - - return menuItem; - } - - - void HandleItem(object sender) - { - ToolStripMenuItem item = null; - if (sender is ToolStripMenuItem) - item = (ToolStripMenuItem)sender; - - if (item != null) { - TextNode node = (TextNode)item.Tag; - node.Language = (SupportedLanguage)SupportedLanguage.Parse(typeof(SupportedLanguage), item.Text); - } - } - - public System.Collections.ICollection BuildItems(Codon codon, object owner) - { - return BuildSubmenu(codon, owner).TranslateToWpf(); - } - } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Common/AutoCompleteTextBox.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Common/AutoCompleteTextBox.cs new file mode 100644 index 0000000000..3d88d0130f --- /dev/null +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/Common/AutoCompleteTextBox.cs @@ -0,0 +1,120 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) + +using System; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Threading; +using ICSharpCode.AvalonEdit; +using ICSharpCode.SharpDevelop; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Dom.NRefactoryResolver; +using ICSharpCode.SharpDevelop.Editor; +using ICSharpCode.SharpDevelop.Editor.CodeCompletion; +using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.SharpDevelop.Services; + +namespace Debugger.AddIn.Pads.Controls +{ + public class AutoCompleteTextBox : UserControl + { + TextEditor editor; + ITextEditor editorAdapter; + + public static readonly DependencyProperty TextProperty = + DependencyProperty.Register("Text", typeof(string), typeof(AutoCompleteTextBox), + new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, TextChanged)); + + public static readonly DependencyProperty IsEditableProperty = + DependencyProperty.Register("IsEditable", typeof(bool), typeof(AutoCompleteTextBox), + new FrameworkPropertyMetadata(true, IsEditableChanged)); + + public string Text { + get { return (string)GetValue(TextProperty); } + set { SetValue(TextProperty, value); } + } + + public bool IsEditable { + get { return (bool)GetValue(IsEditableProperty); } + set { SetValue(IsEditableProperty, value); } + } + + static void TextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ((AutoCompleteTextBox)d).editor.Text = (string)e.NewValue; + } + + static void IsEditableChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ((AutoCompleteTextBox)d).editor.IsReadOnly = !(bool)e.NewValue; + } + + public AutoCompleteTextBox() + { + object tmp; + this.editorAdapter = EditorControlService.CreateEditor(out tmp); + this.editor = (TextEditor)tmp; + + this.editor.Background = Brushes.Transparent; + this.editor.ShowLineNumbers = false; + this.editor.HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden; + this.editor.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden; + this.editor.TextArea.GotKeyboardFocus += delegate { + this.Background = Brushes.White; + }; + this.editor.TextArea.LostKeyboardFocus += delegate { + this.Background = Brushes.Transparent; + this.Text = this.editor.Text; + this.editor.Select(0, 0); + }; + this.editor.TextArea.PreviewKeyDown += editor_TextArea_PreviewKeyDown; + this.editor.TextArea.TextEntered += editor_TextArea_TextEntered; + + this.Content = this.editor; + } + + void editor_TextArea_PreviewKeyDown(object sender, KeyEventArgs e) + { + if (e.Key == Key.Return || e.Key == Key.Escape) { + if (e.Key == Key.Return) + this.Text = this.editor.Text; + + e.Handled = true; + } + } + + void editor_TextArea_TextEntered(object sender, TextCompositionEventArgs e) + { + StackFrame frame = WindowsDebugger.CurrentStackFrame; + if (e.Text == "." && frame != null) + ShowDotCompletion(frame, this.editor.Text); + } + + private void ShowDotCompletion(StackFrame frame, string currentText) + { + string language = ProjectService.CurrentProject == null ? "C#" : ProjectService.CurrentProject.Language; + NRefactoryResolver resolver = new NRefactoryResolver(LanguageProperties.GetLanguage(language)); + + var seg = frame.NextStatement; + + var expressionFinder = ParserService.GetExpressionFinder(seg.Filename); + var info = ParserService.GetParseInformation(seg.Filename); + + string text = ParserService.GetParseableFileContent(seg.Filename).Text; + + int currentOffset = this.editor.CaretOffset; + + var expr = expressionFinder.FindExpression(currentText, currentOffset); + + expr.Region = new DomRegion(seg.StartLine, seg.StartColumn, seg.EndLine, seg.EndColumn); + + var rr = resolver.Resolve(expr, info, text); + + if (rr != null) { + editorAdapter.ShowCompletionWindow(new DotCodeCompletionItemProvider().GenerateCompletionListForResolveResult(rr, expr.Context)); + } + } + } +} \ No newline at end of file diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Common/CommonResources.xaml b/src/AddIns/Debugger/Debugger.AddIn/Pads/Common/CommonResources.xaml new file mode 100644 index 0000000000..f124ab42f0 --- /dev/null +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/Common/CommonResources.xaml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs index cf257d6b6e..8d9e919511 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs @@ -45,34 +45,27 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads string Evaluate(string code) { - if (process == null) { + Process process = WindowsDebugger.CurrentProcess; + StackFrame frame = WindowsDebugger.CurrentStackFrame; + + if (process == null) return "No process is being debugged"; - } - if (process.IsRunning) { + if (process.IsRunning) return "The process is running"; - } + if (frame == null) + return "No current execution frame"; + try { - var debugger = (WindowsDebugger)DebuggerService.CurrentDebugger; - StackFrame frame = debugger.DebuggedProcess.GetCurrentExecutingFrame(); - if (frame == null) return "No current execution frame"; - - object data = debugger.debuggerDecompilerService.GetLocalVariableIndex(frame.MethodInfo.DeclaringType.MetadataToken, + object data = ((WindowsDebugger)DebuggerService.CurrentDebugger).debuggerDecompilerService.GetLocalVariableIndex(frame.MethodInfo.DeclaringType.MetadataToken, frame.MethodInfo.MetadataToken, code); Value val = ExpressionEvaluator.Evaluate(code, SelectedLanguage, frame, data); - return ExpressionEvaluator.FormatValue(val); + return ExpressionEvaluator.FormatValue(WindowsDebugger.EvalThread, val); } catch (GetValueException e) { return e.Message; } } - Process process; - - public Process Process { - get { return process; } - set { process = value; } - } - protected override string Prompt { get { return "> "; @@ -102,35 +95,17 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads public ConsolePad() { WindowsDebugger debugger = (WindowsDebugger)DebuggerService.CurrentDebugger; - - debugger.ProcessSelected += delegate(object sender, ProcessEventArgs e) { - this.Process = e.Process; - }; - this.Process = debugger.DebuggedProcess; } protected override void AbstractConsolePadTextEntered(object sender, TextCompositionEventArgs e) { - if (this.process == null || this.process.IsRunning) - return; - - StackFrame frame = this.process.GetCurrentExecutingFrame(); - if (frame == null) - return; - - foreach (char ch in e.Text) { - if (ch == '.') { - ShowDotCompletion(console.CommandText); - } - } + StackFrame frame = WindowsDebugger.CurrentStackFrame; + if (e.Text == "." && frame != null) + ShowDotCompletion(frame, console.CommandText); } - void ShowDotCompletion(string currentText) + void ShowDotCompletion(StackFrame frame, string currentText) { - StackFrame frame = this.process.GetCurrentExecutingFrame(); - if (frame == null) - return; - var seg = frame.NextStatement; if (seg == null) return; diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/ConditionCell.xaml b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/ConditionCell.xaml deleted file mode 100644 index 20ab0bae89..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/ConditionCell.xaml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/ConditionCell.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/ConditionCell.xaml.cs deleted file mode 100644 index eb8e1b2066..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/ConditionCell.xaml.cs +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using System; -using System.IO; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Input; - -using ICSharpCode.AvalonEdit; -using ICSharpCode.Core; -using ICSharpCode.Core.Presentation; -using ICSharpCode.NRefactory; -using ICSharpCode.SharpDevelop; -using ICSharpCode.SharpDevelop.Bookmarks.Pad.Controls; -using ICSharpCode.SharpDevelop.Debugging; -using ICSharpCode.SharpDevelop.Dom; -using ICSharpCode.SharpDevelop.Dom.NRefactoryResolver; -using ICSharpCode.SharpDevelop.Editor; -using ICSharpCode.SharpDevelop.Editor.CodeCompletion; -using ICSharpCode.SharpDevelop.Gui; -using ICSharpCode.SharpDevelop.Project; - -namespace Debugger.AddIn.Pads.Controls -{ - public partial class ConditionCell : UserControl - { - private string language; - - protected ConsoleControl console; - - public static readonly DependencyProperty CommandTextProperty = - DependencyProperty.Register("CommandText", typeof(string), typeof(ConditionCell), - new UIPropertyMetadata(null, new PropertyChangedCallback(OnCommandTextChanged))); - - private NRefactoryResolver resolver; - - public ConditionCell() - { - InitializeComponent(); - - console = new ConsoleControl(); - console.TextAreaTextEntered += new TextCompositionEventHandler(consoleControl_TextAreaTextEntered); - console.TextAreaPreviewKeyDown += new KeyEventHandler(console_TextAreaPreviewKeyDown); - console.LostFocus += new RoutedEventHandler(console_LostFocus); - console.HideScrollBar(); - ConsolePanel.Content = console; - - // get language - if (ProjectService.CurrentProject == null) - language = "C#"; - else - language = ProjectService.CurrentProject.Language; - resolver = new NRefactoryResolver(LanguageProperties.GetLanguage(language)); - - // FIXME set language - if (language == "VB" || language == "VBNet") { - console.SetHighlighting("VBNET"); - } - else { - console.SetHighlighting("C#"); - } - } - - /// - /// Gets/sets the command text displayed at the command prompt. - /// - public string CommandText { - get { return console.CommandText.Trim(); } - set { console.CommandText = value; } - } - - private BreakpointBookmark Breakpoint { - get { - var model = Model; - return model.Mark as BreakpointBookmark; - } - } - - private ListViewPadItemModel Model { - get { return Tag as ListViewPadItemModel; } - } - - private ITextEditor TextEditor { - get { - return console.TextEditor; - } - } - - private void console_TextAreaPreviewKeyDown(object sender, KeyEventArgs e) - { - if (e.Key == Key.Return || e.Key == Key.Escape) { - - if (e.Key == Key.Escape) - CommandText = string.Empty; - else { - if(!CheckSyntax()) - return; - } - - UpdateBreakpoint(); - - e.Handled = true; - } - } - - private void console_LostFocus(object sender, RoutedEventArgs e) - { - if (string.IsNullOrEmpty(CommandText) || !this.CheckSyntax()) - return; - - UpdateBreakpoint(); - } - - private void UpdateBreakpoint() - { - Breakpoint.Condition = CommandText; - Model.Condition = CommandText; - Breakpoint.ScriptLanguage = language; - Model.Language = language; - - if (!string.IsNullOrEmpty(console.CommandText)) { - Breakpoint.Action = BreakpointAction.Condition; - if (Breakpoint.IsEnabled) - Model.Image = BreakpointBookmark.BreakpointConditionalImage.ImageSource; - } - else { - Breakpoint.Action = BreakpointAction.Break; - if (Breakpoint.IsEnabled) - Model.Image = BreakpointBookmark.BreakpointImage.ImageSource; - } - } - - private bool CheckSyntax() - { - string command = CommandText; - if (string.IsNullOrEmpty(command)) - return true; - - // FIXME workaround the NRefactory issue that needs a ; at the end - if (language == "C#") { - if(!command.EndsWith(";")) - command += ";"; - // FIXME only one string should be available; highlighting expects C#, supproted language, CSharp - language = "CSharp"; - } - - SupportedLanguage supportedLanguage = (SupportedLanguage)Enum.Parse(typeof(SupportedLanguage), language.ToString(), true); - using (var parser = ParserFactory.CreateParser(supportedLanguage, new StringReader(TextEditor.Document.Text))) { - parser.ParseExpression(); - if (parser.Errors.Count > 0) { - MessageService.ShowError(parser.Errors.ErrorOutput); - return false; - } - } - - return true; - } - - private void consoleControl_TextAreaTextEntered(object sender, TextCompositionEventArgs e) - { - foreach (char ch in e.Text) { - if (ch == '.') { - ShowDotCompletion(console.CommandText); - } - } - } - - private void ShowDotCompletion(string currentText) - { - var seg = Breakpoint; - - var expressionFinder = ParserService.GetExpressionFinder(seg.FileName.ToString()); - var info = ParserService.GetParseInformation(seg.FileName.ToString()); - - string text = ParserService.GetParseableFileContent(seg.FileName.ToString()).Text; - - int currentOffset = TextEditor.Caret.Offset - console.CommandOffset - 1; - - var expr = expressionFinder.FindExpression(currentText, currentOffset); - - expr.Region = new DomRegion(seg.LineNumber, seg.ColumnNumber, seg.LineNumber, seg.ColumnNumber); - - var rr = resolver.Resolve(expr, info, text); - - if (rr != null) { - TextEditor.ShowCompletionWindow(new DotCodeCompletionItemProvider().GenerateCompletionListForResolveResult(rr, expr.Context)); - } - } - - private static void OnCommandTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - var cell = d as ConditionCell; - cell.CommandText = e.NewValue.ToString(); - } - } -} \ No newline at end of file diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/Converters.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/Converters.cs deleted file mode 100644 index 2283a4cca2..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/Converters.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using System; -using System.Globalization; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Media; - -namespace Debugger.AddIn.Pads.Controls -{ - public class BoolToVisibilityConverter : IMultiValueConverter - { - public object Convert(object[] values, Type targetType, - object parameter, CultureInfo culture) - { - bool val = bool.Parse(parameter.ToString()); - return val == (bool.Parse(values[0].ToString()) && bool.Parse(values[1].ToString())) ? Visibility.Visible : Visibility.Collapsed; - } - - public object[] ConvertBack(object value, Type[] targetTypes, - object parameter, CultureInfo culture) - { - throw new NotImplementedException(); - } - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml deleted file mode 100644 index f31b220086..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml.cs deleted file mode 100644 index 2809cb6adf..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml.cs +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Input; -using Debugger.AddIn.TreeModel; -using ICSharpCode.Core.Presentation; -using ICSharpCode.SharpDevelop.Gui; -using ICSharpCode.SharpDevelop.Gui.Pads; -using ICSharpCode.TreeView; - -namespace Debugger.AddIn.Pads.Controls -{ - public enum WatchListType - { - LocalVar, - Watch - } - - public partial class WatchList : UserControl - { - public WatchList(WatchListType type) - { - InitializeComponent(); - WatchType = type; - if (type == WatchListType.Watch) - myList.Root = new WatchRootNode(); - else - myList.Root = new SharpTreeNode(); - } - - public WatchListType WatchType { get; private set; } - - public SharpTreeNodeCollection WatchItems { - get { return myList.Root.Children; } - } - - public TreeNodeWrapper SelectedNode { - get { return myList.SelectedItem as TreeNodeWrapper; } - } - - void OnValueTextBoxKeyUp(object sender, KeyEventArgs e) - { - if (e.Key != Key.Enter && e.Key != Key.Escape) { - e.Handled = true; - return; - } - - if (e.Key == Key.Enter) { - if(SelectedNode.Node is ExpressionNode) { - var node = (ExpressionNode)SelectedNode.Node; - node.SetText(((TextBox)sender).Text); - } - } - if (e.Key == Key.Enter || e.Key == Key.Escape) { - myList.UnselectAll(); - if (LocalVarPad.Instance != null) - LocalVarPad.Instance.InvalidatePad(); - if (WatchPad.Instance != null) - WatchPad.Instance.InvalidatePad(); - } - } - - void WatchListAutoCompleteCellCommandEntered(object sender, EventArgs e) - { - var selectedNode = SelectedNode; - if (selectedNode == null) return; - if (WatchType != WatchListType.Watch) return; - - var cell = ((WatchListAutoCompleteCell)sender); - - selectedNode.Node.Name = cell.CommandText; - myList.UnselectAll(); - if (WatchType == WatchListType.Watch && WatchPad.Instance != null) { - WatchPad.Instance.InvalidatePad(); - } - selectedNode.IsEditing = false; - } - - void MyListPreviewMouseDoubleClick(object sender, MouseButtonEventArgs e) - { - if (SelectedNode == null) return; - if (WatchType != WatchListType.Watch) - return; - SelectedNode.IsEditing = true; - } - } -} \ No newline at end of file diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchListAutoCompleteCell.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchListAutoCompleteCell.cs deleted file mode 100644 index 4cf639972f..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchListAutoCompleteCell.cs +++ /dev/null @@ -1,175 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using System; -using System.IO; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Input; - -using ICSharpCode.AvalonEdit; -using ICSharpCode.Core; -using ICSharpCode.NRefactory; -using ICSharpCode.SharpDevelop; -using ICSharpCode.SharpDevelop.Debugging; -using ICSharpCode.SharpDevelop.Dom; -using ICSharpCode.SharpDevelop.Dom.NRefactoryResolver; -using ICSharpCode.SharpDevelop.Editor; -using ICSharpCode.SharpDevelop.Editor.CodeCompletion; -using ICSharpCode.SharpDevelop.Gui; -using ICSharpCode.SharpDevelop.Gui.Pads; -using ICSharpCode.SharpDevelop.Project; -using ICSharpCode.SharpDevelop.Services; - -namespace Debugger.AddIn.Pads.Controls -{ - public partial class WatchListAutoCompleteCell : UserControl - { - string language; - - protected ConsoleControl console; - - public static readonly DependencyProperty CommandTextProperty = - DependencyProperty.Register("CommandText", typeof(string), typeof(WatchListAutoCompleteCell), - new UIPropertyMetadata(null, new PropertyChangedCallback(OnCommandTextChanged))); - - NRefactoryResolver resolver; - - public event EventHandler CommandEntered; - - public WatchListAutoCompleteCell() - { - InitializeComponent(); - - console = new ConsoleControl(); - console.TextAreaTextEntered += new TextCompositionEventHandler(consoleControl_TextAreaTextEntered); - console.TextAreaPreviewKeyDown += new KeyEventHandler(console_TextAreaPreviewKeyDown); - console.LostFocus += new RoutedEventHandler(console_LostFocus); - console.HideScrollBar(); - ConsolePanel.Content = console; - - // get language - if (ProjectService.CurrentProject == null) - language = "C#"; - else - language = ProjectService.CurrentProject.Language; - resolver = new NRefactoryResolver(LanguageProperties.GetLanguage(language)); - - // FIXME set language - if (language == "VB" || language == "VBNet") { - console.SetHighlighting("VBNET"); - } - else { - console.SetHighlighting("C#"); - } - - // get process - WindowsDebugger debugger = (WindowsDebugger)DebuggerService.CurrentDebugger; - - debugger.ProcessSelected += delegate(object sender, ProcessEventArgs e) { - this.Process = e.Process; - }; - this.Process = debugger.DebuggedProcess; - } - - Process Process { get; set; } - - /// - /// Gets/sets the command text displayed at the command prompt. - /// - public string CommandText { - get { return console.CommandText.Trim(); } - set { console.CommandText = value; } - } - - ITextEditor TextEditor { - get { - return console.TextEditor; - } - } - - void console_TextAreaPreviewKeyDown(object sender, KeyEventArgs e) - { - if (e.Key == Key.Return || e.Key == Key.Escape) { - - if (e.Key == Key.Escape) - CommandText = string.Empty; - else { - if(!CheckSyntax()) - return; - } - - if (CommandEntered != null) - CommandEntered(this, EventArgs.Empty); - - e.Handled = true; - } - } - - void console_LostFocus(object sender, RoutedEventArgs e) - { - if (string.IsNullOrEmpty(CommandText) || !this.CheckSyntax()) - return; - - if (CommandEntered != null) - CommandEntered(this, EventArgs.Empty); - } - - bool CheckSyntax() - { - string command = CommandText; - - // FIXME workaround the NRefactory issue that needs a ; at the end - if (language == "C#" || language == "CSharp") { - if (!command.EndsWith(";")) - command += ";"; - // FIXME only one string should be available; highlighting expects C#, supported language, CSharp - language = "CSharp"; - } - - SupportedLanguage supportedLanguage = (SupportedLanguage)Enum.Parse(typeof(SupportedLanguage), language.ToString(), true); - using (var parser = ParserFactory.CreateParser(supportedLanguage, new StringReader(command))) { - parser.ParseExpression(); - if (parser.Errors.Count > 0) { - MessageService.ShowError(parser.Errors.ErrorOutput); - return false; - } - } - - return true; - } - - void consoleControl_TextAreaTextEntered(object sender, TextCompositionEventArgs e) - { - foreach (char ch in e.Text) { - if (ch == '.') { - ShowDotCompletion(console.CommandText); - } - } - } - - void ShowDotCompletion(string currentText) - { - var seg = Process.SelectedStackFrame.NextStatement; - var expressionFinder = ParserService.GetExpressionFinder(seg.Filename); - var info = ParserService.GetParseInformation(seg.Filename); - string text = ParserService.GetParseableFileContent(seg.Filename).Text; - int currentOffset = TextEditor.Caret.Offset - console.CommandOffset - 1; - var expr = expressionFinder.FindExpression(currentText, currentOffset); - expr.Region = new DomRegion(seg.StartLine, seg.StartColumn, seg.EndLine, seg.EndColumn); - var rr = resolver.Resolve(expr, info, text); - - if (rr != null) { - TextEditor.ShowCompletionWindow(new DotCodeCompletionItemProvider().GenerateCompletionListForResolveResult(rr, expr.Context)); - } - } - - static void OnCommandTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) - { - var cell = d as WatchListAutoCompleteCell; - if (cell != null && e.NewValue != null) { - cell.CommandText = e.NewValue.ToString(); - } - } - } -} \ No newline at end of file diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchListAutoCompleteCell.xaml b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchListAutoCompleteCell.xaml deleted file mode 100644 index 6148d1da83..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchListAutoCompleteCell.xaml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerPad.cs deleted file mode 100644 index 9e712e5176..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerPad.cs +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) - -using System.Windows.Controls; -using Debugger; -using ICSharpCode.SharpDevelop.Debugging; -using ICSharpCode.SharpDevelop.Services; - -namespace ICSharpCode.SharpDevelop.Gui.Pads -{ - public abstract class DebuggerPad : AbstractPadContent - { - protected DockPanel panel; - ToolBar toolbar; - protected WindowsDebugger debugger; - - public override object Control { - get { - return panel; - } - } - - public DebuggerPad() - { - // UI - this.panel = new DockPanel(); - this.toolbar = BuildToolBar(); - - if (this.toolbar != null) { - this.toolbar.SetValue(DockPanel.DockProperty, Dock.Top); - - this.panel.Children.Add(toolbar); - } - - // logic - debugger = (WindowsDebugger)DebuggerService.CurrentDebugger; - - InitializeComponents(); - - debugger.ProcessSelected += delegate(object sender, ProcessEventArgs e) { - SelectProcess(e.Process); - }; - SelectProcess(debugger.DebuggedProcess); - } - - protected virtual void InitializeComponents() - { - - } - - protected virtual void SelectProcess(Process process) - { - - } - - /// - /// Never call this directly. Always use InvalidatePad() - /// - protected virtual void RefreshPad() - { - - } - - bool invalidatePadEnqueued; - - public void InvalidatePad() - { - WorkbenchSingleton.AssertMainThread(); - if (invalidatePadEnqueued || WorkbenchSingleton.Workbench == null) - return; - invalidatePadEnqueued = true; - WorkbenchSingleton.SafeThreadAsyncCall( - delegate { - invalidatePadEnqueued = false; - RefreshPad(); - }); - - } - - protected virtual ToolBar BuildToolBar() - { - return null; - } - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs index b2d39e5b5f..279841c1d9 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs @@ -2,6 +2,7 @@ // This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) using System; +using System.Collections.Generic; using System.Collections.ObjectModel; using System.Dynamic; using System.Windows; @@ -11,107 +12,64 @@ using Debugger; using Debugger.AddIn.Pads.Controls; using Debugger.AddIn.Pads.ParallelPad; using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Services; namespace ICSharpCode.SharpDevelop.Gui.Pads { - public class LoadedModulesPad : DebuggerPad + public class LoadedModulesPad : AbstractPadContent { - ListView loadedModulesList; - Process debuggedProcess; - ObservableCollection loadedModules; + ListView listView; - protected override void InitializeComponents() - { - loadedModulesList = new ListView(); - loadedModules = new ObservableCollection(); - loadedModulesList.ItemsSource = loadedModules; - loadedModulesList.View = new GridView(); - panel.Children.Add(loadedModulesList); - RedrawContent(); - ResourceService.LanguageChanged += delegate { RedrawContent(); }; - } - - public void RedrawContent() - { - loadedModulesList.ClearColumns(); - loadedModulesList.AddColumn(StringParser.Parse("${res:Global.Name}"), - new Binding { Path = new PropertyPath("Name") }, 250); - loadedModulesList.AddColumn(StringParser.Parse("${res:MainWindow.Windows.Debug.Modules.AddressColumn}"), - new Binding { Path = new PropertyPath("Address") }, 100); - loadedModulesList.AddColumn(StringParser.Parse("${res:Global.Path}"), - new Binding { Path = new PropertyPath("Path") }, 250); - loadedModulesList.AddColumn(StringParser.Parse("${res:MainWindow.Windows.Debug.Modules.OrderColumn}"), - new Binding { Path = new PropertyPath("Order") }, 80); - loadedModulesList.AddColumn(StringParser.Parse("${res:MainWindow.Windows.Debug.Modules.SymbolsColumn}"), - new Binding { Path = new PropertyPath("Symbols") }, 130); - } - - protected override void SelectProcess(Process process) - { - if (debuggedProcess != null) { - debuggedProcess.Modules.Added -= debuggedProcess_ModuleLoaded; - debuggedProcess.Modules.Removed -= debuggedProcess_ModuleUnloaded; - } - debuggedProcess = process; - if (debuggedProcess != null) { - debuggedProcess.Modules.Added += debuggedProcess_ModuleLoaded; - debuggedProcess.Modules.Removed += debuggedProcess_ModuleUnloaded; - } - InvalidatePad(); - } - - void debuggedProcess_ModuleLoaded(object sender, CollectionItemEventArgs e) - { - AddModule(e.Item); + public override object Control { + get { return listView; } } - void debuggedProcess_ModuleUnloaded(object sender, CollectionItemEventArgs e) + public LoadedModulesPad() { - RemoveModule(e.Item); + var res = new CommonResources(); + res.InitializeComponent(); + + listView = new ListView(); + listView.View = (GridView)res["loadedModulesGridView"]; + + WindowsDebugger.RefreshingPads += RefreshPad; + RefreshPad(); } - protected override void RefreshPad() + void RefreshPad() { - loadedModules.Clear(); - if (debuggedProcess != null) { - foreach(Module module in debuggedProcess.Modules) { - AddModule(module); + Process process = WindowsDebugger.CurrentProcess; + List loadedModules = new List(); + if (process != null) { + foreach(Module module in process.Modules) { + loadedModules.Add(new ModuleItem(module)); } } - } - - void AddModule(Module module) - { - loadedModules.Add(new ModuleModel(module)); - } - - void RemoveModule(Module module) - { - loadedModules.RemoveWhere(model => model.Module == module); + listView.ItemsSource = loadedModules; } } - static class ListViewExtensions + public class ModuleItem { - public static void ClearColumns(this ListView view) - { - if (view == null) - throw new ArgumentNullException("view"); - if (view.View is GridView) - ((GridView)view.View).Columns.Clear(); - } + public string Name { get; private set; } + public string Address { get; private set; } + public string Path { get; private set; } + public string Order { get; private set; } + public string Symbols { get; private set; } - public static void AddColumn(this ListView view, string header, Binding binding, double width) + public ModuleItem(Module module) { - if (view == null) - throw new ArgumentNullException("view"); - if (view.View is GridView) { - GridViewColumn column = new GridViewColumn { - Width = width, - DisplayMemberBinding = binding, - Header = header }; - ((GridView)view.View).Columns.Add(column); + this.Name = module.Name; + this.Address = string.Format("{0:X8}", module.BaseAdress); + if (module.IsDynamic) { + this.Path = StringParser.Parse("${res:MainWindow.Windows.Debug.Modules.DynamicModule}"); + } else if (module.IsInMemory) { + this.Path = StringParser.Parse("${res:MainWindow.Windows.Debug.Modules.InMemoryModule}"); + } else { + this.Path = module.FullPath; } + this.Order = module.OrderOfLoading.ToString(); + this.Symbols = module.HasSymbols ? StringParser.Parse("${res:MainWindow.Windows.Debug.Modules.HasSymbols}") : StringParser.Parse("${res:MainWindow.Windows.Debug.Modules.HasNoSymbols}"); } } } \ No newline at end of file diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs index 3b870d7418..cdc918cf61 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs @@ -1,85 +1,55 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) -using System.Collections.ObjectModel; using System.Linq; +using System.Windows.Controls; using System.Windows.Threading; using Debugger; -using Debugger.AddIn.Pads.Controls; using Debugger.AddIn.TreeModel; -using ICSharpCode.Core; -using Exception = System.Exception; -using TreeNode = Debugger.AddIn.TreeModel.TreeNode; +using ICSharpCode.SharpDevelop.Services; +using ICSharpCode.TreeView; namespace ICSharpCode.SharpDevelop.Gui.Pads { - public class LocalVarPad : DebuggerPad + public class LocalVarPad : AbstractPadContent { - WatchList localVarList; - Process debuggedProcess; - static LocalVarPad instance; + SharpTreeView tree; - public LocalVarPad() - { - instance = this; - } - - /// Always check if Instance is null, might be null if pad is not opened! - public static LocalVarPad Instance { - get { return instance; } - } - - public Process Process { - get { return debuggedProcess; } - } - - protected override void InitializeComponents() - { - localVarList = new WatchList(WatchListType.LocalVar); - panel.Children.Add(localVarList); + public override object Control { + get { return tree; } } - protected override void SelectProcess(Process process) - { - if (debuggedProcess != null) { - debuggedProcess.Paused -= debuggedProcess_Paused; - } - debuggedProcess = process; - if (debuggedProcess != null) { - debuggedProcess.Paused += debuggedProcess_Paused; - } - InvalidatePad(); + SharpTreeNodeCollection Items { + get { return tree.Root.Children; } } - void debuggedProcess_Paused(object sender, ProcessEventArgs e) + public LocalVarPad() { - InvalidatePad(); + var res = new CommonResources(); + res.InitializeComponent(); + + this.tree = new SharpTreeView(); + this.tree.Root = new SharpTreeNode(); + this.tree.ShowRoot = false; + this.tree.View = (GridView)res["variableGridView"]; + + WindowsDebugger.RefreshingPads += RefreshPad; + RefreshPad(); } - protected override void RefreshPad() + void RefreshPad() { - if (debuggedProcess == null || debuggedProcess.IsRunning) { - localVarList.WatchItems.Clear(); - return; - } + StackFrame frame = WindowsDebugger.CurrentStackFrame; - LoggingService.Info("Local Variables refresh"); - try { - StackFrame frame = debuggedProcess.GetCurrentExecutingFrame(); - localVarList.WatchItems.Clear(); - if (frame == null) return; - - debuggedProcess.EnqueueForEach( + if (frame == null) { + this.Items.Clear(); + } else { + this.Items.Clear(); + frame.Process.EnqueueForEach( Dispatcher.CurrentDispatcher, - new StackFrameNode(frame).ChildNodes.ToList(), - n => localVarList.WatchItems.Add(n.ToSharpTreeNode()) + ValueNode.GetLocalVariables().ToList(), + n => this.Items.Add(n.ToSharpTreeNode()) ); - } catch (Exception ex) { - if (debuggedProcess == null || debuggedProcess.HasExited) { - // Process unexpectedly exited - } else { - MessageService.ShowException(ex); - } } } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/MemoryPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/MemoryPad.cs deleted file mode 100644 index afae24227e..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/MemoryPad.cs +++ /dev/null @@ -1,331 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Globalization; -using System.Text; -using System.Text.RegularExpressions; -using System.Windows.Controls; - -using Debugger; -using Debugger.Interop; -using ICSharpCode.Core; -using ICSharpCode.Core.Presentation; -using ICSharpCode.SharpDevelop.Debugging; - -namespace ICSharpCode.SharpDevelop.Gui.Pads -{ - public sealed class MemoryPad : DebuggerPad - { - int currentAddressIndex; - ConsoleControl console; - int columnsNumber = 16; - byte displayByteSize = 1; - byte[] memory; - Process debuggedProcess; - List> memoryAddresses = new List>(); - Dictionary addressesMapping = new Dictionary(); - - /// - /// Gets or sets the number of columns in the display - /// - [DefaultValue(16)] - public int ColumnsNumber { - get { return columnsNumber; } - set { - if (value != columnsNumber) { - columnsNumber = value; - } - } - } - - /// - /// Gets or sets the display byte size: 1, 2, 4 - /// - [DefaultValue(1)] - public byte DisplayByteSize { - get { return displayByteSize; } - set { - // check is value is a power of 2 between 1 and 4. - if ((value & (value - 1)) != 0) - return; - if (value < 1 || value > 4) - return; - - if (displayByteSize != value) { - displayByteSize = value; - } - } - } - - public MemoryPad() - { - this.console = new ConsoleControl(); - this.panel.Children.Add(console); - this.console.Encoding = Encoding.Default; - RefreshPad(); // exception - this.console.SetReadonly(); - - DebuggerService.DebugStopped += DebuggerService_DebugStopped; - } - - void DebuggerService_DebugStopped(object sender, EventArgs e) - { - memoryAddresses.Clear(); - addressesMapping.Clear(); - memory = null; - } - - protected override ToolBar BuildToolBar() - { - return ToolBarService.CreateToolBar(panel, this, "/SharpDevelop/Pads/MemoryPad/ToolBar"); - } - - protected override void SelectProcess(Process process) - { - if (process == null) - return; - - debuggedProcess = process; - memoryAddresses = debuggedProcess.GetVirtualMemoryAddresses(); - currentAddressIndex = 0; - } - - public void JumpToAddress(string address) - { - try { - if (address.StartsWith("0x")) - address = address.Substring(2); - - long addr = Int64.Parse(address, NumberStyles.AllowHexSpecifier); - - memoryAddresses = debuggedProcess.GetVirtualMemoryAddresses(); - // find index for the address or the near addess - currentAddressIndex = memoryAddresses.BinarySearch(addr); - if (currentAddressIndex == -1) { - MessageService.ShowMessage( - string.Format(ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.AddressNotFound"), address), - ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad")); - - currentAddressIndex = 0; - return; - } - - // refresh pad - if (!Refresh()) - return; - - // find line - long mod = addr % (columnsNumber * displayByteSize); - int line; - long key = addr - mod; - //int index = addressesMapping.BinarySearch(key); - if (addressesMapping.ContainsKey(key)) - line = addressesMapping[key]; - else - line = 1; - - // jump - console.SelectText(line, 0, 8); - console.JumpToLine(line); - - } catch (System.Exception ex) { - LoggingService.Error(ex.Message); - } - } - - public bool Refresh(bool refreshMemoryAddresses = false) - { - if (console == null) - return false; - - console.Clear(); - if (debuggedProcess == null || debugger.IsProcessRunning) { - console.Append(ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.NotDebuggingOrProcessRunning")); - return false; - } - - if (currentAddressIndex <= -1) { - console.Append(ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.NoMappings")); - currentAddressIndex = -1; - return false; - } - - if (refreshMemoryAddresses) - memoryAddresses = debuggedProcess.GetVirtualMemoryAddresses(); - - if (memoryAddresses.Count == 0) { - console.Append(ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.NoMappings")); - return false; - } - - if (currentAddressIndex >= memoryAddresses.Count) { - console.Append(ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.NoMappings")); - currentAddressIndex = memoryAddresses.Count ; - return false; - } - - RetrieveMemory(); - return true; - } - - void RetrieveMemory() - { - // refresh data - addressesMapping.Clear(); - - // get current address - var item = memoryAddresses[currentAddressIndex]; - long address = item.Item1; - long size = item.Item2; - - memory = debuggedProcess.ReadProcessMemory(address, size); - if (memory == null) { - console.Append(string.Format(ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.UnableToReadFormat"), address.ToString("X8"), size)); - return; - } - - DisplayMemory(); - } - - public void DisplayMemory() - { - if (memory == null || memory.Length == 0) - return; - - if (console == null) - return; - - console.Clear(); - addressesMapping.Clear(); - var item = memoryAddresses[currentAddressIndex]; - long address = item.Item1; - - int totalBytesPerRow = columnsNumber * displayByteSize; - int numberOfLines = memory.Length / totalBytesPerRow; - int remainingMemory = memory.Length % totalBytesPerRow; - int currentLine = 2;// line in the console - int index = 0;// index in memory arrray of current line - - StringBuilder sb = new StringBuilder(); - sb.Append(string.Format(ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.ReadingFromFormat"), address.ToString("X8"), (address + memory.Length).ToString("X8"), memory.Length)); - sb.Append(Environment.NewLine); - - while (index < numberOfLines) { - addressesMapping.Add(address, currentLine); - // write address - sb.Append(address.ToString("X8")); - address += (long)totalBytesPerRow; - sb.Append(" "); - - // write bytes - int start = index * totalBytesPerRow; - for (int i = 0; i < columnsNumber; ++i) { - for (int j = 0; j < displayByteSize; ++j) { - sb.Append(memory[start++].ToString("X2")); - } - sb.Append(" "); - } - - // write chars - start = index * totalBytesPerRow; - StringBuilder sb1 = new StringBuilder(); - for (int i = 0; i < totalBytesPerRow; ++i) { - sb1.Append(((char)memory[start++]).ToString()); - } - string s = sb1.ToString(); - s = Regex.Replace(s, "\\r\\n", string.Empty); - s = Regex.Replace(s, "\\n", string.Empty); - s = Regex.Replace(s, "\\r", string.Empty); - sb.Append(s); - sb.Append(Environment.NewLine); - currentLine++; - index++; - } - - // write the rest of memory - if (remainingMemory != 0) { - addressesMapping.Add(address, currentLine); - // write address - sb.Append(address.ToString("X8")); - sb.Append(" "); - - // write bytes - int start = index * remainingMemory * displayByteSize; - for (int i = 0; i < remainingMemory; ++i) { - for (int j = 0; j < displayByteSize; j++) { - sb.Append(memory[start++].ToString("X2")); - } - sb.Append(" "); - } - - // write chars - start = index * remainingMemory * displayByteSize; - StringBuilder sb1 = new StringBuilder(); - for (int i = 0; i < remainingMemory * displayByteSize; ++i) { - sb1.Append(((char)memory[start++]).ToString()); - } - string s = sb1.ToString(); - s = Regex.Replace(s, "\\r\\n", string.Empty); - s = Regex.Replace(s, "\\n", string.Empty); - s = Regex.Replace(s, "\\r", string.Empty); - sb.Append(s); - } - - console.Append(sb.ToString()); - } - - public void MoveToPreviousAddress() - { - currentAddressIndex--; - Refresh(); - } - - public void MoveToNextAddress() - { - currentAddressIndex++; - Refresh(); - } - } - - internal static class MemoryPadExtensions - { - /// - /// Does a binary search when the Item1 from Tuple is sorted. - /// - /// Source of data. - /// Item to search. - /// The nearest index. - internal static int BinarySearch(this List> source, long item1) - { - // base checks - if (source == null) - throw new NullReferenceException("Source is null!"); - - if (source.Count == 0) - return -1; - - if (item1 < source[0].Item1) - return 0; - - if (item1 > source[source.Count - 1].Item1) - return source.Count; - - // do a binary search since the source is sorted - int first = 0; int last = source.Count; - while (first < last - 1) { - int middle = (first + last) / 2; - if (source[middle].Item1 == item1) - return middle; - else - if (source[middle].Item1 < item1) - first = middle; - else - last = middle; - } - - return first; - } - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs deleted file mode 100644 index 1617201833..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) - -using ICSharpCode.Core; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Windows; -using Debugger; -using Debugger.AddIn.Visualizers.Graph; - -namespace ICSharpCode.SharpDevelop.Gui.Pads -{ - /// - /// Description of ObjectGraphPad. - /// - public class ObjectGraphPad : DebuggerPad - { - Process debuggedProcess; - ObjectGraphControl objectGraphControl; - static ObjectGraphPad instance; - - public ObjectGraphPad() - { - instance = this; - } - - /// Always check if Instance is null, might be null if pad is not opened! - public static ObjectGraphPad Instance { - get { return instance; } - } - - protected override void InitializeComponents() - { - objectGraphControl = new ObjectGraphControl(); - panel.Children.Add(objectGraphControl); - } - - - protected override void RefreshPad() - { - // BUG: if pad window is undocked and floats standalone, IsVisible == false (so pad won't refresh) - // REQUEST: need to refresh when pad becomes visible -> VisibleChanged event? - if (!objectGraphControl.IsVisible) - { - return; - } - if (debuggedProcess == null || debuggedProcess.IsRunning || debuggedProcess.SelectedStackFrame == null) { - this.objectGraphControl.Clear(); - return; - } - this.objectGraphControl.RefreshView(); - } - - protected override void SelectProcess(Process process) - { - if (debuggedProcess != null) { - debuggedProcess.Paused -= debuggedProcess_Paused; - } - debuggedProcess = process; - if (debuggedProcess != null) { - debuggedProcess.Paused += debuggedProcess_Paused; - } - InvalidatePad(); - } - - void debuggedProcess_Paused(object sender, ProcessEventArgs e) - { - InvalidatePad(); - } - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackFrameModel.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackFrameModel.cs index fa8fe1eaab..e829345310 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackFrameModel.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackFrameModel.cs @@ -63,118 +63,4 @@ namespace Debugger.AddIn.Pads.ParallelPad } } } - - public class ThreadModel : ViewModelBase - { - Thread thread; - - public ThreadModel(Thread thread) - { - if (thread == null) - throw new ArgumentNullException("thread"); - this.thread = thread; - thread.NameChanged += delegate { RaisePropertyChanged(() => Name); }; - } - - public Thread Thread { - get { return thread; } - } - - public uint ID { - get { return thread.ID; } - } - - public string Name { - get { return thread.Name; } - } - - public string Priority { - get { - switch (thread.Priority) { - case System.Threading.ThreadPriority.Highest: - return ResourceService.GetString("MainWindow.Windows.Debug.Threads.Priority.Highest"); - case System.Threading.ThreadPriority.AboveNormal: - return ResourceService.GetString("MainWindow.Windows.Debug.Threads.Priority.AboveNormal"); - case System.Threading.ThreadPriority.Normal: - return ResourceService.GetString("MainWindow.Windows.Debug.Threads.Priority.Normal"); - case System.Threading.ThreadPriority.BelowNormal: - return ResourceService.GetString("MainWindow.Windows.Debug.Threads.Priority.BelowNormal"); - case System.Threading.ThreadPriority.Lowest: - return ResourceService.GetString("MainWindow.Windows.Debug.Threads.Priority.Lowest"); - default: - return thread.Priority.ToString(); - } - } - } - - public string Location { - get { - if (thread.Process.IsPaused && thread.MostRecentStackFrame != null) - return thread.MostRecentStackFrame.MethodInfo.Name; - return ResourceService.GetString("Global.NA"); - } - } - - public string Frozen { - get { - return ResourceService.GetString(thread.Suspended ? "Global.Yes" : "Global.No"); - } - } - } - - public class ModuleModel : ViewModelBase - { - Module module; - - public ModuleModel(Module module) - { - if (module == null) - throw new ArgumentNullException("module"); - this.module = module; - this.module.SymbolsUpdated += delegate { - RaisePropertyChanged(() => Name); - RaisePropertyChanged(() => Address); - RaisePropertyChanged(() => Path); - RaisePropertyChanged(() => Order); - RaisePropertyChanged(() => Symbols); - }; - } - - public Module Module { - get { return module; } - } - - public string Name { - get { return module.Name; } - } - - public string Address { - get { return string.Format("{0:X8}", module.BaseAdress); } - } - - public string Path { - get { - if (module.IsDynamic) - return StringParser.Parse("${res:MainWindow.Windows.Debug.Modules.DynamicModule}"); - if (module.IsInMemory) - return StringParser.Parse("${res:MainWindow.Windows.Debug.Modules.InMemoryModule}"); - - return module.FullPath; - } - } - - public string Order { - get { - return module.OrderOfLoading.ToString(); - } - } - - public string Symbols { - get { - if (module.HasSymbols) - return StringParser.Parse("${res:MainWindow.Windows.Debug.Modules.HasSymbols}"); - return StringParser.Parse("${res:MainWindow.Windows.Debug.Modules.HasNoSymbols}"); - } - } - } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs index 8feecd7c33..579fc17aa4 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs @@ -20,6 +20,7 @@ using ICSharpCode.SharpDevelop.Bookmarks; using ICSharpCode.SharpDevelop.Debugging; using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Gui.Pads; +using ICSharpCode.SharpDevelop.Services; namespace ICSharpCode.SharpDevelop.Gui.Pads { @@ -29,43 +30,45 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads Tasks } - public class ParallelStackPad : DebuggerPad + public class ParallelStackPad : AbstractPadContent { + DockPanel panel; + ToolBar toolbar; + DrawSurface surface; - Process debuggedProcess; ParallelStacksGraph graph; List currentThreadStacks = new List(); ParallelStacksView parallelStacksView; StackFrame selectedFrame; bool isMethodView; + public override object Control { + get { return panel; } + } + #region Overrides - protected override void InitializeComponents() + public ParallelStackPad() { + this.panel = new DockPanel(); + this.toolbar = ToolBarService.CreateToolBar(panel, this, "/SharpDevelop/Pads/ParallelStacksPad/ToolBar"); + this.toolbar.SetValue(DockPanel.DockProperty, Dock.Top); + this.panel.Children.Add(toolbar); + surface = new DrawSurface(); panel.Children.Add(surface); - } - - protected override void SelectProcess(Process process) - { - if (debuggedProcess != null) { - debuggedProcess.Paused -= OnProcessPaused; - } - debuggedProcess = process; - if (debuggedProcess != null) { - debuggedProcess.Paused += OnProcessPaused; - } - + + WindowsDebugger.RefreshingPads += RefreshPad; + RefreshPad(); DebuggerService.DebugStarted += OnReset; - DebuggerService.DebugStopped += OnReset; - - InvalidatePad(); + DebuggerService.DebugStopped += OnReset; } - protected override void RefreshPad() + protected void RefreshPad() { + Process debuggedProcess = WindowsDebugger.CurrentProcess; + if (debuggedProcess == null || debuggedProcess.IsRunning) { return; } @@ -95,12 +98,12 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads if (isMethodView) { // build method view for threads - CreateMethodViewStacks(); + CreateMethodViewStacks(debuggedProcess); } else { // normal view - CreateCommonStacks(); + CreateCommonStacks(debuggedProcess); } } @@ -119,11 +122,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads surface.SetGraph(graph); } } - - protected override ToolBar BuildToolBar() - { - return ToolBarService.CreateToolBar(panel, this, "/SharpDevelop/Pads/ParallelStacksPad/ToolBar"); - } #endregion @@ -133,7 +131,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads get { return parallelStacksView; } set { parallelStacksView = value; - InvalidatePad(); + WindowsDebugger.RefreshPads(); } } @@ -141,7 +139,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads get { return isMethodView; } set { isMethodView = value; - InvalidatePad(); + WindowsDebugger.RefreshPads(); } } @@ -163,11 +161,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads BookmarkManager.RemoveAll(b => b is SelectedFrameBookmark); } - void OnProcessPaused(object sender, ProcessEventArgs e) - { - InvalidatePad(); - } - void AddChildren(ThreadStack parent) { if(parent.ThreadStackChildren == null || parent.ThreadStackChildren.Count == 0) @@ -187,7 +180,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads } } - void CreateCommonStacks() + void CreateCommonStacks(Process debuggedProcess) { // stack.ItemCollection order // 0 -> top of stack = S.C @@ -311,7 +304,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads commonParent.Process = debuggedProcess; commonParent.StackSelected += OnThreadStackSelected; commonParent.FrameSelected += OnFrameSelected; - commonParent.IsSelected = commonParent.ThreadIds.Contains(debuggedProcess.SelectedThread.ID); + commonParent.IsSelected = commonParent.ThreadIds.Contains(WindowsDebugger.CurrentThread.ID); // add new children foreach (var stack in listOfCurrentStacks) { if (stack.ItemCollection.Count == 0) @@ -369,7 +362,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads } } - void CreateMethodViewStacks() + void CreateMethodViewStacks(Process debuggedProcess) { var list = new List, ObservableCollection, List>>(); @@ -439,6 +432,9 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads void CreateThreadStack(Thread thread) { + Process debuggedProcess = thread.Process; + Thread currentThread = WindowsDebugger.CurrentThread; + var items = CreateItems(thread); if (items == null || items.Count == 0) return; @@ -450,10 +446,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads threadStack.ItemCollection = items; threadStack.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, thread.ID); - if (debuggedProcess.SelectedThread != null) { - threadStack.IsSelected = threadStack.ThreadIds.Contains(debuggedProcess.SelectedThread.ID); + if (currentThread != null) { + threadStack.IsSelected = threadStack.ThreadIds.Contains(currentThread.ID); if (selectedFrame == null) - selectedFrame = debuggedProcess.SelectedStackFrame; + selectedFrame = WindowsDebugger.CurrentStackFrame; } currentThreadStacks.Add(threadStack); @@ -465,6 +461,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads int noTasks = 0; var result = new ObservableCollection(); var callstack = thread.GetCallstack(100); + Process debuggedProcess = thread.Process; if (parallelStacksView == ParallelStacksView.Threads) { foreach (StackFrame frame in callstack) { @@ -492,10 +489,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads threadStack.ItemCollection = result.Clone(); threadStack.UpdateThreadIds(true, frame.Thread.ID); - if (debuggedProcess.SelectedThread != null) { - threadStack.IsSelected = threadStack.ThreadIds.Contains(debuggedProcess.SelectedThread.ID); + if (WindowsDebugger.CurrentThread != null) { + threadStack.IsSelected = threadStack.ThreadIds.Contains(WindowsDebugger.CurrentThread.ID); if (selectedFrame == null) - selectedFrame = debuggedProcess.SelectedStackFrame; + selectedFrame = WindowsDebugger.CurrentStackFrame; } currentThreadStacks.Add(threadStack); @@ -535,10 +532,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads lastItemIsExternalMethod = true; } - if (frame.Thread.SelectedStackFrame != null && - frame.Thread.ID == debuggedProcess.SelectedThread.ID && - frame.Thread.SelectedStackFrame.IP == frame.IP && - frame.Thread.SelectedStackFrame.GetMethodName() == frame.GetMethodName()) { + if (frame.Thread.MostRecentStackFrame != null && + frame.Thread.ID == WindowsDebugger.CurrentThread.ID && + frame.Thread.MostRecentStackFrame.IP == frame.IP && + frame.Thread.MostRecentStackFrame.GetMethodName() == frame.GetMethodName()) { model.Image = PresentationResourceService.GetImage("Bookmarks.CurrentLine").Source; model.IsRunningStackFrame = true; } else { @@ -583,7 +580,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads ToggleSelectedFrameBookmark(e.Location); if (isMethodView) - InvalidatePad(); + WindowsDebugger.RefreshPads(); } #endregion diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs index 35d1dd92b8..345630cac6 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs @@ -5,15 +5,16 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Dynamic; +using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; - using ICSharpCode.Core.Presentation; using ICSharpCode.NRefactory; using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop.Gui.Pads; +using ICSharpCode.SharpDevelop.Services; namespace Debugger.AddIn.Pads.ParallelPad { @@ -183,7 +184,7 @@ namespace Debugger.AddIn.Pads.ParallelPad if (selectedItem == null) return; - var thread = Process.Threads.Find(t => t.ID == threadId); + var thread = Process.Threads.FirstOrDefault(t => t.ID == threadId); if (thread == null) return; @@ -233,7 +234,7 @@ namespace Debugger.AddIn.Pads.ParallelPad foreach (var id in ThreadIds) { MenuItem m = new MenuItem(); m.IsCheckable = true; - m.IsChecked = id == Process.SelectedThread.ID; + m.IsChecked = id == WindowsDebugger.CurrentThread.ID; m.Click += delegate(object sender, RoutedEventArgs e) { var menuItem = e.OriginalSource as MenuItem; SelectFrame((uint)menuItem.Tag, item); @@ -270,7 +271,7 @@ namespace Debugger.AddIn.Pads.ParallelPad if (selectedItem.MethodName == frame.GetMethodName()) { TextBlock tb = new TextBlock(); - tb.Text = thread.ID + ": " + CallStackPadContent.GetFullName(frame); + tb.Text = thread.ID + ": " + CallStackPad.GetFullName(frame); panel.Children.Add(tb); } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.Menu.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.Menu.cs deleted file mode 100644 index 5a5f60ab1f..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.Menu.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) - -using System.Collections; -using System.Dynamic; -using System.Linq; -using System.Windows; -using System.Windows.Controls; -using Debugger; -using Debugger.AddIn.Pads.ParallelPad; -using ICSharpCode.Core; - -namespace ICSharpCode.SharpDevelop.Gui.Pads -{ - public partial class RunningThreadsPad - { - ContextMenu CreateContextMenuStrip() - { - ContextMenu menu = new ContextMenu(); - menu.Opened += FillContextMenuStrip; - return menu; - } - - void FillContextMenuStrip(object sender, RoutedEventArgs e) - { - var items = runningThreadsList.SelectedItems; - if (items == null || items.Count == 0) { - e.Handled = true; - return; - } - - ThreadModel item = items[0] as ThreadModel; - if (item == null) - return; - - ContextMenu menu = sender as ContextMenu; - menu.Items.Clear(); - - MenuItem freezeItem; - freezeItem = new MenuItem(); - freezeItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.Threads.Freeze"); - freezeItem.IsChecked = item.Thread.Suspended; - freezeItem.Click += - delegate { - if (items == null || items.Count == 0) { - e.Handled = true; - return; - } - bool suspended = item.Thread.Suspended; - - if (!debuggedProcess.IsPaused) { - MessageService.ShowMessage("${res:MainWindow.Windows.Debug.Threads.CannotFreezeWhileRunning}", "${res:MainWindow.Windows.Debug.Threads.Freeze}"); - return; - } - - foreach(ThreadModel current in items.OfType()) { - current.Thread.Suspended = !suspended; - } - InvalidatePad(); - }; - - menu.Items.Add(freezeItem); - } - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs deleted file mode 100644 index 2f908ce001..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs +++ /dev/null @@ -1,154 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) - -using System; -using System.Collections.ObjectModel; -using System.Linq; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Threading; -using Debugger; -using Debugger.AddIn.Pads.Controls; -using Debugger.AddIn.Pads.ParallelPad; -using Debugger.AddIn.TreeModel; -using ICSharpCode.Core; -using ICSharpCode.SharpDevelop.Debugging; -using ICSharpCode.SharpDevelop.Services; -using Exception = System.Exception; -using Thread = Debugger.Thread; - -namespace ICSharpCode.SharpDevelop.Gui.Pads -{ - public partial class RunningThreadsPad : DebuggerPad - { - ListView runningThreadsList; - ObservableCollection runningThreads; - Process debuggedProcess; - - protected override void InitializeComponents() - { - runningThreads = new ObservableCollection(); - runningThreadsList = new ListView(); - runningThreadsList.ContextMenu = CreateContextMenuStrip(); - runningThreadsList.MouseDoubleClick += RunningThreadsListItemActivate; - runningThreadsList.ItemsSource = runningThreads; - runningThreadsList.View = new GridView(); - panel.Children.Add(runningThreadsList); - - RedrawContent(); - ResourceService.LanguageChanged += delegate { RedrawContent(); }; - } - - public void RedrawContent() - { - runningThreadsList.ClearColumns(); - runningThreadsList.AddColumn(ResourceService.GetString("Global.ID"), - new Binding { Path = new PropertyPath("ID") }, - 100); - runningThreadsList.AddColumn(ResourceService.GetString("Global.Name"), - new Binding { Path = new PropertyPath("Name") }, - 300); - runningThreadsList.AddColumn(ResourceService.GetString("AddIns.HtmlHelp2.Location"), - new Binding { Path = new PropertyPath("Location") }, - 250); - runningThreadsList.AddColumn(ResourceService.GetString("MainWindow.Windows.Debug.Threads.Priority"), - new Binding { Path = new PropertyPath("Priority") }, - 120); - runningThreadsList.AddColumn(ResourceService.GetString("MainWindow.Windows.Debug.Threads.Frozen"), - new Binding { Path = new PropertyPath("Frozen") }, - 80); - } - - protected override void SelectProcess(Process process) - { - if (debuggedProcess != null) { - debuggedProcess.Paused -= debuggedProcess_Paused; - debuggedProcess.Threads.Added -= debuggedProcess_ThreadStarted; - } - debuggedProcess = process; - if (debuggedProcess != null) { - debuggedProcess.Paused += debuggedProcess_Paused; - debuggedProcess.Threads.Added += debuggedProcess_ThreadStarted; - } - runningThreads.Clear(); - InvalidatePad(); - } - - void debuggedProcess_Paused(object sender, ProcessEventArgs e) - { - InvalidatePad(); - } - - void debuggedProcess_ThreadStarted(object sender, CollectionItemEventArgs e) - { - AddThread(e.Item); - } - - protected override void RefreshPad() - { - if (debuggedProcess == null || debuggedProcess.IsRunning) { - runningThreads.Clear(); - return; - } - - LoggingService.Info("Threads refresh"); - - debuggedProcess.EnqueueForEach( - Dispatcher.CurrentDispatcher, - debuggedProcess.Threads.ToList(), - t => AddThread(t) - ); - } - - void RunningThreadsListItemActivate(object sender, EventArgs e) - { - if (debuggedProcess != null) { - if (debuggedProcess.IsPaused) { - ThreadModel obj = runningThreadsList.SelectedItems[0] as ThreadModel; - Thread thread = obj.Thread; - - // check for options - if these options are enabled, selecting the frame should not continue - if ((thread.MostRecentStackFrame == null || !thread.MostRecentStackFrame.HasSymbols) && - !DebuggingOptions.Instance.DecompileCodeWithoutSymbols) { - MessageService.ShowMessage("${res:MainWindow.Windows.Debug.Threads.CannotSwitchWithoutDecompiledCodeOptions}", - "${res:MainWindow.Windows.Debug.Threads.ThreadSwitch}"); - return; - } - - debuggedProcess.SelectedThread = thread; - debuggedProcess.SelectedThread.SelectedStackFrame = debuggedProcess.SelectedThread.MostRecentStackFrame; - if (debuggedProcess.SelectedThread.SelectedStackFrame != null) { - debuggedProcess.PauseSession.PausedReason = PausedReason.CurrentThreadChanged; - debuggedProcess.OnPaused(); // Force refresh of pads - artificial pause - } else { - MessageService.ShowMessage("${res:MainWindow.Windows.Debug.Threads.CannotSwitchOnNAFrame}", "${res:MainWindow.Windows.Debug.Threads.ThreadSwitch}"); - } - } else { - MessageService.ShowMessage("${res:MainWindow.Windows.Debug.Threads.CannotSwitchWhileRunning}", "${res:MainWindow.Windows.Debug.Threads.ThreadSwitch}"); - } - } - } - - void AddThread(Thread thread) - { - if (thread == null) return; - - // remove the object if exists - RemoveThread(thread); - - ThreadModel obj = new ThreadModel(thread); - - runningThreads.Add(obj); - thread.Exited += (s, e) => RemoveThread(e.Thread); - } - - void RemoveThread(Thread thread) - { - if (thread == null) - return; - - runningThreads.RemoveWhere(model => model.Thread == thread); - } - } -} \ No newline at end of file diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/ThreadsPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ThreadsPad.cs new file mode 100644 index 0000000000..54817c9a99 --- /dev/null +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/ThreadsPad.cs @@ -0,0 +1,138 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; + +using Debugger; +using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Services; +using Thread = Debugger.Thread; + +namespace ICSharpCode.SharpDevelop.Gui.Pads +{ + public class ThreadsPad : AbstractPadContent + { + ListView listView; + + public override object Control { + get { return listView; } + } + + public ThreadsPad() + { + var res = new CommonResources(); + res.InitializeComponent(); + + ContextMenu contextMenu = new ContextMenu(); + contextMenu.Opened += FillContextMenuStrip; + + listView = new ListView(); + listView.View = (GridView)res["theadsGridView"]; + listView.ContextMenu = contextMenu; + listView.MouseDoubleClick += listView_MouseDoubleClick; + + WindowsDebugger.RefreshingPads += RefreshPad; + RefreshPad(); + } + + void RefreshPad() + { + Process process = WindowsDebugger.CurrentProcess; + + if (process == null || process.IsRunning) { + listView.ItemsSource = null; + } else { + List items = new List(); + foreach(var thread in process.Threads) { + items.Add(new ThreadItem(thread)); + } + listView.ItemsSource = items; + } + } + + void listView_MouseDoubleClick(object sender, MouseButtonEventArgs e) + { + ThreadItem item = listView.SelectedItem as ThreadItem; + + if (WindowsDebugger.CurrentProcess != null) { + if (WindowsDebugger.CurrentProcess.IsPaused) { + WindowsDebugger.CurrentThread = item.Thread; + WindowsDebugger.Instance.JumpToCurrentLine(); + WindowsDebugger.RefreshPads(); + } else { + MessageService.ShowMessage("${res:MainWindow.Windows.Debug.Threads.CannotSwitchWhileRunning}", "${res:MainWindow.Windows.Debug.Threads.ThreadSwitch}"); + } + } + } + + void FillContextMenuStrip(object sender, RoutedEventArgs e) + { + var items = listView.SelectedItems.OfType(); + // Suspended property is safe to access at any point + bool suspended = items.All(t => t.Thread.Suspended); + + ContextMenu menu = sender as ContextMenu; + menu.Items.Clear(); + + MenuItem freezeItem; + freezeItem = new MenuItem(); + freezeItem.Header = ResourceService.GetString("MainWindow.Windows.Debug.Threads.Freeze"); + freezeItem.IsChecked = suspended; + freezeItem.Click += delegate { + if (WindowsDebugger.CurrentProcess == null || WindowsDebugger.CurrentProcess.IsRunning) { + MessageService.ShowMessage("${res:MainWindow.Windows.Debug.Threads.CannotFreezeWhileRunning}", "${res:MainWindow.Windows.Debug.Threads.Freeze}"); + return; + } + foreach(ThreadItem item in items.OfType()) { + item.Thread.Suspended = !suspended; + } + WindowsDebugger.RefreshPads(); + }; + + menu.Items.Add(freezeItem); + } + } + + public class ThreadItem + { + public Thread Thread { get; private set; } + public uint ID { get; private set; } + public string Name { get; private set; } + public string Priority { get; private set; } + public string Frozen { get; private set; } + + public ThreadItem(Thread thread) + { + // We want to egarly evaluate the properties while the process is paused + // rather then wait until the GUI acesses them at some unspecified point + this.Thread = thread; + this.ID = thread.ID; + this.Name = thread.Name; + this.Priority = PriorityToString(thread.Priority); + this.Frozen = ResourceService.GetString(thread.Suspended ? "Global.Yes" : "Global.No"); + } + + static string PriorityToString(System.Threading.ThreadPriority priority) + { + switch (priority) { + case System.Threading.ThreadPriority.Highest: + return ResourceService.GetString("MainWindow.Windows.Debug.Threads.Priority.Highest"); + case System.Threading.ThreadPriority.AboveNormal: + return ResourceService.GetString("MainWindow.Windows.Debug.Threads.Priority.AboveNormal"); + case System.Threading.ThreadPriority.Normal: + return ResourceService.GetString("MainWindow.Windows.Debug.Threads.Priority.Normal"); + case System.Threading.ThreadPriority.BelowNormal: + return ResourceService.GetString("MainWindow.Windows.Debug.Threads.Priority.BelowNormal"); + case System.Threading.ThreadPriority.Lowest: + return ResourceService.GetString("MainWindow.Windows.Debug.Threads.Priority.Lowest"); + default: + return ResourceService.GetString("Global.NA"); + } + } + } +} \ No newline at end of file diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchInputBox.xaml b/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchInputBox.xaml deleted file mode 100644 index 96473894e2..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchInputBox.xaml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - Layout: + Layout: Zoom: diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraphControl.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraphControl.xaml.cs index 074b42de3f..33ffe9d9b0 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraphControl.xaml.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraphControl.xaml.cs @@ -62,7 +62,7 @@ namespace Debugger.AddIn.Visualizers.Graph public void RefreshView() { - debuggerService.DebuggedProcess.EnqueueWork(Dispatcher, () => Refresh()); + WindowsDebugger.CurrentProcess.EnqueueWork(Dispatcher, () => Refresh()); } void Refresh() @@ -78,7 +78,7 @@ namespace Debugger.AddIn.Visualizers.Graph } bool isSuccess = true; try { - this.objectGraph = RebuildGraph(txtExpression.Text); + this.objectGraph = RebuildGraph(); } catch(DebuggerVisualizerException ex) { isSuccess = false; ErrorMessage(ex.Message); @@ -94,8 +94,8 @@ namespace Debugger.AddIn.Visualizers.Graph } } - private ICSharpCode.NRefactory.Ast.Expression shownExpression; - public ICSharpCode.NRefactory.Ast.Expression ShownExpression + private GraphExpression shownExpression; + public GraphExpression ShownExpression { get { return shownExpression; @@ -107,23 +107,17 @@ namespace Debugger.AddIn.Visualizers.Graph RefreshView(); return; } - if (shownExpression == null || value.PrettyPrint() != shownExpression.PrettyPrint()) { - txtExpression.Text = value.PrettyPrint(); + if (shownExpression == null || value.Expr.PrettyPrint() != shownExpression.Expr.PrettyPrint()) { + txtExpression.Text = value.Expr.PrettyPrint(); RefreshView(); } } } - private void Inspect_Button_Click(object sender, RoutedEventArgs e) - { - RefreshView(); - } - - ObjectGraph RebuildGraph(string expression) + ObjectGraph RebuildGraph() { this.objectGraphBuilder = new ObjectGraphBuilder(debuggerService); - Log.Debug("Debugger visualizer: Building graph for expression: " + txtExpression.Text); - return this.objectGraphBuilder.BuildGraphForExpression(expression, expanded.Expressions); + return this.objectGraphBuilder.BuildGraphForExpression(this.ShownExpression, expanded.Expressions); } void LayoutGraph(ObjectGraph graph) @@ -185,7 +179,7 @@ namespace Debugger.AddIn.Visualizers.Graph void node_PropertyExpanded(object sender, PositionedPropertyEventArgs e) { // remember this property is expanded (for later graph rebuilds) - expanded.Expressions.SetExpanded(e.Property.Expression); + expanded.Expressions.SetExpanded(e.Property.Expression.Expr); // add edge (+ possibly nodes) to underlying object graph (no need to fully rebuild) e.Property.ObjectGraphProperty.TargetNode = this.objectGraphBuilder.ObtainNodeForExpression(e.Property.Expression); @@ -195,7 +189,7 @@ namespace Debugger.AddIn.Visualizers.Graph void node_PropertyCollapsed(object sender, PositionedPropertyEventArgs e) { // remember this property is collapsed (for later graph rebuilds) - expanded.Expressions.SetCollapsed(e.Property.Expression); + expanded.Expressions.SetCollapsed(e.Property.Expression.Expr); // just remove edge from underlying object graph (no need to fully rebuild) e.Property.ObjectGraphProperty.TargetNode = null; diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraphWindow.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraphWindow.xaml.cs index eb4056d1a9..0bccfe5dcf 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraphWindow.xaml.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraphWindow.xaml.cs @@ -42,7 +42,7 @@ namespace Debugger.AddIn.Visualizers.Graph ObjectGraphWindow.Instance = null; // allow release } - public ICSharpCode.NRefactory.Ast.Expression ShownExpression + public GraphExpression ShownExpression { get { return this.objectGraphControl.ShownExpression; } set { this.objectGraphControl.ShownExpression = value; } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml index 664da36dd7..954552e85d 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml @@ -27,9 +27,6 @@ - Expression: - - diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs index 80703cd997..db8f1eabdd 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs @@ -2,25 +2,15 @@ // This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; using System.Reflection; -using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; -using Debugger.AddIn.TreeModel; using Debugger.AddIn.Visualizers.PresentationBindings; using Debugger.AddIn.Visualizers.Utils; using Debugger.MetaData; using ICSharpCode.Core; -using ICSharpCode.NRefactory.Ast; using ICSharpCode.SharpDevelop; -using ICSharpCode.SharpDevelop.Debugging; using ICSharpCode.SharpDevelop.Services; namespace Debugger.AddIn.Visualizers.GridVisualizer @@ -30,160 +20,94 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer /// public partial class GridVisualizerWindow : Window { - WindowsDebugger debuggerService; - GridViewColumnHider columnHider; + Func getValue; - public GridVisualizerWindow() + public GridVisualizerWindow(string valueName, Func getValue) { InitializeComponent(); - this.debuggerService = DebuggerService.CurrentDebugger as WindowsDebugger; - if (debuggerService == null) - throw new ApplicationException("Only windows debugger is currently supported"); + this.Title = valueName; + this.getValue = getValue; - instance = this; - this.Deactivated += GridVisualizerWindow_Deactivated; - } - - void GridVisualizerWindow_Deactivated(object sender, EventArgs e) - { - this.Close(); - } - - private ICSharpCode.NRefactory.Ast.Expression shownExpression; - public ICSharpCode.NRefactory.Ast.Expression ShownExpression - { - get { - return shownExpression; - } - set { - if (value == null) { - shownExpression = null; - txtExpression.Text = null; - - Refresh(); - return; - } - if (shownExpression == null || value.PrettyPrint() != shownExpression.PrettyPrint()) { - txtExpression.Text = value.PrettyPrint(); - Refresh(); - } - } - } - - static GridVisualizerWindow instance; - /// When Window is visible, returns reference to the Window. Otherwise returns null. - public static GridVisualizerWindow Instance - { - get { return instance; } - } - - public static GridVisualizerWindow EnsureShown() - { - var window = GridVisualizerWindow.Instance ?? new GridVisualizerWindow(); - window.Topmost = true; - window.Show(); - return window; - } - - protected override void OnClosing(System.ComponentModel.CancelEventArgs e) - { - this.Deactivated -= GridVisualizerWindow_Deactivated; - base.OnClosing(e); - } - - protected override void OnClosed(EventArgs e) - { - base.OnClosed(e); - instance = null; - } - - private void btnInspect_Click(object sender, RoutedEventArgs e) - { Refresh(); } - + public void Refresh() { - try { + try { // clear ListView listView.ItemsSource = null; - ScrollViewer listViewScroller = listView.GetScrollViewer(); - if (listViewScroller != null) { - listViewScroller.ScrollToVerticalOffset(0); - } - Value shownValue = null; - ICSharpCode.NRefactory.Ast.Expression shownExpr = null; - try { - shownExpr = debuggerService.GetExpression(txtExpression.Text); - shownValue = shownExpr.Evaluate(debuggerService.DebuggedProcess); - } catch(GetValueException e) { - MessageService.ShowMessage(e.Message); - } - if (shownValue != null && !shownValue.IsNull) { - GridValuesProvider gridValuesProvider; - // Value is IList - DebugType iListType, listItemType; - if (shownValue.Type.ResolveIListImplementation(out iListType, out listItemType)) { - gridValuesProvider = CreateListValuesProvider(shownExpr.CastToIList(), listItemType); + + Value shownValue = getValue(); + + DebugType iListType, iEnumerableType, itemType; + // Value is IList + if (shownValue.Type.ResolveIListImplementation(out iListType, out itemType)) { + // Ok + } else { + // Value is IEnumerable + if (shownValue.Type.ResolveIEnumerableImplementation(out iEnumerableType, out itemType)) { + shownValue = DebuggerHelpers.CreateListFromIEnumerable(shownValue); + iListType = DebugType.CreateFromType(shownValue.AppDomain, typeof(System.Collections.Generic.IList<>), itemType); } else { - // Value is IEnumerable - DebugType iEnumerableType, itemType; - if (shownValue.Type.ResolveIEnumerableImplementation(out iEnumerableType, out itemType)) { - DebugType debugListType; - var debugListExpression = DebuggerHelpers.CreateDebugListExpression(shownExpr, itemType, out debugListType); - gridValuesProvider = CreateListValuesProvider(debugListExpression, itemType); - } else { - // Not IList or IEnumerable - can't be displayed in GridVisualizer - return; - } + // Not IList or IEnumerable - can't be displayed in GridVisualizer + return; } - - IList itemTypeMembers = gridValuesProvider.GetItemTypeMembers(); - InitializeColumns((GridView)this.listView.View, itemTypeMembers); - this.columnHider = new GridViewColumnHider((GridView)this.listView.View); - cmbColumns.ItemsSource = this.columnHider.HideableColumns; } - } catch (GetValueException e) { - MessageService.ShowMessage(e.Message); - } catch (DebuggerVisualizerException e) { + shownValue = shownValue.GetPermanentReference(WindowsDebugger.EvalThread); + + MemberInfo[] members = itemType.GetFieldsAndNonIndexedProperties(BindingFlags.Public | BindingFlags.Instance); + PropertyInfo itemGetter = iListType.GetProperty("Item"); + int rowCount = (int)shownValue.GetPropertyValue(WindowsDebugger.EvalThread, iListType.GetProperty("Count")).PrimitiveValue; + int columnCount = members.Length + 1; + + var rowCollection = new VirtualizingCollection>( + rowCount, + (rowIndex) => new VirtualizingCollection( + columnCount, + (columnIndex) => { + if (columnIndex == members.Length) + return "[" + rowIndex + "]"; + try { + var rowValue = shownValue.GetPropertyValue(WindowsDebugger.EvalThread, itemGetter, Eval.CreateValue(WindowsDebugger.EvalThread, rowIndex)); + return rowValue.GetMemberValue(WindowsDebugger.EvalThread, members[columnIndex]).InvokeToString(WindowsDebugger.EvalThread); + } catch (GetValueException e) { + return "Exception: " + e.Message; + } + } + ) + ); + this.listView.ItemsSource = rowCollection; + + InitializeColumns((GridView)this.listView.View, members); + + GridViewColumnHider columnHider = new GridViewColumnHider((GridView)this.listView.View); + cmbColumns.ItemsSource = columnHider.HideableColumns; + + } catch(GetValueException e) { MessageService.ShowMessage(e.Message); } } - ListValuesProvider CreateListValuesProvider(ICSharpCode.NRefactory.Ast.Expression targetExpression, DebugType listItemType) - { - var listValuesProvider = new ListValuesProvider(targetExpression, listItemType); - var virtCollection = new VirtualizingCollection(listValuesProvider); - this.listView.ItemsSource = virtCollection; - return listValuesProvider; - } - - void InitializeColumns(GridView gridView, IList itemTypeMembers) + void InitializeColumns(GridView gridView, MemberInfo[] members) { gridView.Columns.Clear(); - AddIndexColumn(gridView); - AddMembersColumns(gridView, itemTypeMembers); - } - - void AddIndexColumn(GridView gridView) - { + + // Index column var indexColumn = new GridViewHideableColumn(); indexColumn.CanBeHidden = false; indexColumn.Width = 36; indexColumn.Header = string.Empty; - indexColumn.DisplayMemberBinding = new Binding("Index"); + indexColumn.DisplayMemberBinding = new Binding("[" + members.Length + "]"); gridView.Columns.Add(indexColumn); - } - - void AddMembersColumns(GridView gridView, IList itemTypeMembers) - { - foreach (var member in itemTypeMembers) { + + // Member columns + for (int i = 0; i < members.Length; i++) { var memberColumn = new GridViewHideableColumn(); memberColumn.CanBeHidden = true; - memberColumn.Header = member.Name; - // "{Binding Path=[Name].Value}" - memberColumn.DisplayMemberBinding = new Binding("[" + member.Name + "].Value"); + memberColumn.Header = members[i].Name; + memberColumn.IsVisibleDefault = ((IDebugMemberInfo)members[i]).IsPublic; + memberColumn.DisplayMemberBinding = new Binding("[" + i + "]"); gridView.Columns.Add(memberColumn); } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ObjectValue.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ObjectValue.cs deleted file mode 100644 index 6663528bca..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ObjectValue.cs +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) - -using System; -using System.Collections.Generic; -using Debugger.AddIn.Visualizers.Utils; -using Debugger.MetaData; -using ICSharpCode.NRefactory.Ast; -using ICSharpCode.SharpDevelop.Services; -using System.Reflection; - -namespace Debugger.AddIn.Visualizers.GridVisualizer -{ - /// - /// Item of a collection in the debugee, with lazy evaluated properties. - /// - public class ObjectValue - { - /// Index of this item in the collection. - public int Index { get; private set; } - - // PermanentReference for one row. - public Value PermanentReference { get; private set; } - - private Dictionary properties = new Dictionary(); - - /// Used to quickly find MemberInfo by member name - DebugType.GetMember(name) uses a loop to search members - private Dictionary memberForNameMap; - - internal ObjectValue(int index, Dictionary memberFromNameMap) - { - this.Index = index; - this.memberForNameMap = memberFromNameMap; - } - - /// - /// Returns property with given name. - /// - public ObjectProperty this[string propertyName] - { - get - { - ObjectProperty property; - // has property with name 'propertyName' already been evaluated? - if(!this.properties.TryGetValue(propertyName, out property)) - { - if (this.PermanentReference == null) { - throw new DebuggerVisualizerException("Cannot get member of this ObjectValue - ObjectValue.PermanentReference is null"); - } - MemberInfo memberInfo = this.memberForNameMap.GetValue(propertyName); - if (memberInfo == null) { - throw new DebuggerVisualizerException("Cannot get member value - no member found with name " + propertyName); - } - property = CreatePropertyFromValue(propertyName, this.PermanentReference.GetMemberValue(memberInfo)); - this.properties.Add(propertyName, property); - } - return property; - } - } - - public static ObjectValue Create(Debugger.Value value, int index, Dictionary memberFromName) - { - ObjectValue result = new ObjectValue(index, memberFromName); - - // remember PermanentReference for expanding IEnumerable - Value permanentReference = value.GetPermanentReference(); - result.PermanentReference = permanentReference; - - return result; - } - - private static ObjectProperty CreatePropertyFromValue(string propertyName, Value value) - { - ObjectProperty property = new ObjectProperty(); - property.Name = propertyName; - // property.Expression = ?.Age - // - cannot use expression, - // if the value is returned from an enumerator, it has no meaningful expression - property.IsAtomic = value.Type.IsPrimitive; - property.IsNull = value.IsNull; - property.Value = value.IsNull ? "" : value.InvokeToString(); - return property; - } - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/EnumerableValuesProvider.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/EnumerableValuesProvider.cs deleted file mode 100644 index 09b9a5cf9f..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/EnumerableValuesProvider.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) - -using System; -using System.Collections; -using System.Collections.Generic; - -using Debugger.AddIn.Visualizers.Utils; -using Debugger.MetaData; -using ICSharpCode.Core; -using ICSharpCode.NRefactory.Ast; -using ICSharpCode.SharpDevelop.Services; -using System.Reflection; - -namespace Debugger.AddIn.Visualizers.GridVisualizer -{ - /// - /// Provides s for debugee objects implementing IEnumerable. - /// - /*public class EnumerableValuesProvider : GridValuesProvider - { - public EnumerableValuesProvider(Expression targetObject, DebugType iEnumerableType, DebugType itemType) - :base(targetObject, iEnumerableType, itemType) - { - this.itemsSource = enumerateItems(); - } - - private IEnumerable itemsSource; - public IEnumerable ItemsSource - { - get { return this.itemsSource; } - } - - private IEnumerable enumerateItems() - { - MethodInfo enumeratorMethod = collectionType.GetMethod("GetEnumerator"); - Value enumerator = targetObject.Evaluate(WindowsDebugger.CurrentProcess).InvokeMethod(enumeratorMethod, null).GetPermanentReference(); - - MethodInfo moveNextMethod = enumerator.Type.GetMethod("MoveNext"); - PropertyInfo currentproperty = enumerator.Type.GetInterface(typeof(IEnumerator).FullName).GetProperty("Current"); - - int index = 0; - while ((bool)enumerator.InvokeMethod(moveNextMethod, null).PrimitiveValue) - { - Value currentValue = enumerator.GetPropertyValue(currentproperty); - yield return ObjectValue.Create(currentValue, index++, this.memberFromNameMap); - } - } - }*/ -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/GridValuesProvider.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/GridValuesProvider.cs deleted file mode 100644 index f656934db6..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/GridValuesProvider.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) - -using System; -using System.Collections.Generic; -using Debugger.AddIn.Visualizers.Utils; -using Debugger.MetaData; -using ICSharpCode.NRefactory.Ast; -using System.Reflection; - -namespace Debugger.AddIn.Visualizers.GridVisualizer -{ - /// - /// Provides s to be displayed in Grid visualizer. - /// Descandants implement getting values for IList and IEnumerable. - /// - public class GridValuesProvider - { - /// Used to quickly find MemberInfo by member name - DebugType.GetMember(name) uses a loop to search members - protected Dictionary memberFromNameMap; - - protected Expression targetObject; - protected DebugType itemType; - - public GridValuesProvider(Expression targetObject, DebugType itemType) - { - this.targetObject = targetObject; - this.itemType = itemType; - - this.memberFromNameMap = this.GetItemTypeMembers().MakeDictionary(memberInfo => memberInfo.Name); - } - - /// - /// Gets members that will be displayed as columns. - /// - public IList GetItemTypeMembers() - { - var publicPropetiesAndFields = itemType.GetFieldsAndNonIndexedProperties(BindingFlags.Public | BindingFlags.Instance); - return publicPropetiesAndFields; - } - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/ListValuesProvider.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/ListValuesProvider.cs deleted file mode 100644 index 457566d0cf..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/ValueProviders/ListValuesProvider.cs +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using Debugger.AddIn.Visualizers.Utils; -using Debugger.MetaData; -using ICSharpCode.Core; -using ICSharpCode.NRefactory.Ast; -using ICSharpCode.SharpDevelop.Services; - -namespace Debugger.AddIn.Visualizers.GridVisualizer -{ - /// - /// Provides s for debugee objects implementing IList. - /// - public class ListValuesProvider : GridValuesProvider, IListValuesProvider - { - int? listCount = null; - /// - /// After evaluating how many items to clear debugger Expression cache, - /// so that the cache does not keep too many PermanentReferences. - /// - static readonly int ClearCacheThreshold = 50; - - public ListValuesProvider(Expression targetObject, DebugType listItemType) - :base(targetObject, listItemType) - { - } - - public int GetCount() - { - if (this.listCount == null) { - this.listCount = this.targetObject.GetIListCount(); - } - return this.listCount.Value; - } - - /// When this reaches ClearCacheThreshold, the debugger Expression cache is cleared. - int itemClearCacheCounter = 0; - - public ObjectValue GetItemAt(int index) - { - if (itemClearCacheCounter++ > ClearCacheThreshold) { - // clear debugger Expression cache to avoid holding too many PermanentReferences - WindowsDebugger.CurrentProcess.ClearExpressionCache(); - LoggingService.Info("Cleared debugger Expression cache."); - itemClearCacheCounter = 0; - } - return ObjectValue.Create( - targetObject.AppendIndexer(index).Evaluate(WindowsDebugger.CurrentProcess), - //targetObject.AppendIndexer(index), // use Expression instead of value - possible only for IList though - index, - this.memberFromNameMap); - } - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/TextVisualizer/TextVisualizerMode.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/TextVisualizer/TextVisualizerMode.cs deleted file mode 100644 index f084773b26..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/TextVisualizer/TextVisualizerMode.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) - -using System.Collections.Generic; -using System.Linq; -using System; - -public enum TextVisualizerMode -{ - PlainText, - Xml -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/TextVisualizer/TextVisualizerWindow.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/TextVisualizer/TextVisualizerWindow.xaml.cs index 56c8a75dc3..ab35e503ca 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/TextVisualizer/TextVisualizerWindow.xaml.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/TextVisualizer/TextVisualizerWindow.xaml.cs @@ -1,17 +1,9 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) -using ICSharpCode.AvalonEdit.Highlighting; using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Windows; -using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; -using System.Windows.Input; -using System.Windows.Media; +using ICSharpCode.AvalonEdit.Highlighting; namespace Debugger.AddIn.Visualizers.TextVisualizer { @@ -20,42 +12,14 @@ namespace Debugger.AddIn.Visualizers.TextVisualizer /// public partial class TextVisualizerWindow : Window { - public TextVisualizerWindow() - { - InitializeComponent(); - Mode = TextVisualizerMode.PlainText; - textEditor.IsReadOnly = true; - } - - public TextVisualizerWindow(string title, string text) + public TextVisualizerWindow(string title, string text, string highlighting = null) { InitializeComponent(); - Title= title; - Text = text; - } - - public string Text - { - get { return this.textEditor.Text; } - set { this.textEditor.Text = value; } - } - - private TextVisualizerMode mode; - public TextVisualizerMode Mode - { - get { return mode; } - set { - mode = value; - switch (mode) { - case TextVisualizerMode.PlainText: - textEditor.SyntaxHighlighting = null; - break; - case TextVisualizerMode.Xml: - textEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinitionByExtension(".xml"); - break; - } - } + Title = title; + this.textEditor.Text = text; + if (highlighting != null) + this.textEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinitionByExtension(highlighting); } void CheckBox_CheckedChanged(object sender, RoutedEventArgs e) diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/AtomicType.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/AtomicType.cs index c029bb0f12..16bad38635 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/AtomicType.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/AtomicType.cs @@ -22,16 +22,5 @@ namespace Debugger.AddIn.Visualizers.Utils { return type.IsPrimitive || type.FullName == "System.String" || type.IsEnum(); } - - /// - /// Checks whether given expression's type is atomic. - /// - /// Expression. - /// True if expression's type is atomic, False otherwise. - public static bool IsOfAtomicType(this Expression expr) - { - DebugType typeOfValue = expr.Evaluate(WindowsDebugger.CurrentProcess).Type; - return AtomicType.IsAtomic(typeOfValue); - } } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/DebuggerHelpers.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/DebuggerHelpers.cs index c962d91625..e880e3741e 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/DebuggerHelpers.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/DebuggerHelpers.cs @@ -2,6 +2,7 @@ // This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) using System.Linq; +using Debugger.AddIn.Visualizers.Graph; using Debugger.Interop.CorDebug; using System; using System.Collections.Generic; @@ -33,6 +34,24 @@ namespace Debugger.AddIn.Visualizers.Utils return new ObjectCreateExpression(listType.GetTypeReference(), iEnumerableVariableExplicitCast.SingleItemList()); } + /// + /// Evaluates 'new List<T>(iEnumerableValue)' in the debuggee. + /// + public static Value CreateListFromIEnumerable(Value iEnumerableValue) + { + DebugType iEnumerableType, itemType; + if (!iEnumerableValue.Type.ResolveIEnumerableImplementation(out iEnumerableType, out itemType)) + throw new GetValueException("Value is not IEnumerable"); + + DebugType listType = DebugType.CreateFromType(iEnumerableValue.AppDomain, typeof(System.Collections.Generic.List<>), itemType); + DebugConstructorInfo ctor = (DebugConstructorInfo)listType.GetConstructor(BindingFlags.Default, null, CallingConventions.Any, new System.Type[] { iEnumerableType }, null); + if (ctor == null) + throw new DebuggerException("List constructor not found"); + + // Keep reference since we do not want to keep reenumerating it + return Value.InvokeMethod(WindowsDebugger.EvalThread, null, ctor.MethodInfo, new Value[] { iEnumerableValue }).GetPermanentReferenceOfHeapValue(); + } + /// /// Gets underlying address of object in the debuggee. /// @@ -59,14 +78,6 @@ namespace Debugger.AddIn.Visualizers.Utils return type.FullName == "System.Object"; } - /// - /// Evaluates expression and gets underlying address of object in the debuggee. - /// - public static ulong GetObjectAddress(this Expression expr) - { - return expr.Evaluate(WindowsDebugger.CurrentProcess).GetObjectAddress(); - } - /// /// System.Runtime.CompilerServices.GetHashCode method, for obtaining non-overriden hash codes from debuggee. /// @@ -86,7 +97,7 @@ namespace Debugger.AddIn.Visualizers.Utils throw new DebuggerException("Cannot obtain method System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode"); } } - Value defaultHashCode = Eval.InvokeMethod(DebuggerHelpers.hashCodeMethod, null, new Value[]{value}); + Value defaultHashCode = Eval.InvokeMethod(WindowsDebugger.EvalThread, DebuggerHelpers.hashCodeMethod, null, new Value[]{value}); //MethodInfo method = value.Type.GetMember("GetHashCode", BindingFlags.Method | BindingFlags.IncludeSuperType) as MethodInfo; //string hashCode = value.InvokeMethod(method, null).AsString; @@ -106,23 +117,34 @@ namespace Debugger.AddIn.Visualizers.Utils } } - public static Value EvalPermanentReference(this Expression expr) - { - return expr.Evaluate(WindowsDebugger.CurrentProcess).GetPermanentReference(); - } - /// - /// Evaluates System.Collections.ICollection.Count property on given object. + /// Evaluates 'System.Collections.ICollection.Count' on given Value. /// /// Evaluating System.Collections.ICollection.Count on targetObject failed. - public static int GetIListCount(this Expression targetObject) + public static int GetIListCount(this Value list) { - Value list = targetObject.Evaluate(WindowsDebugger.CurrentProcess); var iCollectionType = list.Type.GetInterface(typeof(System.Collections.ICollection).FullName); if (iCollectionType == null) - throw new GetValueException(targetObject, targetObject.PrettyPrint() + " does not implement System.Collections.ICollection"); + throw new GetValueException("Object does not implement System.Collections.ICollection"); // Do not get string representation since it can be printed in hex - return (int)list.GetPropertyValue(iCollectionType.GetProperty("Count")).PrimitiveValue; + return (int)list.GetPropertyValue(WindowsDebugger.EvalThread, iCollectionType.GetProperty("Count")).PrimitiveValue; + } + + /// + /// Evaluates 'System.Collection.IList.Item(i)' on given Value. + /// + /// + /// + /// + public static Value GetIListItem(this Value target, int index) + { + var iListType = target.Type.GetInterface(typeof(System.Collections.IList).FullName); + if (iListType == null) + throw new GetValueException("Object does not implement System.Collections.IList"); + DebugPropertyInfo indexerProperty = (DebugPropertyInfo)iListType.GetProperty("Item"); + if (indexerProperty == null) + throw new GetValueException("The object does not have an indexer property"); + return target.GetPropertyValue(WindowsDebugger.EvalThread, indexerProperty, Eval.CreateValue(WindowsDebugger.EvalThread, index)); } /// diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/LinqUtils.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/LinqUtils.cs index 1c8ad1ddef..07bab775c8 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/LinqUtils.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/LinqUtils.cs @@ -7,9 +7,6 @@ using System; namespace Debugger.AddIn.Visualizers.Utils { - /// - /// Description of LinqUtils. - /// public static class LinqUtils { public static int MaxOrDefault(this IEnumerable source, Func selector, int defaultValue) diff --git a/src/AddIns/Debugger/Debugger.Core/AppDomainCollection.cs b/src/AddIns/Debugger/Debugger.Core/AppDomainCollection.cs deleted file mode 100644 index 19c92e40f6..0000000000 --- a/src/AddIns/Debugger/Debugger.Core/AppDomainCollection.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using System; -using Debugger.Interop.CorDebug; - -namespace Debugger -{ - public class AppDomainCollection: CollectionWithEvents - { - public AppDomainCollection(NDebugger dbgr): base(dbgr) {} - - public AppDomain this[ICorDebugAppDomain corAppDomain] { - get { - foreach(AppDomain a in this) { - if (a.CorAppDomain.Equals(corAppDomain)) { - return a; - } - } - throw new DebuggerException("AppDomain not found"); - } - } - } -} diff --git a/src/AddIns/Debugger/Debugger.Core/Breakpoint.cs b/src/AddIns/Debugger/Debugger.Core/Breakpoint.cs index bca887514f..56a4924610 100644 --- a/src/AddIns/Debugger/Debugger.Core/Breakpoint.cs +++ b/src/AddIns/Debugger/Debugger.Core/Breakpoint.cs @@ -11,103 +11,43 @@ namespace Debugger { public class Breakpoint: DebuggerObject { - NDebugger debugger; - - string fileName; - byte[] checkSum; - int line; - int column; - bool enabled; - - SourcecodeSegment originalLocation; - + bool enabled; protected List corBreakpoints = new List(); - public event EventHandler Hit; - public event EventHandler Set; - - [Debugger.Tests.Ignore] - public NDebugger Debugger { - get { return debugger; } - protected set { debugger = value; } - } - - public string FileName { - get { return fileName; } - } - - public byte[] CheckSum { - get { return checkSum; } - } - - public int Line { - get { return line; } - set { line = value; } - } + public string FileName { get; private set; } + public int Line { get; set; } + public int Column { get; set; } + public SourcecodeSegment OriginalLocation { get; private set; } - public int Column { - get { return column; } - } - - public bool Enabled { + public bool IsEnabled { get { return enabled; } set { enabled = value; foreach(ICorDebugFunctionBreakpoint corBreakpoint in corBreakpoints) { - corBreakpoint.Activate(enabled ? 1 : 0); + try { + corBreakpoint.Activate(enabled ? 1 : 0); + } catch(COMException e) { + // Sometimes happens, but we had not repro yet. + // 0x80131301: Process was terminated. + if ((uint)e.ErrorCode == 0x80131301) + continue; + throw; + } } } } - public SourcecodeSegment OriginalLocation { - get { return originalLocation; } - } - public bool IsSet { - get { - return corBreakpoints.Count > 0; - } - } - - public string TypeName { - get; protected set; - } - - protected virtual void OnHit(BreakpointEventArgs e) - { - if (Hit != null) { - Hit(this, e); - } - } - - internal void NotifyHit() - { - OnHit(new BreakpointEventArgs(this)); - debugger.Breakpoints.OnHit(this); - } - - protected virtual void OnSet(BreakpointEventArgs e) - { - if (Set != null) { - Set(this, e); - } + get { return corBreakpoints.Count > 0; } } - public Breakpoint() { } + public string TypeName { get; protected set; } - public Breakpoint(NDebugger debugger, ICorDebugFunctionBreakpoint corBreakpoint) + internal Breakpoint(string fileName, int line, int column, bool enabled) { - this.debugger = debugger; - this.corBreakpoints.Add(corBreakpoint); - } - - public Breakpoint(NDebugger debugger, string fileName, byte[] checkSum, int line, int column, bool enabled) - { - this.debugger = debugger; - this.fileName = fileName; - this.checkSum = checkSum; - this.line = line; - this.column = column; + this.FileName = fileName; + this.Line = line; + this.Column = column; this.enabled = enabled; } @@ -119,70 +59,38 @@ namespace Debugger return false; } - internal void Deactivate() - { - foreach(ICorDebugFunctionBreakpoint corBreakpoint in corBreakpoints) { - #if DEBUG - // Get repro - corBreakpoint.Activate(0); - #else - try { - corBreakpoint.Activate(0); - } catch(COMException e) { - // Sometimes happens, but we had not repro yet. - // 0x80131301: Process was terminated. - if ((uint)e.ErrorCode == 0x80131301) - continue; - throw; - } - #endif - } - corBreakpoints.Clear(); - } - - internal void MarkAsDeactivated() + internal void NotifyDebuggerTerminated() { corBreakpoints.Clear(); } public virtual bool SetBreakpoint(Module module) { - if (this.fileName == null) + SourcecodeSegment segment = SourcecodeSegment.Resolve(module, FileName, Line, Column); + if (segment == null) return false; - SourcecodeSegment segment = SourcecodeSegment.Resolve(module, FileName, CheckSum, Line, Column); - if (segment == null) return false; - - originalLocation = segment; + OriginalLocation = segment; ICorDebugFunctionBreakpoint corBreakpoint = segment.CorFunction.GetILCode().CreateBreakpoint((uint)segment.ILStart); corBreakpoint.Activate(enabled ? 1 : 0); corBreakpoints.Add(corBreakpoint); - OnSet(new BreakpointEventArgs(this)); - return true; } - - /// Remove this breakpoint - public void Remove() - { - debugger.Breakpoints.Remove(this); - } } public class ILBreakpoint : Breakpoint { - public ILBreakpoint(NDebugger debugger, string typeName, int line, int metadataToken, int memberToken, int offset, bool enabled) + public ILBreakpoint(string typeName, int line, int metadataToken, int memberToken, int offset, bool enabled) + : base(null, line, 0, enabled) { - this.Debugger = debugger; - this.Line = line; this.TypeName = typeName; this.MetadataToken = metadataToken; this.MemberMetadataToken = memberToken; this.ILOffset = offset; - this.Enabled = enabled; + this.IsEnabled = enabled; } public int MetadataToken { get; private set; } @@ -193,36 +101,23 @@ namespace Debugger public override bool SetBreakpoint(Module module) { + var currentModuleTypes = module.GetNamesOfDefinedTypes(); + // set the breakpoint only if the module contains the type + if (!currentModuleTypes.Contains(this.TypeName)) + return false; + SourcecodeSegment segment = SourcecodeSegment.CreateForIL(module, this.Line, MemberMetadataToken, ILOffset); if (segment == null) return false; try { ICorDebugFunctionBreakpoint corBreakpoint = segment.CorFunction.GetILCode().CreateBreakpoint((uint)segment.ILStart); - corBreakpoint.Activate(Enabled ? 1 : 0); + corBreakpoint.Activate(this.IsEnabled ? 1 : 0); corBreakpoints.Add(corBreakpoint); - OnSet(new BreakpointEventArgs(this)); return true; - } catch - #if DEBUG - (System.Exception) - #endif - { + } catch { return false; } } } - - [Serializable] - public class BreakpointEventArgs : DebuggerEventArgs - { - public Breakpoint Breakpoint { - get; private set; - } - - public BreakpointEventArgs(Breakpoint breakpoint): base(breakpoint.Debugger) - { - this.Breakpoint = breakpoint; - } - } } diff --git a/src/AddIns/Debugger/Debugger.Core/BreakpointCollection.cs b/src/AddIns/Debugger/Debugger.Core/BreakpointCollection.cs deleted file mode 100644 index 0e114f5cd8..0000000000 --- a/src/AddIns/Debugger/Debugger.Core/BreakpointCollection.cs +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using System; -using System.Collections.Generic; -using Debugger.Interop.CorDebug; - -namespace Debugger -{ - public class BreakpointCollection: CollectionWithEvents - { - public event EventHandler> Hit; - - protected internal void OnHit(Breakpoint item) - { - if (Hit != null) { - Hit(this, new CollectionItemEventArgs(item)); - } - } - - public BreakpointCollection(NDebugger debugger):base(debugger) { } - - internal Breakpoint this[ICorDebugBreakpoint corBreakpoint] { - get { - foreach (Breakpoint breakpoint in this) { - if (breakpoint.IsOwnerOf(corBreakpoint)) { - return breakpoint; - } - } - return null; - } - } - - public new void Add(Breakpoint breakpoint) - { - base.Add(breakpoint); - } - - public Breakpoint Add(string filename, int line) - { - Breakpoint breakpoint = new Breakpoint(this.Debugger, filename, null, line, 0, true); - Add(breakpoint); - return breakpoint; - } - - public Breakpoint Add(string fileName, byte[] checkSum, int line, int column, bool enabled) - { - Breakpoint breakpoint = new Breakpoint(this.Debugger, fileName, checkSum, line, column, enabled); - Add(breakpoint); - return breakpoint; - } - - protected override void OnAdded(Breakpoint breakpoint) - { - foreach(Process process in this.Debugger.Processes) { - foreach(Module module in process.Modules) { - if (breakpoint is ILBreakpoint) { - var currentModuleTypes = module.GetNamesOfDefinedTypes(); - // set the breakpoint only if the module contains the type - if (!currentModuleTypes.Contains(breakpoint.TypeName)) - continue; - } - breakpoint.SetBreakpoint(module); - } - } - - base.OnAdded(breakpoint); - } - - public new void Remove(Breakpoint breakpoint) - { - base.Remove(breakpoint); - } - - protected override void OnRemoved(Breakpoint breakpoint) - { - breakpoint.Deactivate(); - - base.OnRemoved(breakpoint); - } - - internal void SetInModule(Module module) - { - // This is in case that the client modifies the collection as a response to set breakpoint - // NB: If client adds new breakpoint, it will be set directly as a result of his call, not here (because module is already loaded) - List collection = new List(); - collection.AddRange(this); - - var currentModuleTypes = module.GetNamesOfDefinedTypes(); - foreach (Breakpoint b in collection) { - if (b is ILBreakpoint) { - // set the breakpoint only if the module contains the type - if (!currentModuleTypes.Contains(b.TypeName)) - continue; - b.SetBreakpoint(module); - } else { - b.SetBreakpoint(module); - } - } - } - } -} diff --git a/src/AddIns/Debugger/Debugger.Core/CollectionWithEvents.cs b/src/AddIns/Debugger/Debugger.Core/CollectionWithEvents.cs deleted file mode 100644 index 1a1715f113..0000000000 --- a/src/AddIns/Debugger/Debugger.Core/CollectionWithEvents.cs +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using System; -using System.Collections; -using System.Collections.Generic; - -namespace Debugger -{ - public class CollectionItemEventArgs : EventArgs - { - T item; - - public T Item { - get { - return item; - } - } - - public CollectionItemEventArgs(T item) - { - this.item = item; - } - } - - /// - /// A collection that fires events when items are added or removed. - /// - public class CollectionWithEvents : IEnumerable - { - NDebugger debugger; - - List list = new List(); - - public event EventHandler> Added; - public event EventHandler> Removed; - - protected virtual void OnAdded(T item) - { - if (Added != null) { - Added(this, new CollectionItemEventArgs(item)); - } - } - - protected virtual void OnRemoved(T item) - { - if (Removed != null) { - Removed(this, new CollectionItemEventArgs(item)); - } - } - - public CollectionWithEvents(NDebugger debugger) - { - this.debugger = debugger; - } - - protected NDebugger Debugger { - get { - return debugger; - } - } - - public int Count { - get { - return list.Count; - } - } - - public T this[int index] { - get { - return list[index]; - } - } - - internal void Add(T item) - { - list.Add(item); - OnAdded(item); - } - - internal void Remove(T item) - { - if (list.Remove(item)) { - OnRemoved(item); - } else { - throw new DebuggerException("Item is not in the collection"); - } - } - - internal void Clear() - { - List oldList = list; - list = new List(); - foreach (T item in oldList) { - OnRemoved(item); - } - } - - IEnumerator IEnumerable.GetEnumerator() - { - return list.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return list.GetEnumerator(); - } - } -} diff --git a/src/AddIns/Debugger/Debugger.Core/DebuggeeState.cs b/src/AddIns/Debugger/Debugger.Core/DebuggeeState.cs deleted file mode 100644 index 179125c37b..0000000000 --- a/src/AddIns/Debugger/Debugger.Core/DebuggeeState.cs +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -namespace Debugger -{ - /// - /// Represents span of time in which the debugger state is assumed to - /// be unchanged. - /// - /// - /// For example, although property evaluation can in theory change - /// any memory, it is assumed that they behave 'correctly' and thus - /// property evaluation does not change debugger state. - /// - public class DebuggeeState: DebuggerObject - { - Process process; - - public Process Process { - get { return process; } - } - - public DebuggeeState(Process process) - { - this.process = process; - } - } -} diff --git a/src/AddIns/Debugger/Debugger.Core/Debugger.Core.csproj b/src/AddIns/Debugger/Debugger.Core/Debugger.Core.csproj index d59af38cff..33ac0f2f23 100644 --- a/src/AddIns/Debugger/Debugger.Core/Debugger.Core.csproj +++ b/src/AddIns/Debugger/Debugger.Core/Debugger.Core.csproj @@ -64,19 +64,12 @@ - - - - - - - @@ -102,7 +95,6 @@ - @@ -144,14 +136,8 @@ - - - - - - @@ -159,9 +145,7 @@ - - @@ -198,17 +182,7 @@ - - - - - - {3A9AE6AA-BC07-4A2F-972C-581E3AE2F195} - NRefactory - False - - \ No newline at end of file diff --git a/src/AddIns/Debugger/Debugger.Core/DebuggerObject.cs b/src/AddIns/Debugger/Debugger.Core/DebuggerObject.cs deleted file mode 100644 index 714ef27792..0000000000 --- a/src/AddIns/Debugger/Debugger.Core/DebuggerObject.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using System; - -namespace Debugger -{ - /// - /// A base class for all classes declared by the debugger - /// - public class DebuggerObject: MarshalByRefObject - { - - } -} diff --git a/src/AddIns/Debugger/Debugger.Core/Eval.cs b/src/AddIns/Debugger/Debugger.Core/Eval.cs index 4c70596375..7dae8165ed 100644 --- a/src/AddIns/Debugger/Debugger.Core/Eval.cs +++ b/src/AddIns/Debugger/Debugger.Core/Eval.cs @@ -46,11 +46,11 @@ namespace Debugger get { return description; } } - public ICorDebugEval CorEval { + internal ICorDebugEval CorEval { get { return corEval; } } - public ICorDebugEval2 CorEval2 { + internal ICorDebugEval2 CorEval2 { get { return (ICorDebugEval2)corEval; } } @@ -81,14 +81,25 @@ namespace Debugger } } - Eval(AppDomain appDomain, string description, EvalStarter evalStarter) + Eval(Thread evalThread, string description, EvalStarter evalStarter) { - this.appDomain = appDomain; + if (evalThread == null) + throw new DebuggerException("No evaluation thread was provided"); + + this.appDomain = evalThread.AppDomain; this.process = appDomain.Process; this.description = description; this.state = EvalState.Evaluating; - this.thread = GetEvaluationThread(appDomain); - this.corEval = thread.CorThread.CreateEval(); + this.thread = evalThread; + + if (evalThread.Suspended) + throw new GetValueException("Can not evaluate because thread is suspended"); + if (evalThread.IsInNativeCode) + throw new GetValueException("Can not evaluate because thread is in native code"); + if (!evalThread.IsAtSafePoint) + throw new GetValueException("Can not evaluate because thread is not at safe point"); + + this.corEval = evalThread.CorThread.CreateEval(); try { evalStarter(this); @@ -120,37 +131,14 @@ namespace Debugger } } - appDomain.Process.ActiveEvals.Add(this); + appDomain.Process.activeEvals.Add(this); if (appDomain.Process.Options.SuspendOtherThreads) { - appDomain.Process.AsyncContinue(DebuggeeStateAction.Keep, new Thread[] { thread }, CorDebugThreadState.THREAD_SUSPEND); + appDomain.Process.AsyncContinue(DebuggeeStateAction.Keep, new Thread[] { evalThread }, CorDebugThreadState.THREAD_SUSPEND); } else { appDomain.Process.AsyncContinue(DebuggeeStateAction.Keep, this.Process.UnsuspendedThreads, CorDebugThreadState.THREAD_RUN); } } - - static Thread GetEvaluationThread(AppDomain appDomain) - { - appDomain.Process.AssertPaused(); - - Thread st = appDomain.Process.SelectedThread; - if (st != null && !st.Suspended && !st.IsInNativeCode && st.IsAtSafePoint && st.CorThread.GetAppDomain().GetID() == appDomain.ID) { - return st; - } - - foreach(Thread t in appDomain.Process.Threads) { - if (!t.Suspended && !t.IsInNativeCode && t.IsAtSafePoint && t.CorThread.GetAppDomain().GetID() == appDomain.ID) { - return t; - } - } - - throw new GetValueException("No suitable thread for evaluation"); - } - - internal bool IsCorEval(ICorDebugEval corEval) - { - return this.corEval == corEval; - } /// Evaluation can not be stopped /// Process exited @@ -200,19 +188,19 @@ namespace Debugger } /// Synchronously calls a function and returns its return value - public static Value InvokeMethod(DebugMethodInfo method, Value thisValue, Value[] args) + public static Value InvokeMethod(Thread evalThread, DebugMethodInfo method, Value thisValue, Value[] args) { if (method.BackingField != null) { method.Process.TraceMessage("Using backing field for " + method.FullName); - return Value.GetMemberValue(thisValue, method.BackingField, args); + return Value.GetMemberValue(evalThread, thisValue, method.BackingField, args); } - return AsyncInvokeMethod(method, thisValue, args).WaitForResult(); + return AsyncInvokeMethod(evalThread, method, thisValue, args).WaitForResult(); } - public static Eval AsyncInvokeMethod(DebugMethodInfo method, Value thisValue, Value[] args) + public static Eval AsyncInvokeMethod(Thread evalThread, DebugMethodInfo method, Value thisValue, Value[] args) { return new Eval( - method.AppDomain, + evalThread, "Function call: " + method.FullName, delegate(Eval eval) { MethodInvokeStarter(eval, method, thisValue, args); @@ -246,19 +234,21 @@ namespace Debugger Value arg = args[i]; DebugType paramType = (DebugType)method.GetParameters()[i].ParameterType; if (!arg.Type.CanImplicitelyConvertTo(paramType)) - throw new GetValueException("Inncorrect parameter type"); + throw new GetValueException("Inncorrect parameter type. Expected " + paramType.ToString()); // Implicitely convert to correct primitve type if (paramType.IsPrimitive && args[i].Type != paramType) { object oldPrimVal = arg.PrimitiveValue; object newPrimVal = Convert.ChangeType(oldPrimVal, paramType.PrimitiveType); - arg = CreateValue(method.AppDomain, newPrimVal); + // Eval - TODO: Is this dangerous? + arg = CreateValue(eval.thread, newPrimVal); } // It is importatnt to pass the parameted in the correct form (boxed/unboxed) if (paramType.IsValueType) { corArgs.Add(arg.CorGenericValue); } else { if (args[i].Type.IsValueType) { - corArgs.Add(arg.Box().CorValue); + // Eval - TODO: Is this dangerous? + corArgs.Add(arg.Box(eval.thread).CorValue); } else { corArgs.Add(arg.CorValue); } @@ -272,25 +262,24 @@ namespace Debugger (uint)corArgs.Count, corArgs.ToArray() ); } - - public static Value CreateValue(AppDomain appDomain, object value) - { - if (value == null) { - ICorDebugClass corClass = appDomain.ObjectType.CorType.GetClass(); - Thread thread = GetEvaluationThread(appDomain); - ICorDebugEval corEval = thread.CorThread.CreateEval(); + + public static Value CreateValue(Thread evalThread, object value) + { + if (value == null) { + ICorDebugClass corClass = evalThread.AppDomain.ObjectType.CorType.GetClass(); + ICorDebugEval corEval = evalThread.CorThread.CreateEval(); ICorDebugValue corValue = corEval.CreateValue((uint)CorElementType.CLASS, corClass); - return new Value(appDomain, corValue); + return new Value(evalThread.AppDomain, corValue); } else if (value is string) { - return Eval.NewString(appDomain, (string)value); + return Eval.NewString(evalThread, (string)value); } else { - if (!value.GetType().IsPrimitive) - throw new DebuggerException("Value must be primitve type. Seen " + value.GetType()); - Value val = Eval.NewObjectNoConstructor(DebugType.CreateFromType(appDomain.Mscorlib, value.GetType())); - val.PrimitiveValue = value; + if (!value.GetType().IsPrimitive) + throw new DebuggerException("Value must be primitve type. Seen " + value.GetType()); + Value val = Eval.NewObjectNoConstructor(evalThread, DebugType.CreateFromType(evalThread.AppDomain.Mscorlib, value.GetType())); + val.SetPrimitiveValue(evalThread, value); return val; } - } + } /* // The following function create values only for the purpuse of evalutaion @@ -318,19 +307,15 @@ namespace Debugger } */ - #region Convenience methods - - public static Value NewString(AppDomain appDomain, string textToCreate) + public static Value NewString(Thread evalThread, string textToCreate) { - return AsyncNewString(appDomain, textToCreate).WaitForResult(); + return AsyncNewString(evalThread, textToCreate).WaitForResult(); } - #endregion - - public static Eval AsyncNewString(AppDomain appDomain, string textToCreate) + public static Eval AsyncNewString(Thread evalThread, string textToCreate) { return new Eval( - appDomain, + evalThread, "New string: " + textToCreate, delegate(Eval eval) { eval.CorEval2.NewStringWithLength(textToCreate, (uint)textToCreate.Length); @@ -338,20 +323,16 @@ namespace Debugger ); } - #region Convenience methods - - public static Value NewArray(DebugType type, uint length, uint? lowerBound) + public static Value NewArray(Thread evalThread, DebugType type, uint length, uint? lowerBound) { - return AsyncNewArray(type, length, lowerBound).WaitForResult(); + return AsyncNewArray(evalThread, type, length, lowerBound).WaitForResult(); } - #endregion - - public static Eval AsyncNewArray(DebugType type, uint length, uint? lowerBound) + public static Eval AsyncNewArray(Thread evalThread, DebugType type, uint length, uint? lowerBound) { lowerBound = lowerBound ?? 0; return new Eval( - type.AppDomain, + evalThread, "New array: " + type + "[" + length + "]", delegate(Eval eval) { // Multi-dimensional arrays not supported in .NET 2.0 @@ -360,43 +341,37 @@ namespace Debugger ); } - #region Convenience methods - - public static Value NewObject(DebugMethodInfo constructor, Value[] constructorArguments) + public static Value NewObject(Thread evalThread, DebugMethodInfo constructor, Value[] constructorArguments) { - return AsyncNewObject(constructor, constructorArguments).WaitForResult(); + return AsyncNewObject(evalThread, constructor, constructorArguments).WaitForResult(); } - #endregion - - public static Eval AsyncNewObject(DebugMethodInfo constructor, Value[] constructorArguments) + public static Eval AsyncNewObject(Thread evalThread, DebugMethodInfo constructor, Value[] constructorArguments) { ICorDebugValue[] constructorArgsCorDebug = ValuesAsCorDebug(constructorArguments); return new Eval( - constructor.AppDomain, + evalThread, "New object: " + constructor.FullName, delegate(Eval eval) { eval.CorEval2.NewParameterizedObject( constructor.CorFunction, - (uint)constructor.DeclaringType.GetGenericArguments().Length, ((DebugType)constructor.DeclaringType).GenericArgumentsAsCorDebugType, - (uint)constructorArgsCorDebug.Length, constructorArgsCorDebug); + (uint)constructor.DeclaringType.GetGenericArguments().Length, + ((DebugType)constructor.DeclaringType).GenericArgumentsAsCorDebugType, + (uint)constructorArgsCorDebug.Length, + constructorArgsCorDebug); } ); } - #region Convenience methods - - public static Value NewObjectNoConstructor(DebugType debugType) + public static Value NewObjectNoConstructor(Thread evalThread, DebugType debugType) { - return AsyncNewObjectNoConstructor(debugType).WaitForResult(); + return AsyncNewObjectNoConstructor(evalThread, debugType).WaitForResult(); } - #endregion - - public static Eval AsyncNewObjectNoConstructor(DebugType debugType) + public static Eval AsyncNewObjectNoConstructor(Thread evalThread, DebugType debugType) { return new Eval( - debugType.AppDomain, + evalThread, "New object: " + debugType.FullName, delegate(Eval eval) { eval.CorEval2.NewParameterizedObjectNoConstructor(debugType.CorType.GetClass(), (uint)debugType.GetGenericArguments().Length, debugType.GenericArgumentsAsCorDebugType); diff --git a/src/AddIns/Debugger/Debugger.Core/EvalCollection.cs b/src/AddIns/Debugger/Debugger.Core/EvalCollection.cs deleted file mode 100644 index 6004c9dabd..0000000000 --- a/src/AddIns/Debugger/Debugger.Core/EvalCollection.cs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using Debugger.Interop.CorDebug; - -namespace Debugger -{ - public class EvalCollection: CollectionWithEvents - { - public EvalCollection(NDebugger debugger): base(debugger) {} - - internal Eval this[ICorDebugEval corEval] { - get { - foreach(Eval eval in this) { - if (eval.IsCorEval(corEval)) { - return eval; - } - } - throw new DebuggerException("Eval not found for given ICorDebugEval"); - } - } - } -} diff --git a/src/AddIns/Debugger/Debugger.Core/Exception.cs b/src/AddIns/Debugger/Debugger.Core/Exception.cs index ee75897de2..6486f4ba3e 100644 --- a/src/AddIns/Debugger/Debugger.Core/Exception.cs +++ b/src/AddIns/Debugger/Debugger.Core/Exception.cs @@ -4,7 +4,15 @@ using System.Text; namespace Debugger -{ +{ + enum ExceptionType + { + FirstChance = 1, + UserFirstChance = 2, + CatchHandlerFound = 3, + Unhandled = 4, + } + /// This convenience class provides access to an exception within the debugee. /// public class Exception: DebuggerObject @@ -15,9 +23,16 @@ namespace Debugger get { return exception; } } - public Exception(Value exception) + ExceptionType ExceptionType { get; set; } + + public bool IsUnhandled { + get { return this.ExceptionType == ExceptionType.Unhandled; } + } + + internal Exception(Value exception, ExceptionType exceptionType) { this.exception = exception; + this.ExceptionType = exceptionType; } /// The GetType().FullName of the exception. @@ -32,7 +47,7 @@ namespace Debugger /// public string Message { get { - Value message = exception.GetMemberValue("_message"); + Value message = exception.GetFieldValue("_message"); return message.IsNull ? string.Empty : message.AsString(); } } @@ -41,14 +56,14 @@ namespace Debugger /// public Exception InnerException { get { - Value innerException = exception.GetMemberValue("_innerException"); - return innerException.IsNull ? null : new Exception(innerException); + Value innerException = exception.GetFieldValue("_innerException"); + return innerException.IsNull ? null : new Exception(innerException, this.ExceptionType); } } public void MakeValuePermanent() { - exception = exception.GetPermanentReference(); + exception = exception.GetPermanentReferenceOfHeapValue(); } public override string ToString() @@ -66,25 +81,25 @@ namespace Debugger return sb.ToString(); } - public string GetStackTrace() + public string GetStackTrace(Thread evalThread) { - return GetStackTrace("--- End of inner exception stack trace ---"); + return GetStackTrace(evalThread, "--- End of inner exception stack trace ---"); } /// Returs formated stacktrace for the exception /// Getting the stacktrace involves property /// evaluation so GetValueException can be thrown in some cicumstances. - public string GetStackTrace(string endOfInnerExceptionFormat) + public string GetStackTrace(Thread evalThread, string endOfInnerExceptionFormat) { StringBuilder sb = new StringBuilder(); if (this.InnerException != null) { - sb.Append(this.InnerException.GetStackTrace(endOfInnerExceptionFormat)); + sb.Append(this.InnerException.GetStackTrace(evalThread, endOfInnerExceptionFormat)); sb.Append(" "); sb.Append(endOfInnerExceptionFormat); sb.AppendLine(); } // Note that evaluation is not possible after a stackoverflow exception - Value stackTrace = exception.GetMemberValue("StackTrace"); + Value stackTrace = exception.GetMemberValue(evalThread, "StackTrace"); if (!stackTrace.IsNull) { sb.Append(stackTrace.AsString()); sb.AppendLine(); @@ -92,30 +107,4 @@ namespace Debugger return sb.ToString(); } } - - public class ExceptionEventArgs: ProcessEventArgs - { - readonly Exception exception; - readonly ExceptionType exceptionType; - readonly bool isUnhandled; - - public Exception Exception { - get { return exception; } - } - - public ExceptionType ExceptionType { - get { return exceptionType; } - } - - public bool IsUnhandled { - get { return isUnhandled; } - } - - public ExceptionEventArgs(Process process, Exception exception, ExceptionType exceptionType, bool isUnhandled):base(process) - { - this.exception = exception; - this.exceptionType = exceptionType; - this.isUnhandled = isUnhandled; - } - } } diff --git a/src/AddIns/Debugger/Debugger.Core/ExceptionType.cs b/src/AddIns/Debugger/Debugger.Core/ExceptionType.cs deleted file mode 100644 index 287bcf31d1..0000000000 --- a/src/AddIns/Debugger/Debugger.Core/ExceptionType.cs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -namespace Debugger -{ - public enum ExceptionType - { - FirstChance = 1, - UserFirstChance = 2, - CatchHandlerFound = 3, - Unhandled = 4, - } -} diff --git a/src/AddIns/Debugger/Debugger.Core/GetValueException.cs b/src/AddIns/Debugger/Debugger.Core/GetValueException.cs index a1adb2fa4f..0183d9d199 100644 --- a/src/AddIns/Debugger/Debugger.Core/GetValueException.cs +++ b/src/AddIns/Debugger/Debugger.Core/GetValueException.cs @@ -2,55 +2,21 @@ // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; -using ICSharpCode.NRefactory.Ast; namespace Debugger { public class GetValueException: DebuggerException { - INode expression; - string error; - - /// Expression that has caused this exception to occur - public INode Expression { - get { return expression; } - set { expression = value; } - } - - public string Error { - get { return error; } - } - - public override string Message { - get { - if (expression == null) { - return error; - } else { - return error; - // return String.Format("Error evaluating \"{0}\": {1}", expression.PrettyPrint(), error); - } - } - } - - public GetValueException(INode expression, string error):base(error) - { - this.expression = expression; - this.error = error; - } - public GetValueException(string error, System.Exception inner):base(error, inner) { - this.error = error; } public GetValueException(string errorFmt, params object[] args):base(string.Format(errorFmt, args)) { - this.error = string.Format(errorFmt, args); } public GetValueException(string error):base(error) { - this.error = error; } } } diff --git a/src/AddIns/Debugger/Debugger.Core/Interop/NativeMethods.cs b/src/AddIns/Debugger/Debugger.Core/Interop/NativeMethods.cs index 5c9e6c2d8d..54b585701d 100644 --- a/src/AddIns/Debugger/Debugger.Core/Interop/NativeMethods.cs +++ b/src/AddIns/Debugger/Debugger.Core/Interop/NativeMethods.cs @@ -12,89 +12,6 @@ using Debugger.Interop.CorDebug; namespace Debugger.Interop { - [StructLayout(LayoutKind.Sequential)] - public struct MEMORY_BASIC_INFORMATION - { - public IntPtr BaseAddress; - public IntPtr AllocationBase; - public uint AllocationProtect; - public IntPtr RegionSize; - public uint State; - public uint Protect; - public uint Type; - } - - [Flags] - public enum ProcessAccessFlags : uint - { - All = 0x001F0FFF, - Terminate = 0x00000001, - CreateThread = 0x00000002, - VMOperation = 0x00000008, - VMRead = 0x00000010, - VMWrite = 0x00000020, - DupHandle = 0x00000040, - SetInformation = 0x00000200, - QueryInformation = 0x00000400, - Synchronize = 0x00100000 - } - - [StructLayout(LayoutKind.Sequential)] - public struct SYSTEM_INFO - { - internal _PROCESSOR_INFO_UNION uProcessorInfo; - public uint dwPageSize; - public IntPtr lpMinimumApplicationAddress; - public IntPtr lpMaximumApplicationAddress; - public IntPtr dwActiveProcessorMask; - public uint dwNumberOfProcessors; - public uint dwProcessorType; - public uint dwAllocationGranularity; - public ushort dwProcessorLevel; - public ushort dwProcessorRevision; - } - - [StructLayout(LayoutKind.Explicit)] - public struct _PROCESSOR_INFO_UNION - { - [FieldOffset(0)] - internal uint dwOemId; - [FieldOffset(0)] - internal ushort wProcessorArchitecture; - [FieldOffset(2)] - internal ushort wReserved; - } - - [Flags] - public enum AllocationType - { - Commit = 0x1000, - Reserve = 0x2000, - Decommit = 0x4000, - Release = 0x8000, - Reset = 0x80000, - Physical = 0x400000, - TopDown = 0x100000, - WriteWatch = 0x200000, - LargePages = 0x20000000 - } - - [Flags] - public enum MemoryProtection - { - Execute = 0x10, - ExecuteRead = 0x20, - ExecuteReadWrite = 0x40, - ExecuteWriteCopy = 0x80, - NoAccess = 0x01, - ReadOnly = 0x02, - ReadWrite = 0x04, - WriteCopy = 0x08, - GuardModifierflag = 0x100, - NoCacheModifierflag = 0x200, - WriteCombineModifierflag = 0x400 - } - public static class NativeMethods { [DllImport("kernel32.dll", SetLastError = true)] @@ -108,88 +25,6 @@ namespace Debugger.Interop [DllImport("mscoree.dll", CharSet=CharSet.Unicode)] public static extern int GetRequestedRuntimeVersion(string exeFilename, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pVersion, Int32 cchBuffer, out Int32 dwLength); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool VirtualQueryEx(IntPtr hProcess, - IntPtr lpAddress, - out MEMORY_BASIC_INFORMATION lpBuffer, - uint dwLength); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, - UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern bool ReadProcessMemory( - IntPtr hProcess, - IntPtr lpBaseAddress, - [Out] byte[] lpBuffer, - int dwSize, - out int lpNumberOfBytesRead - ); - - [DllImport("kernel32.dll", SetLastError = true)] - public static extern void GetSystemInfo(out SYSTEM_INFO lpSystemInfo); - - public static List> GetVirtualMemoryAddresses(this Process process) - { - var result = new List>(); - SYSTEM_INFO sysinfo = new SYSTEM_INFO(); - GetSystemInfo(out sysinfo); - - long address = 0; - MEMORY_BASIC_INFORMATION m = new MEMORY_BASIC_INFORMATION(); - IntPtr openedProcess = IntPtr.Zero; - try { - openedProcess = OpenProcess(ProcessAccessFlags.All, false, (int)process.Id); - - while (address < sysinfo.lpMaximumApplicationAddress.ToInt64()) - { - try { - if (!VirtualQueryEx(openedProcess, new IntPtr(address), out m, (uint)Marshal.SizeOf(m))) - continue; - } finally { - // next address - address = m.BaseAddress.ToInt64() + m.RegionSize.ToInt64(); - } - - result.Add(new Tuple(m.BaseAddress.ToInt64(), m.RegionSize.ToInt64())); - } - } finally { - if (openedProcess != IntPtr.Zero) - CloseHandle(openedProcess); - } - - return result; - } - - public static byte[] ReadProcessMemory(this Process process, long startAddress, long size) - { - IntPtr openedProcess = IntPtr.Zero; - byte[] temp = null; - try { - temp = new byte[size]; - openedProcess = OpenProcess(ProcessAccessFlags.All, false, (int)process.Id); - - int outSize; - bool success = ReadProcessMemory(openedProcess, new IntPtr(startAddress), temp, temp.Length, out outSize); - - if (!success || outSize == 0) { - var proc = System.Diagnostics.Process.GetProcessById((int)process.Id); - return process.ReadProcessMemory(proc.MainModule.BaseAddress.ToInt64(), (long)4096); - } - } catch { - return null; - } finally { - if (openedProcess != IntPtr.Zero) - CloseHandle(openedProcess); - } - - return temp; - } } } diff --git a/src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs b/src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs index 7842aa06fa..a598cfbdd9 100644 --- a/src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs +++ b/src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs @@ -2,6 +2,7 @@ // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; +using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; using Debugger.Interop; @@ -22,7 +23,12 @@ namespace Debugger { Process process; bool pauseOnNextExit; - bool isInCallback = false; + bool raiseEventsOnNextExit; + bool isInCallback; + + Thread threadToReport; + List breakpointsHit = new List(); + Exception exceptionThrown; [Debugger.Tests.Ignore] public Process Process { @@ -38,7 +44,7 @@ namespace Debugger this.process = process; } - void EnterCallback(PausedReason pausedReason, string name, ICorDebugProcess pProcess) + void EnterCallback(string name, ICorDebugProcess pProcess) { isInCallback = true; @@ -46,35 +52,32 @@ namespace Debugger System.Diagnostics.Debug.Assert(process.CorProcess == pProcess); // After break is pressed we may receive some messages that were already queued - if (process.IsPaused && process.PauseSession.PausedReason == PausedReason.ForcedBreak) { - // TODO: This does not work well if exception if being processed and the user continues it + if (process.IsPaused) { process.TraceMessage("Processing post-break callback"); - // This compensates for the break call and we are in normal callback handling mode + // Decrese the "break count" from 2 to 1 - does not actually continue process.AsyncContinue(DebuggeeStateAction.Keep, new Thread[] {}, null); - // Start of call back - create new pause session (as usual) - process.NotifyPaused(pausedReason); - // Make sure we stay pause after the callback is handled + // Make sure we stay pauses after the callback is handled pauseOnNextExit = true; return; } if (process.IsRunning) { - process.NotifyPaused(pausedReason); + process.NotifyPaused(); return; } throw new DebuggerException("Invalid state at the start of callback"); } - void EnterCallback(PausedReason pausedReason, string name, ICorDebugAppDomain pAppDomain) + void EnterCallback(string name, ICorDebugAppDomain pAppDomain) { - EnterCallback(pausedReason, name, pAppDomain.GetProcess()); + EnterCallback(name, pAppDomain.GetProcess()); } - void EnterCallback(PausedReason pausedReason, string name, ICorDebugThread pThread) + void EnterCallback(string name, ICorDebugThread pThread) { - EnterCallback(pausedReason, name, pThread.GetProcess()); - process.SelectedThread = process.GetThread(pThread); + EnterCallback(name, pThread.GetProcess()); + threadToReport = process.GetThread(pThread); } void ExitCallback() @@ -83,10 +86,8 @@ namespace Debugger if (hasQueuedCallbacks) process.TraceMessage("Process has queued callbacks"); - // only process callbacks if no exception occurred - // if no thread is selected CurrentException must be null - if (hasQueuedCallbacks && (process.SelectedThread == null || process.SelectedThread.CurrentException == null)) { - // Exception has Exception2 queued after it + if (hasQueuedCallbacks && exceptionThrown == null) { + // Process queued callbacks if no exception occurred process.AsyncContinue(DebuggeeStateAction.Keep, null, null); } else if (process.Evaluating) { // Ignore events during property evaluation @@ -94,8 +95,25 @@ namespace Debugger } else if (pauseOnNextExit) { if (process.Options.Verbose) process.TraceMessage("Callback exit: Paused"); + + process.DisableAllSteppers(); + if (raiseEventsOnNextExit) { + DebuggerEventArgs e = new DebuggerEventArgs(); + e.Process = process; + e.Thread = threadToReport; + e.BreakpointsHit = breakpointsHit.ToArray(); + e.ExceptionThrown = exceptionThrown; + threadToReport = null; + breakpointsHit.Clear(); + exceptionThrown = null; + + // Raise the pause event outside the callback + // Warning: Make sure that process in not resumed in the meantime + process.Debugger.MTA2STA.AsyncCall(delegate { process.OnPaused(e); }); + } + pauseOnNextExit = false; - Pause(); + raiseEventsOnNextExit = false; } else { process.AsyncContinue(DebuggeeStateAction.Keep, null, null); } @@ -103,35 +121,16 @@ namespace Debugger isInCallback = false; } - void Pause() - { - if (process.PauseSession.PausedReason == PausedReason.EvalComplete || - process.PauseSession.PausedReason == PausedReason.ExceptionIntercepted) { - // TODO: There might be qued callback after EvalComplete making this unrealiable - process.DisableAllSteppers(); - process.CheckSelectedStackFrames(); - // Do not set selected stack frame - // Do not raise events - } else { - // Raise the pause event outside the callback - // Warning: Make sure that process in not resumed in the meantime - process.Debugger.MTA2STA.AsyncCall(process.RaisePausedEvents); - - // The event might probably get called out of order when the process is running again - } - } - - #region Program folow control public void StepComplete(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugStepper pStepper, CorDebugStepReason reason) { - EnterCallback(PausedReason.StepComplete, "StepComplete (" + reason.ToString() + ")", pThread); + EnterCallback("StepComplete (" + reason.ToString() + ")", pThread); Thread thread = process.GetThread(pThread); Stepper stepper = process.GetStepper(pStepper); - StackFrame currentStackFrame = process.SelectedThread.MostRecentStackFrame; + StackFrame currentStackFrame = thread.MostRecentStackFrame; process.TraceMessage(" - stopped at {0} because of {1}", currentStackFrame.MethodInfo.FullName, stepper.ToString()); process.Steppers.Remove(stepper); @@ -158,6 +157,7 @@ namespace Debugger } else { // User-code method pauseOnNextExit = true; + raiseEventsOnNextExit = true; process.TraceMessage(" - pausing in user code"); } @@ -167,37 +167,42 @@ namespace Debugger // Warning! Marshaing of ICorBreakpoint fails in .NET 1.1 public void Breakpoint(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugBreakpoint corBreakpoint) { - EnterCallback(PausedReason.Breakpoint, "Breakpoint", pThread); + EnterCallback("Breakpoint", pThread); - Breakpoint breakpoint = process.Debugger.Breakpoints[corBreakpoint]; - // The event will be risen outside the callback - process.BreakpointHitEventQueue.Enqueue(breakpoint); + Breakpoint breakpoint = process.Debugger.GetBreakpoint(corBreakpoint); + // Could be tempBreakpoint + if (breakpoint != null) { + breakpointsHit.Add(breakpoint); + } pauseOnNextExit = true; + raiseEventsOnNextExit = true; ExitCallback(); } public void BreakpointSetError(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugBreakpoint pBreakpoint, uint dwError) { - EnterCallback(PausedReason.Other, "BreakpointSetError", pThread); + EnterCallback("BreakpointSetError", pThread); ExitCallback(); } public void Break(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread) { - EnterCallback(PausedReason.Break, "Break", pThread); + EnterCallback("Break", pThread); pauseOnNextExit = true; + raiseEventsOnNextExit = true; ExitCallback(); } public void ControlCTrap(ICorDebugProcess pProcess) { - EnterCallback(PausedReason.ControlCTrap, "ControlCTrap", pProcess); + EnterCallback("ControlCTrap", pProcess); pauseOnNextExit = true; + raiseEventsOnNextExit = true; ExitCallback(); } @@ -211,7 +216,7 @@ namespace Debugger Exception2(pAppDomain, pThread, null, 0, (CorDebugExceptionCallbackType)exceptionType, 0); } else { // This callback should be ignored in v2 applications - EnterCallback(PausedReason.Other, "Exception", pThread); + EnterCallback("Exception", pThread); ExitCallback(); } @@ -223,14 +228,14 @@ namespace Debugger public void LogSwitch(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, int lLevel, uint ulReason, string pLogSwitchName, string pParentName) { - EnterCallback(PausedReason.Other, "LogSwitch", pThread); + EnterCallback("LogSwitch", pThread); ExitCallback(); } public void LogMessage(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, int lLevel, string pLogSwitchName, string pMessage) { - EnterCallback(PausedReason.Other, "LogMessage", pThread); + EnterCallback("LogMessage", pThread); process.OnLogMessage(new MessageEventArgs(process, lLevel, pMessage, pLogSwitchName)); @@ -239,21 +244,21 @@ namespace Debugger public void EditAndContinueRemap(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugFunction pFunction, int fAccurate) { - EnterCallback(PausedReason.Other, "EditAndContinueRemap", pThread); + EnterCallback("EditAndContinueRemap", pThread); ExitCallback(); } public void EvalException(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugEval corEval) { - EnterCallback(PausedReason.EvalComplete, "EvalException", pThread); + EnterCallback("EvalException (" + process.GetActiveEval(corEval).Description + ")", pThread); HandleEvalComplete(pAppDomain, pThread, corEval, true); } public void EvalComplete(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugEval corEval) { - EnterCallback(PausedReason.EvalComplete, "EvalComplete", pThread); + EnterCallback("EvalComplete (" + process.GetActiveEval(corEval).Description + ")", pThread); HandleEvalComplete(pAppDomain, pThread, corEval, false); } @@ -261,9 +266,9 @@ namespace Debugger void HandleEvalComplete(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugEval corEval, bool exception) { // Let the eval know that the CorEval has finished - Eval eval = process.ActiveEvals[corEval]; + Eval eval = process.GetActiveEval(corEval); eval.NotifyEvaluationComplete(!exception); - process.ActiveEvals.Remove(eval); + process.activeEvals.Remove(eval); pauseOnNextExit = true; ExitCallback(); @@ -271,7 +276,7 @@ namespace Debugger public void DebuggerError(ICorDebugProcess pProcess, int errorHR, uint errorCode) { - EnterCallback(PausedReason.DebuggerError, "DebuggerError", pProcess); + EnterCallback("DebuggerError", pProcess); string errorText = String.Format("Debugger error: \nHR = 0x{0:X} \nCode = 0x{1:X}", errorHR, errorCode); @@ -288,6 +293,7 @@ namespace Debugger try { pauseOnNextExit = true; + raiseEventsOnNextExit = true; ExitCallback(); } catch (COMException) { } catch (InvalidComObjectException) { @@ -297,9 +303,9 @@ namespace Debugger public void UpdateModuleSymbols(ICorDebugAppDomain pAppDomain, ICorDebugModule pModule, IStream pSymbolStream) { - EnterCallback(PausedReason.Other, "UpdateModuleSymbols", pAppDomain); + EnterCallback("UpdateModuleSymbols", pAppDomain); - Module module = process.Modules[pModule]; + Module module = process.GetModule(pModule); if (module.CorModule is ICorDebugModule3 && module.IsDynamic) { // In .NET 4.0, we use the LoadClass callback to load dynamic modules // because it always works - UpdateModuleSymbols does not. @@ -320,7 +326,7 @@ namespace Debugger public void CreateProcess(ICorDebugProcess pProcess) { - EnterCallback(PausedReason.Other, "CreateProcess", pProcess); + EnterCallback("CreateProcess", pProcess); // Process is added in NDebugger.Start // disable NGen @@ -340,27 +346,28 @@ namespace Debugger public void CreateAppDomain(ICorDebugProcess pProcess, ICorDebugAppDomain pAppDomain) { - EnterCallback(PausedReason.Other, "CreateAppDomain", pAppDomain); + EnterCallback("CreateAppDomain", pAppDomain); pAppDomain.Attach(); - process.AppDomains.Add(new AppDomain(process, pAppDomain)); + process.appDomains.Add(new AppDomain(process, pAppDomain)); ExitCallback(); } public void LoadAssembly(ICorDebugAppDomain pAppDomain, ICorDebugAssembly pAssembly) { - EnterCallback(PausedReason.Other, "LoadAssembly", pAppDomain); + EnterCallback("LoadAssembly", pAppDomain); ExitCallback(); } public void LoadModule(ICorDebugAppDomain pAppDomain, ICorDebugModule pModule) { - EnterCallback(PausedReason.Other, "LoadModule " + pModule.GetName(), pAppDomain); + EnterCallback("LoadModule " + pModule.GetName(), pAppDomain); - Module module = new Module(process.AppDomains[pAppDomain], pModule); - process.Modules.Add(module); + Module module = new Module(process.GetAppDomain(pAppDomain), pModule); + process.modules.Add(module); + process.OnModuleLoaded(module); ExitCallback(); } @@ -369,17 +376,14 @@ namespace Debugger { if (pAppDomain != null) { - EnterCallback(PausedReason.Other, "NameChange: pAppDomain", pAppDomain); + EnterCallback("NameChange: pAppDomain", pAppDomain); ExitCallback(); } if (pThread != null) { - EnterCallback(PausedReason.Other, "NameChange: pThread", pThread); - - Thread thread = process.GetThread(pThread); - thread.NotifyNameChanged(); + EnterCallback("NameChange: pThread", pThread); ExitCallback(); @@ -390,10 +394,10 @@ namespace Debugger { // We can not use pThread since it has not been added yet // and we continue from this callback anyway - EnterCallback(PausedReason.Other, "CreateThread " + pThread.GetID(), pAppDomain); + EnterCallback("CreateThread " + pThread.GetID(), pAppDomain); Thread thread = new Thread(process, pThread); - process.Threads.Add(thread); + process.threads.Add(thread); thread.CorThread.SetDebugState(process.NewThreadState); @@ -402,9 +406,9 @@ namespace Debugger public void LoadClass(ICorDebugAppDomain pAppDomain, ICorDebugClass c) { - EnterCallback(PausedReason.Other, "LoadClass", pAppDomain); + EnterCallback("LoadClass", pAppDomain); - Module module = process.Modules[c.GetModule()]; + Module module = process.GetModule(c.GetModule()); // Dynamic module has been extended - reload symbols to inlude new class module.LoadSymbolsDynamic(); @@ -418,36 +422,40 @@ namespace Debugger public void UnloadClass(ICorDebugAppDomain pAppDomain, ICorDebugClass c) { - EnterCallback(PausedReason.Other, "UnloadClass", pAppDomain); + EnterCallback("UnloadClass", pAppDomain); ExitCallback(); } public void UnloadModule(ICorDebugAppDomain pAppDomain, ICorDebugModule pModule) { - EnterCallback(PausedReason.Other, "UnloadModule", pAppDomain); + EnterCallback("UnloadModule", pAppDomain); - process.Modules.Remove(process.Modules[pModule]); + Module module = process.GetModule(pModule); + process.modules.Remove(module); + process.OnModuleUnloaded(module); ExitCallback(); } public void UnloadAssembly(ICorDebugAppDomain pAppDomain, ICorDebugAssembly pAssembly) { - EnterCallback(PausedReason.Other, "UnloadAssembly", pAppDomain); + EnterCallback("UnloadAssembly", pAppDomain); ExitCallback(); } public void ExitThread(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread) { + Thread thread = process.GetThread(pThread); + // ICorDebugThread is still not dead and can be used for some operations - if (process.Threads.Contains(pThread)) { - EnterCallback(PausedReason.Other, "ExitThread " + pThread.GetID(), pThread); + if (thread != null) { + EnterCallback("ExitThread " + pThread.GetID(), pThread); - process.GetThread(pThread).NotifyExited(); + thread.NotifyExited(); } else { - EnterCallback(PausedReason.Other, "ExitThread " + pThread.GetID(), process.CorProcess); + EnterCallback("ExitThread " + pThread.GetID(), process.CorProcess); // .NET 4.0 - It seems that the API is reporting exits of threads without announcing their creation. // TODO: Remove in next .NET 4.0 beta and investigate @@ -464,9 +472,9 @@ namespace Debugger public void ExitAppDomain(ICorDebugProcess pProcess, ICorDebugAppDomain pAppDomain) { - EnterCallback(PausedReason.Other, "ExitAppDomain", pAppDomain); + EnterCallback("ExitAppDomain", pAppDomain); - process.AppDomains.Remove(process.AppDomains[pAppDomain]); + process.appDomains.Remove(process.GetAppDomain(pAppDomain)); ExitCallback(); } @@ -476,7 +484,7 @@ namespace Debugger // ExitProcess may be called at any time when debuggee is killed process.TraceMessage("Callback: ExitProcess"); - process.NotifyHasExited(); + process.OnExited(); } #endregion @@ -485,28 +493,28 @@ namespace Debugger public void ChangeConnection(ICorDebugProcess pProcess, uint dwConnectionId) { - EnterCallback(PausedReason.Other, "ChangeConnection", pProcess); + EnterCallback("ChangeConnection", pProcess); ExitCallback(); } public void CreateConnection(ICorDebugProcess pProcess, uint dwConnectionId, IntPtr pConnName) { - EnterCallback(PausedReason.Other, "CreateConnection", pProcess); + EnterCallback("CreateConnection", pProcess); ExitCallback(); } public void DestroyConnection(ICorDebugProcess pProcess, uint dwConnectionId) { - EnterCallback(PausedReason.Other, "DestroyConnection", pProcess); + EnterCallback("DestroyConnection", pProcess); ExitCallback(); } public void Exception2(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugFrame pFrame, uint nOffset, CorDebugExceptionCallbackType _exceptionType, uint dwFlags) { - EnterCallback(PausedReason.Exception, "Exception2 (type=" + _exceptionType.ToString() + ")", pThread); + EnterCallback("Exception2 (type=" + _exceptionType.ToString() + ")", pThread); // This callback is also called from Exception(...)!!!! (the .NET 1.1 version) // Watch out for the zeros and null! @@ -518,13 +526,12 @@ namespace Debugger if (exceptionType == ExceptionType.Unhandled || (pauseOnHandled && exceptionType == ExceptionType.CatchHandlerFound)) { // sanity check: we can only handle one exception after another // TODO : create Exception queue if CLR throws multiple exceptions - Debug.Assert(process.SelectedThread.CurrentException == null); - process.SelectedThread.CurrentException = new Exception(new Value(process.AppDomains[pAppDomain], process.SelectedThread.CorThread.GetCurrentException()).GetPermanentReference()); - process.SelectedThread.CurrentException_DebuggeeState = process.DebuggeeState; - process.SelectedThread.CurrentExceptionType = exceptionType; - process.SelectedThread.CurrentExceptionIsUnhandled = exceptionType == ExceptionType.Unhandled; + Debug.Assert(exceptionThrown == null); + Value value = new Value(process.GetAppDomain(pAppDomain), pThread.GetCurrentException()).GetPermanentReferenceOfHeapValue(); + exceptionThrown = new Exception(value, exceptionType); pauseOnNextExit = true; + raiseEventsOnNextExit = true; } ExitCallback(); @@ -532,7 +539,7 @@ namespace Debugger public void ExceptionUnwind(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, CorDebugExceptionUnwindCallbackType dwEventType, uint dwFlags) { - EnterCallback(PausedReason.ExceptionIntercepted, "ExceptionUnwind", pThread); + EnterCallback("ExceptionUnwind", pThread); if (dwEventType == CorDebugExceptionUnwindCallbackType.DEBUG_EXCEPTION_INTERCEPTED) { pauseOnNextExit = true; @@ -542,14 +549,14 @@ namespace Debugger public void FunctionRemapComplete(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugFunction pFunction) { - EnterCallback(PausedReason.Other, "FunctionRemapComplete", pThread); + EnterCallback("FunctionRemapComplete", pThread); ExitCallback(); } public void FunctionRemapOpportunity(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugFunction pOldFunction, ICorDebugFunction pNewFunction, uint oldILOffset) { - EnterCallback(PausedReason.Other, "FunctionRemapOpportunity", pThread); + EnterCallback("FunctionRemapOpportunity", pThread); ExitCallback(); } @@ -558,9 +565,9 @@ namespace Debugger public void MDANotification(ICorDebugController c, ICorDebugThread t, ICorDebugMDA mda) { if (c is ICorDebugAppDomain) { - EnterCallback(PausedReason.Other, "MDANotification", (ICorDebugAppDomain)c); + EnterCallback("MDANotification", (ICorDebugAppDomain)c); } else if (c is ICorDebugProcess){ - EnterCallback(PausedReason.Other, "MDANotification", (ICorDebugProcess)c); + EnterCallback("MDANotification", (ICorDebugProcess)c); } else { throw new System.Exception("Unknown callback argument"); } diff --git a/src/AddIns/Debugger/Debugger.Core/ManagedCallbackSwitch.cs b/src/AddIns/Debugger/Debugger.Core/ManagedCallbackSwitch.cs index c7abb50974..968b28cc76 100644 --- a/src/AddIns/Debugger/Debugger.Core/ManagedCallbackSwitch.cs +++ b/src/AddIns/Debugger/Debugger.Core/ManagedCallbackSwitch.cs @@ -73,7 +73,7 @@ namespace Debugger Process process; // We have to wait until the created process is added into the collection lock(debugger.ProcessIsBeingCreatedLock) { - process = debugger.Processes[pProcess]; + process = debugger.GetProcess(pProcess); } // Make *really* sure the process is not dead if (process == null) { diff --git a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugConstructorInfo.cs b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugConstructorInfo.cs index 1fd8775669..55b2686fb5 100644 --- a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugConstructorInfo.cs +++ b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugConstructorInfo.cs @@ -19,6 +19,10 @@ namespace Debugger.MetaData { DebugMethodInfo methodInfo; + public DebugMethodInfo MethodInfo { + get { return methodInfo; } + } + internal DebugConstructorInfo(DebugMethodInfo methodInfo) { this.methodInfo = methodInfo; @@ -109,13 +113,13 @@ namespace Debugger.MetaData /// public override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) { - return methodInfo.Invoke(null, invokeAttr, binder, parameters, culture); + throw new NotImplementedException("Use Debugger.Value directly"); } /// public override object Invoke(BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) { - return methodInfo.Invoke(null, invokeAttr, binder, parameters, culture); + throw new NotImplementedException("Use Debugger.Value directly"); } /// diff --git a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugFieldInfo.cs b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugFieldInfo.cs index 8ad8cb9cca..33404f1cb7 100644 --- a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugFieldInfo.cs +++ b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugFieldInfo.cs @@ -109,13 +109,13 @@ namespace Debugger.MetaData /// public override object GetValue(object obj) { - return Value.GetFieldValue((Value)obj, this); + throw new NotImplementedException("Use Debugger.Value directly"); } /// public override void SetValue(object obj, object value, System.Reflection.BindingFlags invokeAttr, Binder binder, CultureInfo culture) { - Value.SetFieldValue((Value)obj, this, (Value)value); + throw new NotImplementedException("Use Debugger.Value directly"); } /// diff --git a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugLocalVariableInfo.cs b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugLocalVariableInfo.cs index 72afa64446..b5b97f7aaa 100644 --- a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugLocalVariableInfo.cs +++ b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugLocalVariableInfo.cs @@ -2,6 +2,7 @@ // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; +using System.Reflection; namespace Debugger.MetaData { @@ -11,6 +12,8 @@ namespace Debugger.MetaData int localIndex; DebugType localType; + public DebugMethodInfo Member { get; private set; } + /// public override int LocalIndex { get { return localIndex; } @@ -34,8 +37,9 @@ namespace Debugger.MetaData public bool IsThis { get; internal set; } public bool IsCaptured { get; internal set; } - public DebugLocalVariableInfo(string name, int localIndex, int startOffset, int endOffset, DebugType localType, ValueGetter getter) + public DebugLocalVariableInfo(DebugMethodInfo member, string name, int localIndex, int startOffset, int endOffset, DebugType localType, ValueGetter getter) { + this.Member = member; this.Name = name; this.localIndex = localIndex; this.StartOffset = startOffset; @@ -46,6 +50,11 @@ namespace Debugger.MetaData public Value GetValue(StackFrame context) { + if (context == null) + throw new ArgumentNullException("context"); + if (context.MethodInfo != this.Member) + throw new GetValueException("Expected stack frame: " + this.Member.ToString()); + return getter(context); } diff --git a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs index 2f8f659726..fe9d8b716f 100644 --- a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs +++ b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs @@ -160,17 +160,7 @@ namespace Debugger.MetaData /// public override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) { - List args = new List(); - foreach(object arg in parameters) { - args.Add((Value)arg); - } - if (this.IsSpecialName && this.Name == ".ctor") { - if (obj != null) - throw new GetValueException("'obj' must be null for constructor call"); - return Eval.NewObject(this, args.ToArray()); - } else { - return Eval.InvokeMethod(this, (Value)obj, args.ToArray()); - } + throw new NotImplementedException("Use Debugger.Value directly"); } /// @@ -575,7 +565,8 @@ namespace Debugger.MetaData localVariables, 0, int.MaxValue, delegate(StackFrame context) { - return context.GetThisValue().GetFieldValue(fieldInfoCopy); + // TODO: Use eval thread + return context.GetThisValue().GetFieldValue(context.Thread, fieldInfoCopy); }, (DebugType)fieldInfo.FieldType ); @@ -585,6 +576,7 @@ namespace Debugger.MetaData // Add this if (!this.IsStatic) { DebugLocalVariableInfo thisVar = new DebugLocalVariableInfo( + this, "this", -1, 0, int.MaxValue, @@ -600,20 +592,22 @@ namespace Debugger.MetaData return localVariables; } - static void AddCapturedLocalVariables(List vars, int scopeStartOffset, int scopeEndOffset, ValueGetter getCaptureClass, DebugType captureClassType) + void AddCapturedLocalVariables(List vars, int scopeStartOffset, int scopeEndOffset, ValueGetter getCaptureClass, DebugType captureClassType) { if (captureClassType.IsDisplayClass || captureClassType.IsYieldEnumerator || captureClassType.IsAsyncStateMachine) { foreach(DebugFieldInfo fieldInfo in captureClassType.GetFields()) { DebugFieldInfo fieldInfoCopy = fieldInfo; if (fieldInfo.Name.StartsWith("CS$")) continue; // Ignore DebugLocalVariableInfo locVar = new DebugLocalVariableInfo( + this, fieldInfo.Name, -1, scopeStartOffset, scopeEndOffset, (DebugType)fieldInfo.FieldType, delegate(StackFrame context) { - return getCaptureClass(context).GetFieldValue(fieldInfoCopy); + // TODO: Use eval thread + return getCaptureClass(context).GetFieldValue(context.Thread, fieldInfoCopy); } ); locVar.IsCaptured = true; @@ -646,7 +640,7 @@ namespace Debugger.MetaData { List vars = new List(); foreach (ISymUnmanagedVariable symVar in symScope.GetLocals()) { - ISymUnmanagedVariable symVarCopy = symVar; + uint address = (uint)symVar.GetAddressField1(); int start; SignatureReader sigReader = new SignatureReader(symVar.GetSignature()); LocalVarSig.LocalVariable locVarSig = sigReader.ReadLocalVariable(sigReader.Blob, 0, out start); @@ -661,13 +655,14 @@ namespace Debugger.MetaData (int)symScope.GetStartOffset(), (int)symScope.GetEndOffset(), delegate(StackFrame context) { - return GetLocalVariableValue(context, symVarCopy); + return context.GetLocalVariableValue(address); }, locVarType ); } } else { DebugLocalVariableInfo locVar = new DebugLocalVariableInfo( + this, symVar.GetName(), (int)symVar.GetAddressField1(), // symVar also has Get*Offset methods, but the are not implemented @@ -675,7 +670,7 @@ namespace Debugger.MetaData (int)symScope.GetEndOffset(), locVarType, delegate(StackFrame context) { - return GetLocalVariableValue(context, symVarCopy); + return context.GetLocalVariableValue(address); } ); vars.Add(locVar); @@ -687,18 +682,6 @@ namespace Debugger.MetaData return vars; } - static Value GetLocalVariableValue(StackFrame context, ISymUnmanagedVariable symVar) - { - ICorDebugValue corVal; - try { - corVal = context.CorILFrame.GetLocalVariable((uint)symVar.GetAddressField1()); - } catch (COMException e) { - if ((uint)e.ErrorCode == 0x80131304) throw new GetValueException("Unavailable in optimized code"); - throw; - } - return new Value(context.AppDomain, corVal); - } - /// public override string ToString() { diff --git a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugParameterInfo.cs b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugParameterInfo.cs index cf95f75558..84cc7203ad 100644 --- a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugParameterInfo.cs +++ b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugParameterInfo.cs @@ -45,6 +45,11 @@ namespace Debugger.MetaData public Value GetValue(StackFrame context) { + if (context == null) + throw new ArgumentNullException("context"); + if (context.MethodInfo != this.Member) + throw new GetValueException("Expected stack frame: " + this.Member.ToString()); + return getter(context); } diff --git a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugPropertyInfo.cs b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugPropertyInfo.cs index 35b0bc252a..36937d52d6 100644 --- a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugPropertyInfo.cs +++ b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugPropertyInfo.cs @@ -184,21 +184,13 @@ namespace Debugger.MetaData /// public override object GetValue(object obj, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture) { - List args = new List(); - foreach(object arg in index) { - args.Add((Value)arg); - } - return Value.GetPropertyValue((Value)obj, this, args.ToArray()); + throw new NotImplementedException("Use Debugger.Value directly"); } /// public override void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture) { - List args = new List(); - foreach(object arg in index) { - args.Add((Value)arg); - } - Value.SetPropertyValue((Value)obj, this, args.ToArray(), (Value)value); + throw new NotImplementedException("Use Debugger.Value directly"); } public bool IsPublic { diff --git a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugType.cs b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugType.cs index fa6b205543..4a9afee7a3 100644 --- a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugType.cs +++ b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugType.cs @@ -9,7 +9,6 @@ using System.Text; using Debugger.Interop.CorDebug; using Debugger.Interop.MetaData; -using ICSharpCode.NRefactory.Ast; using Mono.Cecil.Signatures; namespace Debugger.MetaData @@ -1076,7 +1075,7 @@ namespace Debugger.MetaData public static DebugType CreateFromCorClass(AppDomain appDomain, bool? valueType, ICorDebugClass corClass, DebugType[] genericArguments) { - MetaDataImport metaData = appDomain.Process.Modules[corClass.GetModule()].MetaData; + MetaDataImport metaData = appDomain.Process.GetModule(corClass.GetModule()).MetaData; if (valueType == null) { uint superClassToken = metaData.GetTypeDefProps(corClass.GetToken()).SuperClassToken; @@ -1176,7 +1175,7 @@ namespace Debugger.MetaData genericArguments.Add(DebugType.CreateFromCorType(appDomain, t)); } // Get class props - this.module = appDomain.Process.Modules[corType.GetClass().GetModule()]; + this.module = appDomain.Process.GetModule(corType.GetClass().GetModule()); this.classProps = module.MetaData.GetTypeDefProps(corType.GetClass().GetToken()); if (this.DebugModule.AppDomain != appDomain) throw new DebuggerException("The specified AppDomain was inccorect"); diff --git a/src/AddIns/Debugger/Debugger.Core/Module.cs b/src/AddIns/Debugger/Debugger.Core/Module.cs index db6c99dbd8..d6c1704682 100644 --- a/src/AddIns/Debugger/Debugger.Core/Module.cs +++ b/src/AddIns/Debugger/Debugger.Core/Module.cs @@ -29,11 +29,6 @@ namespace Debugger internal Dictionary LoadedDebugTypes = new Dictionary(); - /// - /// Occurs when symbols are loaded or unloaded (for memory modules) - /// - public event EventHandler SymbolsUpdated; - public AppDomain AppDomain { get { return appDomain; } } @@ -222,11 +217,11 @@ namespace Debugger /// /// Load symblos for on-disk module /// - public void LoadSymbolsFromDisk(string[] searchPath) + public void LoadSymbolsFromDisk(string[] symbolsSearchPaths) { if (!IsDynamic && !IsInMemory) { if (symReader == null) { - symReader = metaData.GetSymReader(fullPath, string.Join("; ", searchPath ?? new string[0])); + symReader = metaData.GetSymReader(fullPath, string.Join("; ", symbolsSearchPaths ?? new string[0])); if (symReader != null) { process.TraceMessage("Loaded symbols from disk for " + this.Name); OnSymbolsUpdated(); @@ -280,31 +275,10 @@ namespace Debugger void OnSymbolsUpdated() { - SetBreakpoints(); - ResetJustMyCodeStatus(); - if (SymbolsUpdated != null) { - SymbolsUpdated(this, new ModuleEventArgs(this)); - } - } - - void SetBreakpoints() - { - if (this.HasSymbols) { - // This is in case that the client modifies the collection as a response to set breakpoint - // NB: If client adds new breakpoint, it will be set directly as a result of his call, not here (because module is already loaded) - List collection = new List(); - collection.AddRange(this.Debugger.Breakpoints); - - var currentModuleTypes = this.GetNamesOfDefinedTypes(); - foreach (Breakpoint b in collection) { - if (b is ILBreakpoint) { - // set the breakpoint only if the module contains the type - if (!currentModuleTypes.Contains(b.TypeName)) - continue; - } - b.SetBreakpoint(this); - } + foreach (Breakpoint b in this.Debugger.Breakpoints) { + b.SetBreakpoint(this); } + ResetJustMyCodeStatus(); } void SetJITCompilerFlags() @@ -396,21 +370,4 @@ namespace Debugger return jcf; } } - - [Serializable] - public class ModuleEventArgs : ProcessEventArgs - { - Module module; - - public Module Module { - get { - return module; - } - } - - public ModuleEventArgs(Module module): base(module.Process) - { - this.module = module; - } - } } diff --git a/src/AddIns/Debugger/Debugger.Core/ModuleCollection.cs b/src/AddIns/Debugger/Debugger.Core/ModuleCollection.cs deleted file mode 100644 index d01fd53af5..0000000000 --- a/src/AddIns/Debugger/Debugger.Core/ModuleCollection.cs +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using System; -using Debugger.Interop.CorDebug; - -namespace Debugger -{ - public class ModuleCollection: CollectionWithEvents - { - public ModuleCollection(NDebugger debugger):base (debugger) {} - - int lastAssignedModuleOrderOfLoading = 0; - - public Module this[string filename] { - get { - foreach(Module module in this) { - if (module.Name == filename) { - return module; - } - } - throw new DebuggerException("Module \"" + filename + "\" is not in collection"); - } - } - - internal Module this[ICorDebugModule corModule] { - get { - foreach(Module module in this) { - if (module.CorModule == corModule) { - return module; - } - } - throw new DebuggerException("Module is not in collection"); - } - } - - protected override void OnAdded(Module module) - { - module.OrderOfLoading = lastAssignedModuleOrderOfLoading; - lastAssignedModuleOrderOfLoading++; - base.OnAdded(module); - } - - protected override void OnRemoved(Module module) - { - base.OnRemoved(module); - module.Dispose(); - } - } -} diff --git a/src/AddIns/Debugger/Debugger.Core/NDebugger.cs b/src/AddIns/Debugger/Debugger.Core/NDebugger.cs index 61ecb39eb5..0858212982 100644 --- a/src/AddIns/Debugger/Debugger.Core/NDebugger.cs +++ b/src/AddIns/Debugger/Debugger.Core/NDebugger.cs @@ -2,6 +2,7 @@ // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; +using System.Collections.Generic; using System.IO; using System.Text; using System.Threading; @@ -11,14 +12,22 @@ using Microsoft.Win32; namespace Debugger { + /// + /// A base class for all classes declared by the debugger + /// + public class DebuggerObject: MarshalByRefObject + { + + } + public class NDebugger: DebuggerObject { ICorDebug corDebug; ManagedCallbackSwitch managedCallbackSwitch; ManagedCallbackProxy managedCallbackProxy; - BreakpointCollection breakpoints; - ProcessCollection processes; + internal List breakpoints = new List(); + internal List processes = new List(); MTA2STA mta2sta = new MTA2STA(); @@ -49,19 +58,16 @@ namespace Debugger set { options = value; } } - public BreakpointCollection Breakpoints { - get { return breakpoints; } + public IEnumerable Breakpoints { + get { return this.breakpoints; } } - public ProcessCollection Processes { - get { return processes; } + public IEnumerable Processes { + get { return this.processes; } } public NDebugger() { - processes = new ProcessCollection(this); - breakpoints = new BreakpointCollection(this); - if (ApartmentState.STA == System.Threading.Thread.CurrentThread.GetApartmentState()) { mta2sta.CallMethod = CallMethod.HiddenFormWithTimeout; } else { @@ -69,6 +75,15 @@ namespace Debugger } } + internal Process GetProcess(ICorDebugProcess corProcess) { + foreach (Process process in this.Processes) { + if (process.CorProcess == corProcess) { + return process; + } + } + return null; + } + /// /// Get the .NET version of the process that called this function /// @@ -137,38 +152,57 @@ namespace Debugger internal void TerminateDebugger() { - // Mark breakpints as deactivated - foreach (Breakpoint b in this.Breakpoints) { - b.MarkAsDeactivated(); + foreach(Breakpoint breakpoint in this.Breakpoints) { + breakpoint.NotifyDebuggerTerminated(); } - TraceMessage("Reset done"); - corDebug.Terminate(); - TraceMessage("ICorDebug terminated"); int released = TrackedComObjects.ReleaseAll(); - TraceMessage("Released " + released + " tracked COM objects"); } - /// - /// Internal: Used to debug the debugger library. - /// - public event EventHandler DebuggerTraceMessage; + public Breakpoint AddBreakpoint(string fileName, int line, int column = 0, bool enabled = true) + { + Breakpoint breakpoint = new Breakpoint(fileName, line, column, enabled); + AddBreakpoint(breakpoint); + return breakpoint; + } - protected internal virtual void OnDebuggerTraceMessage(MessageEventArgs e) + public ILBreakpoint AddILBreakpoint(string typeName, int line, int metadataToken, int memberToken, int offset, bool enabled) { - if (DebuggerTraceMessage != null) { - DebuggerTraceMessage(this, e); + ILBreakpoint breakpoint = new ILBreakpoint(typeName, line, metadataToken, memberToken, offset, enabled); + AddBreakpoint(breakpoint); + return breakpoint; + } + + void AddBreakpoint(Breakpoint breakpoint) + { + this.breakpoints.Add(breakpoint); + + foreach (Process process in this.Processes) { + foreach(Module module in process.Modules) { + breakpoint.SetBreakpoint(module); + } + } + } + + internal Breakpoint GetBreakpoint(ICorDebugBreakpoint corBreakpoint) + { + foreach (Breakpoint breakpoint in this.Breakpoints) { + if (breakpoint.IsOwnerOf(corBreakpoint)) { + return breakpoint; + } } + return null; } internal void TraceMessage(string message) { - System.Diagnostics.Debug.WriteLine("Debugger:" + message); - OnDebuggerTraceMessage(new MessageEventArgs(null, message)); + message = "Debugger: " + message; + System.Console.WriteLine(message); + System.Diagnostics.Debug.WriteLine(message); } public void StartWithoutDebugging(System.Diagnostics.ProcessStartInfo psi) @@ -181,39 +215,36 @@ namespace Debugger internal object ProcessIsBeingCreatedLock = new object(); - public Process Start(string filename, string workingDirectory, string arguments) + public Process Start(string filename, string workingDirectory, string arguments, bool breakInMain) { InitDebugger(GetProgramVersion(filename)); lock(ProcessIsBeingCreatedLock) { Process process = Process.CreateProcess(this, filename, workingDirectory, arguments); // Expose a race conditon System.Threading.Thread.Sleep(0); - this.Processes.Add(process); + process.BreakInMain = breakInMain; + this.processes.Add(process); return process; } } - public Process Attach(System.Diagnostics.Process existingProcess) + public Process Attach(System.Diagnostics.Process existingProcess) { string mainModule = existingProcess.MainModule.FileName; InitDebugger(GetProgramVersion(mainModule)); - ICorDebugProcess corDebugProcess = corDebug.DebugActiveProcess((uint)existingProcess.Id, 0); - // TODO: Can we get the acutal working directory? - Process process = new Process(this, corDebugProcess, Path.GetDirectoryName(mainModule)); - this.Processes.Add(process); - return process; + lock(ProcessIsBeingCreatedLock) { + ICorDebugProcess corDebugProcess = corDebug.DebugActiveProcess((uint)existingProcess.Id, 0); + // TODO: Can we get the acutal working directory? + Process process = new Process(this, corDebugProcess, Path.GetDirectoryName(mainModule)); + this.processes.Add(process); + return process; + } } public void Detach() { - // Deactivate breakpoints - foreach (Breakpoint b in this.Breakpoints) { - b.Deactivate(); - } - // Detach all processes. - for (int i = 0; i < this.Processes.Count; ++i) { - Process process = this.Processes[i]; + foreach(Process process in this.Processes) { if (process == null || process.HasExited) continue; process.Detach(); @@ -264,57 +295,48 @@ namespace Debugger } [Serializable] - public class DebuggerEventArgs : EventArgs + public class DebuggerEventArgs: EventArgs { - NDebugger debugger; - - public NDebugger Debugger { - get { - return debugger; - } - } + /// The process on which the event occured. Can be null. + public Process Process { get; set; } + /// The thread on which the event occured. Can be null if the event was not thread specific. + public Thread Thread { get; set; } + public Breakpoint[] BreakpointsHit { get; set; } + public Exception ExceptionThrown { get; set; } + } + + [Serializable] + public class ModuleEventArgs: DebuggerEventArgs + { + public Module Module { get; private set; } - public DebuggerEventArgs(NDebugger debugger) + public ModuleEventArgs(Module module) { - this.debugger = debugger; + this.Process = module.Process; + this.Module = module; } } [Serializable] - public class MessageEventArgs : ProcessEventArgs + public class MessageEventArgs : EventArgs { - int level; - string message; - string category; - - public int Level { - get { - return level; - } - } - - public string Message { - get { - return message; - } - } - - public string Category { - get { - return category; - } - } + public Process Process { get; private set; } + public int Level { get; private set; } + public string Message { get; private set; } + public string Category { get; private set; } - public MessageEventArgs(Process process, string message): this(process, 0, message, String.Empty) + public MessageEventArgs(Process process, string message) { - this.message = message; + this.Process = process; + this.Message = message; } - public MessageEventArgs(Process process, int level, string message, string category): base(process) + public MessageEventArgs(Process process, int level, string message, string category) { - this.level = level; - this.message = message; - this.category = category; + this.Process = process; + this.Level = level; + this.Message = message; + this.Category = category; } } } diff --git a/src/AddIns/Debugger/Debugger.Core/PauseSession.cs b/src/AddIns/Debugger/Debugger.Core/PauseSession.cs deleted file mode 100644 index 6af85f12bf..0000000000 --- a/src/AddIns/Debugger/Debugger.Core/PauseSession.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -namespace Debugger -{ - /// - /// Holds information about the state of paused debugger. - /// Expires when when Continue is called on debugger. - /// - public class PauseSession: DebuggerObject - { - Process process; - PausedReason pausedReason; - - public Process Process { - get { return process; } - } - - public PausedReason PausedReason { - get { return pausedReason; } - set { pausedReason = value; } - } - - public PauseSession(Process process, PausedReason pausedReason) - { - this.process = process; - this.pausedReason = pausedReason; - } - } -} diff --git a/src/AddIns/Debugger/Debugger.Core/PausedReason.cs b/src/AddIns/Debugger/Debugger.Core/PausedReason.cs deleted file mode 100644 index c424718673..0000000000 --- a/src/AddIns/Debugger/Debugger.Core/PausedReason.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -namespace Debugger -{ - public enum PausedReason : int - { - EvalComplete, - StepComplete, - Breakpoint, - Break, - ControlCTrap, - Exception, - ForcedBreak, // Process.Break called - DebuggerError, - CurrentThreadChanged, - CurrentFunctionChanged, - ExceptionIntercepted, - SetIP, - Other - } -} diff --git a/src/AddIns/Debugger/Debugger.Core/Process.cs b/src/AddIns/Debugger/Debugger.Core/Process.cs index 268bd63f3f..c6c879ed11 100644 --- a/src/AddIns/Debugger/Debugger.Core/Process.cs +++ b/src/AddIns/Debugger/Debugger.Core/Process.cs @@ -7,8 +7,6 @@ using System.Runtime.InteropServices; using Debugger.Interop.CorDebug; using Debugger.Interop.CorSym; -using ICSharpCode.NRefactory.Ast; -using ICSharpCode.NRefactory.Visitors; namespace Debugger { @@ -44,13 +42,21 @@ namespace Debugger ICorDebugProcess corProcess; ManagedCallback callbackInterface; - EvalCollection activeEvals; - ModuleCollection modules; - ThreadCollection threads; - AppDomainCollection appDomains; + List tempBreakpoints = new List(); + + internal List activeEvals = new List(); + internal List modules = new List(); + internal List threads = new List(); + internal List appDomains = new List(); string workingDirectory; + public event EventHandler LogMessage; + public event EventHandler ModuleLoaded; + public event EventHandler ModuleUnloaded; + public event EventHandler Paused; + public event EventHandler Resumed; + public event EventHandler Exited; public NDebugger Debugger { get { return debugger; } @@ -72,53 +78,21 @@ namespace Debugger get { return callbackInterface; } } - public EvalCollection ActiveEvals { - get { return activeEvals; } - } - internal bool Evaluating { get { return activeEvals.Count > 0; } } - public ModuleCollection Modules { - get { return modules; } - } - - public ThreadCollection Threads { - get { return threads; } - } - - public Thread SelectedThread { - get { return this.Threads.Selected; } - set { this.Threads.Selected = value; } - } - - public StackFrame SelectedStackFrame { - get { - if (SelectedThread == null) { - return null; - } else { - return SelectedThread.SelectedStackFrame; - } - } + public IEnumerable Modules { + get { return this.modules; } } - public SourcecodeSegment NextStatement { - get { - if (SelectedStackFrame == null || IsRunning) { - return null; - } else { - return SelectedStackFrame.NextStatement; - } - } + public IEnumerable Threads { + get { return this.threads; } } - public bool BreakAtBeginning { - get; - set; - } + internal bool BreakInMain { get; set; } - public AppDomainCollection AppDomains { + public IEnumerable AppDomains { get { return appDomains; } } @@ -141,12 +115,6 @@ namespace Debugger this.workingDirectory = workingDirectory; this.callbackInterface = new ManagedCallback(this); - - activeEvals = new EvalCollection(debugger); - modules = new ModuleCollection(debugger); - modules.Added += OnModulesAdded; - threads = new ThreadCollection(debugger); - appDomains = new AppDomainCollection(debugger); } static unsafe public Process CreateProcess(NDebugger debugger, string filename, string workingDirectory, string arguments) @@ -189,14 +157,10 @@ namespace Debugger return new Process(debugger, outProcess, workingDirectory); } - /// Fired when System.Diagnostics.Trace.WriteLine() is called in debuged process - public event EventHandler LogMessage; - - protected internal virtual void OnLogMessage(MessageEventArgs arg) + internal void OnLogMessage(MessageEventArgs arg) { - TraceMessage ("Debugger event: OnLogMessage"); - if (LogMessage != null) { - LogMessage(this, arg); + if (this.LogMessage != null) { + this.LogMessage(this, arg); } } @@ -204,8 +168,61 @@ namespace Debugger { if (args.Length > 0) message = string.Format(message, args); - System.Diagnostics.Debug.WriteLine("Debugger:" + message); - debugger.OnDebuggerTraceMessage(new MessageEventArgs(this, message)); + this.Debugger.TraceMessage(message); + } + + internal AppDomain GetAppDomain(ICorDebugAppDomain corAppDomain) + { + foreach(AppDomain a in this.AppDomains) { + if (a.CorAppDomain.Equals(corAppDomain)) { + return a; + } + } + throw new DebuggerException("AppDomain not found"); + } + + internal Eval GetActiveEval(ICorDebugEval corEval) + { + foreach(Eval eval in this.activeEvals) { + if (eval.CorEval == corEval) { + return eval; + } + } + throw new DebuggerException("Eval not found for given ICorDebugEval"); + } + + public Module GetModule(string filename) + { + foreach(Module module in this.Modules) { + if (module.Name == filename) { + return module; + } + } + throw new DebuggerException("Module \"" + filename + "\" is not in collection"); + } + + internal Module GetModule(ICorDebugModule corModule) + { + foreach(Module module in this.Modules) { + if (module.CorModule == corModule) { + return module; + } + } + throw new DebuggerException("Module is not in collection"); + } + + internal Thread GetThread(ICorDebugThread corThread) + { + foreach(Thread thread in this.Threads) { + if (thread.CorThread == corThread) { + return thread; + } + } + // Sometimes, the thread is not reported for some unkown reason + TraceMessage("Thread not found in collection"); + Thread newThread = new Thread(this, corThread); + this.threads.Add(newThread); + return newThread; } /// Read the specified amount of memory at the given memory address @@ -233,47 +250,22 @@ namespace Debugger return written; } - internal Thread GetThread(ICorDebugThread corThread) - { - foreach(Thread thread in this.Threads) { - if (thread.CorThread == corThread) { - return thread; - } - } - Thread t = new Thread(this, corThread); - this.Threads.Add(t); - return t; - } - - #region Exceptions - - public event EventHandler ExceptionThrown; - - protected internal virtual void OnExceptionThrown(ExceptionEventArgs e) - { - TraceMessage ("Debugger event: OnExceptionThrown()"); - if (ExceptionThrown != null) { - ExceptionThrown(this, e); - } - } - - #endregion - // State control for the process internal bool TerminateCommandIssued = false; - internal Queue BreakpointHitEventQueue = new Queue(); - internal Dictionary ExpressionsCache = new Dictionary(); #region Events - public event EventHandler Paused; - public event EventHandler Resumed; - - // HACK: public - public virtual void OnPaused() + internal void OnPaused(DebuggerEventArgs e) { AssertPaused(); + DisableAllSteppers(); + + foreach (var corBreakpoint in tempBreakpoints) { + corBreakpoint.Activate(0); + } + tempBreakpoints.Clear(); + // No real purpose - just additional check if (callbackInterface.IsInCallback) throw new DebuggerException("Can not raise event within callback."); TraceMessage ("Debugger event: OnPaused()"); @@ -287,19 +279,19 @@ namespace Debugger TraceMessage ("Skipping OnPaused delegate because process has exited"); break; } - d.DynamicInvoke(this, new ProcessEventArgs(this)); + d.DynamicInvoke(this, e); } } } - protected virtual void OnResumed() + void OnResumed() { AssertRunning(); if (callbackInterface.IsInCallback) throw new DebuggerException("Can not raise event within callback."); TraceMessage ("Debugger event: OnResumed()"); if (Resumed != null) { - Resumed(this, new ProcessEventArgs(this)); + Resumed(this, new DebuggerEventArgs() { Process = this }); } } @@ -307,30 +299,32 @@ namespace Debugger #region PauseSession & DebugeeState - PauseSession pauseSession; - DebuggeeState debuggeeState; + long pauseSession; + long nextPauseSession = 1; + long debuggeeState; + long nextDebuggeeState = 1; /// /// Indentification of the current debugger session. This value changes whenever debugger is continued /// - public PauseSession PauseSession { + public long PauseSession { get { return pauseSession; } } /// /// Indentification of the state of the debugee. This value changes whenever the state of the debugee significatntly changes /// - public DebuggeeState DebuggeeState { + public long DebuggeeState { get { return debuggeeState; } } /// Puts the process into a paused state - internal void NotifyPaused(PausedReason pauseReason) + internal void NotifyPaused() { AssertRunning(); - pauseSession = new PauseSession(this, pauseReason); - if (debuggeeState == null) { - debuggeeState = new DebuggeeState(this); + pauseSession = nextPauseSession++; + if (debuggeeState == 0) { + debuggeeState = nextDebuggeeState++; } } @@ -338,44 +332,13 @@ namespace Debugger internal void NotifyResumed(DebuggeeStateAction action) { AssertPaused(); - pauseSession = null; + pauseSession = 0; if (action == DebuggeeStateAction.Clear) { - if (debuggeeState == null) throw new DebuggerException("Debugee state already cleared"); - debuggeeState = null; - this.ExpressionsCache.Clear(); + if (debuggeeState == 0) throw new DebuggerException("Debugee state already cleared"); + debuggeeState = 0; } } - /// Sets up the eviroment and raises user events - internal void RaisePausedEvents() - { - AssertPaused(); - DisableAllSteppers(); - CheckSelectedStackFrames(); - SelectMostRecentStackFrameWithLoadedSymbols(); - - // if CurrentException is set an exception has occurred. - if (SelectedThread.CurrentException != null) { - ExceptionEventArgs args = new ExceptionEventArgs(this, this.SelectedThread.CurrentException, this.SelectedThread.CurrentExceptionType, this.SelectedThread.CurrentExceptionIsUnhandled); - OnExceptionThrown(args); - // clear exception, it is being processed by the debugger. - this.SelectedThread.CurrentException = null; - // The event could have resumed or killed the process - if (this.IsRunning || this.TerminateCommandIssued || this.HasExited) return; - } - - while(BreakpointHitEventQueue.Count > 0) { - Breakpoint breakpoint = BreakpointHitEventQueue.Dequeue(); - breakpoint.NotifyHit(); - // The event could have resumed or killed the process - if (this.IsRunning || this.TerminateCommandIssued || this.HasExited) return; - } - - OnPaused(); - // The event could have resumed the process - if (this.IsRunning || this.TerminateCommandIssued || this.HasExited) return; - } - #endregion internal void AssertPaused() @@ -393,7 +356,7 @@ namespace Debugger } public bool IsRunning { - get { return pauseSession == null; } + get { return pauseSession == 0; } } public uint Id { @@ -406,26 +369,29 @@ namespace Debugger bool hasExited = false; - public event EventHandler Exited; - public bool HasExited { get { return hasExited; } } - internal void NotifyHasExited() + internal void OnExited() { if(!hasExited) { hasExited = true; if (Exited != null) { - Exited(this, new ProcessEventArgs(this)); + Exited(this, new DebuggerEventArgs() { Process = this }); } // Expire pause seesion first if (IsPaused) { NotifyResumed(DebuggeeStateAction.Clear); } - debugger.Processes.Remove(this); + debugger.processes.Remove(this); + + if (debugger.processes.Count == 0) { + // Exit callback and then terminate the debugger + this.Debugger.MTA2STA.AsyncCall( delegate { this.Debugger.TerminateDebugger(); } ); + } } } @@ -435,15 +401,20 @@ namespace Debugger corProcess.Stop(uint.MaxValue); // Infinite; ignored anyway - NotifyPaused(PausedReason.ForcedBreak); - RaisePausedEvents(); + NotifyPaused(); + OnPaused(new DebuggerEventArgs() { Process = this }); } public void Detach() { if (IsRunning) { corProcess.Stop(uint.MaxValue); - NotifyPaused(PausedReason.ForcedBreak); + NotifyPaused(); + } + + // Deactivate breakpoints + foreach (Breakpoint b in this.Debugger.Breakpoints) { + b.IsEnabled = false; } // This is necessary for detach @@ -457,8 +428,7 @@ namespace Debugger corProcess.Detach(); // modules - foreach(Module m in this.Modules) - { + foreach(Module m in this.Modules) { m.Dispose(); } @@ -467,7 +437,7 @@ namespace Debugger // threads this.threads.Clear(); - NotifyHasExited(); + OnExited(); } public void Continue() @@ -476,9 +446,24 @@ namespace Debugger WaitForPause(); } + public void RunTo(string fileName, int line, int column) + { + foreach(Module module in this.Modules) { + SourcecodeSegment segment = SourcecodeSegment.Resolve(module, fileName, line, column); + if (segment != null) { + ICorDebugFunctionBreakpoint corBreakpoint = segment.CorFunction.GetILCode().CreateBreakpoint((uint)segment.ILStart); + corBreakpoint.Activate(1); + this.tempBreakpoints.Add(corBreakpoint); + } + } + if (this.IsPaused) { + AsyncContinue(); + } + } + internal Thread[] UnsuspendedThreads { get { - List unsuspendedThreads = new List(this.Threads.Count); + List unsuspendedThreads = new List(); foreach(Thread t in this.Threads) { if (!t.Suspended) unsuspendedThreads.Add(t); @@ -569,63 +554,6 @@ namespace Debugger // This is done once ExitProcess callback is received } - /// - /// Clears the internal Expression cache used too speed up Expression evaluation. - /// Use this if your code evaluates expressions in a way which would cause - /// the cache to grow too large. The cache holds PermanentReferences so it - /// shouldn't grow larger than a few hundred items. - /// - public void ClearExpressionCache() - { - if (this.ExpressionsCache != null ){ - this.ExpressionsCache.Clear(); - } - } - - void SelectSomeThread() - { - if (this.SelectedThread != null && !this.SelectedThread.IsInValidState) { - this.SelectedThread = null; - } - if (this.SelectedThread == null) { - foreach(Thread thread in this.Threads) { - if (thread.IsInValidState) { - this.SelectedThread = thread; - break; - } - } - } - } - - internal void CheckSelectedStackFrames() - { - foreach(Thread thread in this.Threads) { - if (thread.IsInValidState) { - if (thread.SelectedStackFrame != null && thread.SelectedStackFrame.IsInvalid) { - thread.SelectedStackFrame = null; - } - } else { - thread.SelectedStackFrame = null; - } - } - } - - internal void SelectMostRecentStackFrameWithLoadedSymbols() - { - SelectSomeThread(); - if (this.SelectedThread != null) { - this.SelectedThread.SelectedStackFrame = null; - foreach (StackFrame stackFrame in this.SelectedThread.Callstack) { - if (stackFrame.HasSymbols) { - if (this.Options.StepOverDebuggerAttributes && stackFrame.MethodInfo.IsNonUserCode) - continue; - this.SelectedThread.SelectedStackFrame = stackFrame; - break; - } - } - } - } - internal Stepper GetStepper(ICorDebugStepper corStepper) { foreach(Stepper stepper in this.Steppers) { @@ -686,69 +614,47 @@ namespace Debugger #region Break at begining - private void OnModulesAdded(object sender, CollectionItemEventArgs e) + int lastAssignedModuleOrderOfLoading = 0; + + internal void OnModuleLoaded(Module module) { - if (BreakAtBeginning) { - if (e.Item.SymReader == null) return; // No symbols + module.OrderOfLoading = lastAssignedModuleOrderOfLoading++; + + foreach (Breakpoint b in this.Debugger.Breakpoints) { + b.SetBreakpoint(module); + } + + if (this.BreakInMain) { + if (module.SymReader == null) return; // No symbols try { // create a BP at entry point - uint entryPoint = e.Item.SymReader.GetUserEntryPoint(); + uint entryPoint = module.SymReader.GetUserEntryPoint(); if (entryPoint == 0) return; // no EP - var mainFunction = e.Item.CorModule.GetFunctionFromToken(entryPoint); - var corBreakpoint = mainFunction.CreateBreakpoint(); + var corBreakpoint = module.CorModule.GetFunctionFromToken(entryPoint).CreateBreakpoint(); corBreakpoint.Activate(1); - - // create a SD BP - var breakpoint = new Breakpoint(this.debugger, corBreakpoint); - this.debugger.Breakpoints.Add(breakpoint); - breakpoint.Hit += delegate { - if (breakpoint != null) - breakpoint.Remove(); - breakpoint = null; - }; + this.tempBreakpoints.Add(corBreakpoint); } catch { // the app does not have an entry point - COM exception } - BreakAtBeginning = false; + + this.BreakInMain = false; } - if (ModulesAdded != null) - ModulesAdded(this, new ModuleEventArgs(e.Item)); + if (this.ModuleLoaded != null) { + this.ModuleLoaded(this, new ModuleEventArgs(module)); + } } - #endregion - - public event EventHandler ModulesAdded; - - public StackFrame GetCurrentExecutingFrame() + internal void OnModuleUnloaded(Module module) { - if (IsRunning || SelectedThread == null) - return null; - - if (IsSelectedFrameForced()) { - return SelectedStackFrame; // selected from callstack or threads pads - } + module.Dispose(); - if (SelectedStackFrame != null) { - if (SelectedThread.MostRecentStackFrame != null) { - if (SelectedStackFrame.HasSymbols && SelectedThread.MostRecentStackFrame.HasSymbols) - return SelectedStackFrame; - else - return SelectedThread.MostRecentStackFrame; - } else { - return SelectedThread.MostRecentStackFrame; - } - } else { - return SelectedThread.MostRecentStackFrame; + if (this.ModuleUnloaded != null) { + this.ModuleUnloaded(this, new ModuleEventArgs(module)); } } - public bool IsSelectedFrameForced() - { - return pauseSession.PausedReason == PausedReason.CurrentFunctionChanged || - pauseSession.PausedReason == PausedReason.CurrentThreadChanged || - pauseSession.PausedReason == PausedReason.EvalComplete; - } + #endregion } } diff --git a/src/AddIns/Debugger/Debugger.Core/ProcessCollection.cs b/src/AddIns/Debugger/Debugger.Core/ProcessCollection.cs deleted file mode 100644 index b155531926..0000000000 --- a/src/AddIns/Debugger/Debugger.Core/ProcessCollection.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using System; -using Debugger.Interop.CorDebug; - -namespace Debugger -{ - public class ProcessCollection: CollectionWithEvents - { - public ProcessCollection(NDebugger debugger): base(debugger) {} - - internal Process this[ICorDebugProcess corProcess] { - get { - foreach (Process process in this) { - if (process.CorProcess == corProcess) { - return process; - } - } - return null; - } - } - - protected override void OnRemoved(Process item) - { - base.OnRemoved(item); - - if (this.Count == 0) { - // Exit callback and then terminate the debugger - this.Debugger.MTA2STA.AsyncCall( delegate { this.Debugger.TerminateDebugger(); } ); - } - } - } -} diff --git a/src/AddIns/Debugger/Debugger.Core/ProcessEventArgs.cs b/src/AddIns/Debugger/Debugger.Core/ProcessEventArgs.cs deleted file mode 100644 index e28f81aa15..0000000000 --- a/src/AddIns/Debugger/Debugger.Core/ProcessEventArgs.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using System; - -namespace Debugger -{ - [Serializable] - public class ProcessEventArgs: DebuggerEventArgs - { - Process process; - - public Process Process { - get { return process; } - } - - public ProcessEventArgs(Process process): base(process == null ? null : process.Debugger) - { - this.process = process; - } - } -} diff --git a/src/AddIns/Debugger/Debugger.Core/Properties/AssemblyInfo.cs b/src/AddIns/Debugger/Debugger.Core/Properties/AssemblyInfo.cs index 6c9f5b87c5..ecd6793867 100644 --- a/src/AddIns/Debugger/Debugger.Core/Properties/AssemblyInfo.cs +++ b/src/AddIns/Debugger/Debugger.Core/Properties/AssemblyInfo.cs @@ -13,5 +13,5 @@ using System.Reflection; [assembly: AssemblyConfiguration("")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -[assembly: AssemblyCopyright("2005-2008 David Srbecký")] +[assembly: AssemblyCopyright("2005-2012 David Srbecký")] [assembly: AssemblyVersion("4.0.0.0")] diff --git a/src/AddIns/Debugger/Debugger.Core/SourcecodeSegment.cs b/src/AddIns/Debugger/Debugger.Core/SourcecodeSegment.cs index 55b5f92b68..af985081b4 100644 --- a/src/AddIns/Debugger/Debugger.Core/SourcecodeSegment.cs +++ b/src/AddIns/Debugger/Debugger.Core/SourcecodeSegment.cs @@ -13,68 +13,18 @@ namespace Debugger { public class SourcecodeSegment: DebuggerObject { - Module module; - - string filename; - string typename; - byte[] checkSum; - int startLine; - int startColumn; - int endLine; - int endColumn; - - ICorDebugFunction corFunction; - int ilStart; - int ilEnd; - int[] stepRanges; - - public Module Module { - get { return module; } - } - - public string Filename { - get { return filename; } - } - - public string Typename { - get { return typename; } - } - - public byte[] CheckSum { - get { return checkSum; } - } - - public int StartLine { - get { return startLine; } - } - - public int StartColumn { - get { return startColumn; } - } - - public int EndLine { - get { return endLine; } - } - - public int EndColumn { - get { return endColumn; } - } - - internal ICorDebugFunction CorFunction { - get { return corFunction; } - } - - public int ILStart { - get { return ilStart; } - } - - public int ILEnd { - get { return ilEnd; } - } - - public int[] StepRanges { - get { return stepRanges; } - } + public Module Module { get; private set; } + public string Filename { get; private set; } + public string Typename { get; private set; } + public byte[] CheckSum { get; private set; } + public int StartLine { get; private set; } + public int StartColumn { get; private set; } + public int EndLine { get; private set; } + public int EndColumn { get; private set; } + internal ICorDebugFunction CorFunction { get; private set; } + public int ILStart { get; private set; } + public int ILEnd { get; private set; } + public int[] StepRanges { get; private set; } private SourcecodeSegment() { @@ -150,7 +100,7 @@ namespace Debugger } } - static ISymUnmanagedDocument GetSymDocumentFromFilename(Module module, string filename, byte[] checksum) + static ISymUnmanagedDocument GetSymDocumentFromFilename(Module module, string filename) { if (filename == null) throw new ArgumentNullException("filename"); @@ -174,15 +124,17 @@ namespace Debugger return null; } - public static SourcecodeSegment Resolve(Module module, string fileName, byte[] checkSum, int line, int column) + public static SourcecodeSegment Resolve(Module module, string fileName, int line, int column) { // Do not use ISymUnmanagedReader.GetDocument! It is broken if two files have the same name // Do not use ISymUnmanagedMethod.GetOffset! It sometimes returns negative offset + if (fileName == null) return null; + ISymUnmanagedReader symReader = module.SymReader; if (symReader == null) return null; // No symbols - ISymUnmanagedDocument symDoc = GetSymDocumentFromFilename(module, fileName, checkSum); + ISymUnmanagedDocument symDoc = GetSymDocumentFromFilename(module, fileName); if (symDoc == null) return null; // Document not found ISymUnmanagedMethod symMethod; @@ -202,17 +154,17 @@ namespace Debugger // If the desired breakpoint position is before the end of the sequence point if (line < sqPoint.EndLine || (line == sqPoint.EndLine && column < sqPoint.EndColumn)) { SourcecodeSegment segment = new SourcecodeSegment(); - segment.module = module; - segment.filename = symDoc.GetURL(); - segment.checkSum = symDoc.GetCheckSum(); - segment.startLine = (int)sqPoint.Line; - segment.startColumn = (int)sqPoint.Column; - segment.endLine = (int)sqPoint.EndLine; - segment.endColumn = (int)sqPoint.EndColumn; - segment.corFunction = module.CorModule.GetFunctionFromToken(symMethod.GetToken()); - segment.ilStart = (int)sqPoint.Offset; - segment.ilEnd = (int)sqPoint.Offset; - segment.stepRanges = null; + segment.Module = module; + segment.Filename = symDoc.GetURL(); + segment.CheckSum = symDoc.GetCheckSum(); + segment.StartLine = (int)sqPoint.Line; + segment.StartColumn = (int)sqPoint.Column; + segment.EndLine = (int)sqPoint.EndLine; + segment.EndColumn = (int)sqPoint.EndColumn; + segment.CorFunction = module.CorModule.GetFunctionFromToken(symMethod.GetToken()); + segment.ILStart = (int)sqPoint.Offset; + segment.ILEnd = (int)sqPoint.Offset; + segment.StepRanges = null; return segment; } } @@ -300,21 +252,21 @@ namespace Debugger } SourcecodeSegment segment = new SourcecodeSegment(); - segment.module = module; - segment.filename = GetFilenameFromSymDocument(module, sequencePoints[i].Document); - segment.checkSum = sequencePoints[i].Document.GetCheckSum(); - segment.startLine = (int)sequencePoints[i].Line; - segment.startColumn = (int)sequencePoints[i].Column; - segment.endLine = (int)sequencePoints[i].EndLine; - segment.endColumn = (int)sequencePoints[i].EndColumn; - segment.corFunction = corFunction; - segment.ilStart = ilStart; - segment.ilEnd = ilEnd; - segment.stepRanges = stepRanges.ToArray(); + segment.Module = module; + segment.Filename = GetFilenameFromSymDocument(module, sequencePoints[i].Document); + segment.CheckSum = sequencePoints[i].Document.GetCheckSum(); + segment.StartLine = (int)sequencePoints[i].Line; + segment.StartColumn = (int)sequencePoints[i].Column; + segment.EndLine = (int)sequencePoints[i].EndLine; + segment.EndColumn = (int)sequencePoints[i].EndColumn; + segment.CorFunction = corFunction; + segment.ILStart = ilStart; + segment.ILEnd = ilEnd; + segment.StepRanges = stepRanges.ToArray(); // VB.NET sometimes produces temporary files which it then deletes // (eg 17d14f5c-a337-4978-8281-53493378c1071.vb) - string filename = Path.GetFileName(segment.filename); + string filename = Path.GetFileName(segment.Filename); if (filename.Length == 40 && filename.EndsWith(".vb")) { bool guidName = true; foreach(char c in filename.Substring(0, filename.Length - 3)) { @@ -343,7 +295,7 @@ namespace Debugger { return string.Format("{0}:{1},{2}-{3},{4}", Path.GetFileName(this.Filename ?? string.Empty), - this.startLine, this.startColumn, this.endLine, this.endColumn); + this.StartLine, this.StartColumn, this.EndLine, this.EndColumn); } #region Decompiled breakpoint @@ -352,17 +304,17 @@ namespace Debugger { try { SourcecodeSegment segment = new SourcecodeSegment(); - segment.module = module; - segment.typename = null; - segment.checkSum = null; - segment.startLine = line; - segment.startColumn = 0; - segment.endLine = line; - segment.endColumn = 0; - segment.corFunction = module.CorModule.GetFunctionFromToken((uint)metadataToken); - segment.ilStart = iLOffset; - segment.ilEnd = iLOffset; - segment.stepRanges = null; + segment.Module = module; + segment.Typename = null; + segment.CheckSum = null; + segment.StartLine = line; + segment.StartColumn = 0; + segment.EndLine = line; + segment.EndColumn = 0; + segment.CorFunction = module.CorModule.GetFunctionFromToken((uint)metadataToken); + segment.ILStart = iLOffset; + segment.ILEnd = iLOffset; + segment.StepRanges = null; return segment; } catch { @@ -372,19 +324,19 @@ namespace Debugger public static SourcecodeSegment ResolveForIL(Module module, ICorDebugFunction corFunction, int line, int offset, int[] ranges) { - try { + try { SourcecodeSegment segment = new SourcecodeSegment(); - segment.module = module; - segment.typename = null; - segment.checkSum = null; - segment.startLine = line; - segment.startColumn = 0; - segment.endLine = line; - segment.endColumn = 0; - segment.corFunction = corFunction; - segment.ilStart = offset; - segment.ilEnd = ranges[1]; - segment.stepRanges = ranges; + segment.Module = module; + segment.Typename = null; + segment.CheckSum = null; + segment.StartLine = line; + segment.StartColumn = 0; + segment.EndLine = line; + segment.EndColumn = 0; + segment.CorFunction = corFunction; + segment.ILStart = offset; + segment.ILEnd = ranges[1]; + segment.StepRanges = ranges; return segment; } catch { diff --git a/src/AddIns/Debugger/Debugger.Core/StackFrame.cs b/src/AddIns/Debugger/Debugger.Core/StackFrame.cs index 0b6cf9e53b..c5aecad628 100644 --- a/src/AddIns/Debugger/Debugger.Core/StackFrame.cs +++ b/src/AddIns/Debugger/Debugger.Core/StackFrame.cs @@ -22,7 +22,7 @@ namespace Debugger Process process; ICorDebugILFrame corILFrame; - object corILFramePauseSession; + long corILFramePauseSession; ICorDebugFunction corFunction; DebugMethodInfo methodInfo; @@ -83,14 +83,14 @@ namespace Debugger { this.process = thread.Process; this.thread = thread; - this.appDomain = process.AppDomains[corILFrame.GetFunction().GetClass().GetModule().GetAssembly().GetAppDomain()]; + this.appDomain = process.GetAppDomain(corILFrame.GetFunction().GetClass().GetModule().GetAssembly().GetAppDomain()); this.corILFrame = corILFrame; this.corILFramePauseSession = process.PauseSession; this.corFunction = corILFrame.GetFunction(); this.chainIndex = chainIndex; this.frameIndex = frameIndex; - MetaDataImport metaData = thread.Process.Modules[corFunction.GetClass().GetModule()].MetaData; + MetaDataImport metaData = thread.Process.GetModule(corFunction.GetClass().GetModule()).MetaData; int methodGenArgs = metaData.EnumGenericParams(corFunction.GetToken()).Length; // Class parameters are first, then the method ones List corGenArgs = ((ICorDebugILFrame2)corILFrame).EnumerateTypeParameters().ToList(); @@ -241,40 +241,21 @@ namespace Debugger } } - /// - /// Determine whether the instrustion pointer can be set to given location - /// - /// Best possible location. Null is not possible. - public SourcecodeSegment CanSetIP(string filename, int line, int column) - { - return SetIP(true, filename, line, column); - } - - /// - /// Set the instrustion pointer to given location - /// - /// Best possible location. Null is not possible. - public SourcecodeSegment SetIP(string filename, int line, int column) - { - return SetIP(false, filename, line, column); - } - - SourcecodeSegment SetIP(bool simulate, string filename, int line, int column) + public SourcecodeSegment SetIP(string filename, int line, int column, bool dryRun) { process.AssertPaused(); - SourcecodeSegment segment = SourcecodeSegment.Resolve(this.MethodInfo.DebugModule, filename, null, line, column); + SourcecodeSegment segment = SourcecodeSegment.Resolve(this.MethodInfo.DebugModule, filename, line, column); if (segment != null && segment.CorFunction.GetToken() == this.MethodInfo.MetadataToken) { try { - if (simulate) { + if (dryRun) { CorILFrame.CanSetIP((uint)segment.ILStart); } else { - // Invalidates all frames and chains for the current thread CorILFrame.SetIP((uint)segment.ILStart); + // Invalidates all frames and chains for the current thread process.NotifyResumed(DebuggeeStateAction.Keep); - process.NotifyPaused(PausedReason.SetIP); - process.RaisePausedEvents(); + process.NotifyPaused(); } } catch { return null; @@ -345,6 +326,8 @@ namespace Debugger ICorDebugValue GetArgumentCorValue(int index) { + this.Process.AssertPaused(); + ICorDebugValue corValue; try { // Non-static methods include 'this' as first argument @@ -380,6 +363,17 @@ namespace Debugger return loc.GetValue(this); } + public Value GetLocalVariableValue(uint address) + { + this.Process.AssertPaused(); + try { + return new Value(this.AppDomain, this.CorILFrame.GetLocalVariable(address)); + } catch (COMException e) { + if ((uint)e.ErrorCode == 0x80131304) throw new GetValueException("Unavailable in optimized code"); + throw; + } + } + /// Get instance of 'this'. It works well with delegates and enumerators. [Debugger.Tests.Ignore] public Value GetLocalVariableThis() diff --git a/src/AddIns/Debugger/Debugger.Core/Stepper.cs b/src/AddIns/Debugger/Debugger.Core/Stepper.cs index c8bb8c8d94..3320242df4 100644 --- a/src/AddIns/Debugger/Debugger.Core/Stepper.cs +++ b/src/AddIns/Debugger/Debugger.Core/Stepper.cs @@ -8,6 +8,14 @@ namespace Debugger { enum StepperOperation {StepIn, StepOver, StepOut}; + /// + /// - During evaluation some chains may be temporarly removed + /// - When two events are invoked and JMC is active, step out skips the second function + /// - Step out and step over works properly for exceptions + /// - Evaluation kills stepper overs on active frame + /// - StepRange callbacks go first (probably in order), StepOut callback are called after that + /// - StepRange is much slower then StepOut + /// class Stepper { StackFrame stackFrame; @@ -118,7 +126,7 @@ namespace Debugger } [Serializable] - class StepperEventArgs: ProcessEventArgs + class StepperEventArgs: EventArgs { Stepper stepper; CorDebugStepReason reason; @@ -131,7 +139,7 @@ namespace Debugger get { return reason; } } - public StepperEventArgs(Stepper stepper, CorDebugStepReason reason): base(stepper.Process) + public StepperEventArgs(Stepper stepper, CorDebugStepReason reason) { this.stepper = stepper; this.reason = reason; diff --git a/src/AddIns/Debugger/Debugger.Core/Stepping.txt b/src/AddIns/Debugger/Debugger.Core/Stepping.txt deleted file mode 100644 index e83afbac90..0000000000 --- a/src/AddIns/Debugger/Debugger.Core/Stepping.txt +++ /dev/null @@ -1,7 +0,0 @@ -== Notes == -- During evaluation some chains may be temporarly removed -- When two events are invoked and JMC is active, step out skips the second function -- Step out and step over works properly for exceptions -- Evaluation kills stepper overs on active frame -- StepRange callbacks go first (probably in order), StepOut callback are called after that -- StepRange is much slower then StepOut diff --git a/src/AddIns/Debugger/Debugger.Core/Thread.cs b/src/AddIns/Debugger/Debugger.Core/Thread.cs index 9f25b02822..0d7226a707 100644 --- a/src/AddIns/Debugger/Debugger.Core/Thread.cs +++ b/src/AddIns/Debugger/Debugger.Core/Thread.cs @@ -22,19 +22,13 @@ namespace Debugger Stepper currentStepIn; - StackFrame selectedStackFrame; - - Exception currentException; - DebuggeeState currentException_DebuggeeState; - ExceptionType currentExceptionType; - bool currentExceptionIsUnhandled; - - public event EventHandler NameChanged; - public event EventHandler Exited; - public Process Process { get { return process; } } + + public AppDomain AppDomain { + get { return process.GetAppDomain(this.corThread.GetAppDomain()); } + } [Debugger.Tests.Ignore] public uint ID { @@ -89,20 +83,9 @@ namespace Debugger if (this.HasExited) throw new DebuggerException("Already exited"); process.TraceMessage("Thread " + this.ID + " exited"); - if (process.SelectedThread == this) { - process.SelectedThread = null; - } this.HasExited = true; - OnExited(new ThreadEventArgs(this)); - process.Threads.Remove(this); - } - - protected virtual void OnExited(ThreadEventArgs e) - { - if (Exited != null) { - Exited(this, e); - } + process.threads.Remove(this); } /// If the thread is not at safe point, it is not posible to evaluate @@ -129,7 +112,7 @@ namespace Debugger Value runTimeValue = RuntimeValue; if (runTimeValue.IsNull) return ThreadPriority.Normal; - return (ThreadPriority)(int)runTimeValue.GetMemberValue("m_Priority").PrimitiveValue; + return (ThreadPriority)(int)runTimeValue.GetFieldValue("m_Priority").PrimitiveValue; } } @@ -142,7 +125,7 @@ namespace Debugger process.AssertPaused(); ICorDebugValue corValue = this.CorThread.GetObject(); - return new Value(process.AppDomains[this.CorThread.GetAppDomain()], corValue); + return new Value(process.GetAppDomain(this.CorThread.GetAppDomain()), corValue); } } @@ -154,50 +137,12 @@ namespace Debugger if (!IsInValidState) return string.Empty; Value runtimeValue = RuntimeValue; if (runtimeValue.IsNull) return string.Empty; - Value runtimeName = runtimeValue.GetMemberValue("m_Name"); + Value runtimeName = runtimeValue.GetFieldValue("m_Name"); if (runtimeName.IsNull) return string.Empty; return runtimeName.AsString(100); } } - protected virtual void OnNameChanged(ThreadEventArgs e) - { - if (NameChanged != null) { - NameChanged(this, e); - } - } - - internal void NotifyNameChanged() - { - OnNameChanged(new ThreadEventArgs(this)); - } - - public Exception CurrentException { - get { - if (currentException_DebuggeeState == process.DebuggeeState) { - return currentException; - } else { - return null; - } - } - internal set { currentException = value; } - } - - internal DebuggeeState CurrentException_DebuggeeState { - get { return currentException_DebuggeeState; } - set { currentException_DebuggeeState = value; } - } - - public ExceptionType CurrentExceptionType { - get { return currentExceptionType; } - internal set { currentExceptionType = value; } - } - - public bool CurrentExceptionIsUnhandled { - get { return currentExceptionIsUnhandled; } - internal set { currentExceptionIsUnhandled = value; } - } - /// Tryies to intercept the current exception. /// The intercepted expression stays available through the CurrentException property. /// False, if the exception was already intercepted or @@ -220,9 +165,6 @@ namespace Debugger } if (mostRecentUnoptimized == null) return false; - if (exception == null) - exception = currentException; - try { // Interception will expire the CorValue so keep permanent reference exception.MakeValuePermanent(); @@ -345,30 +287,31 @@ namespace Debugger return stackTrace.ToString(); } - public StackFrame SelectedStackFrame { - get { - if (selectedStackFrame != null && selectedStackFrame.IsInvalid) return null; - if (process.IsRunning) return null; - return selectedStackFrame; - } - set { - selectedStackFrame = value; - } - } - /// /// Returns the most recent stack frame (the one that is currently executing). /// Returns null if callstack is empty. /// public StackFrame MostRecentStackFrame { get { - foreach(StackFrame stackFrame in Callstack) { + foreach(StackFrame stackFrame in this.Callstack) { return stackFrame; } return null; } } + [Debugger.Tests.Ignore] + public StackFrame MostRecentUserStackFrame { + get { + foreach (StackFrame stackFrame in this.Callstack) { + if (!stackFrame.MethodInfo.StepOver) { + return stackFrame; + } + } + return null; + } + } + public bool IsInNativeCode { get { process.AssertPaused(); @@ -380,21 +323,4 @@ namespace Debugger } } } - - [Serializable] - public class ThreadEventArgs : ProcessEventArgs - { - Thread thread; - - public Thread Thread { - get { - return thread; - } - } - - public ThreadEventArgs(Thread thread): base(thread.Process) - { - this.thread = thread; - } - } } diff --git a/src/AddIns/Debugger/Debugger.Core/ThreadCollection.cs b/src/AddIns/Debugger/Debugger.Core/ThreadCollection.cs deleted file mode 100644 index b8bd30ef1c..0000000000 --- a/src/AddIns/Debugger/Debugger.Core/ThreadCollection.cs +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using System; -using Debugger.Interop.CorDebug; - -namespace Debugger -{ - public class ThreadCollection: CollectionWithEvents - { - public ThreadCollection(NDebugger debugger): base(debugger) {} - - Thread selected; - - public Thread Selected { - get { return selected; } - set { selected = value; } - } - - public Thread Find(Predicate predicate) - { - if (predicate == null) - return null; - - foreach (var thread in this) - { - if (predicate(thread)) - return thread; - } - - return null; - } - - internal bool Contains(ICorDebugThread corThread) - { - foreach(Thread thread in this) { - if (thread.CorThread == corThread) return true; - } - return false; - } - } -} diff --git a/src/AddIns/Debugger/Debugger.Core/Value.cs b/src/AddIns/Debugger/Debugger.Core/Value.cs index e104f05c19..64f326c020 100644 --- a/src/AddIns/Debugger/Debugger.Core/Value.cs +++ b/src/AddIns/Debugger/Debugger.Core/Value.cs @@ -23,7 +23,7 @@ namespace Debugger { AppDomain appDomain; ICorDebugValue corValue; - PauseSession corValue_pauseSession; + long corValue_pauseSession; DebugType type; // Permanently stored as convinience so that it survives Continue @@ -113,8 +113,7 @@ namespace Debugger /// Value is valid only until the debuggee is resummed. public bool IsInvalid { get { - return corValue_pauseSession != this.Process.PauseSession && - !(corValue is ICorDebugHandleValue); + return corValue_pauseSession != this.Process.PauseSession && !(corValue is ICorDebugHandleValue); } } @@ -193,11 +192,11 @@ namespace Debugger } // Box value type - public Value Box() + public Value Box(Thread evalThread) { byte[] rawValue = this.CorGenericValue.GetRawValue(); // The type must not be a primive type (always true in current design) - ICorDebugReferenceValue corRefValue = Eval.NewObjectNoConstructor(this.Type).CorReferenceValue; + ICorDebugReferenceValue corRefValue = Eval.NewObjectNoConstructor(evalThread, this.Type).CorReferenceValue; // Make the reference to box permanent corRefValue = ((ICorDebugHeapValue2)corRefValue.Dereference()).CreateHandle(CorDebugHandleType.HANDLE_STRONG); // Create new value @@ -207,8 +206,17 @@ namespace Debugger return newValue; } + /// If we are sure it is heap value we do not need eval. [Debugger.Tests.Ignore] - public Value GetPermanentReference() + public Value GetPermanentReferenceOfHeapValue() + { + if (this.CorValue is ICorDebugReferenceValue) { + return GetPermanentReference(null); + } + throw new DebuggerException("Value is not a heap value"); + } + + public Value GetPermanentReference(Thread evalThread) { if (this.CorValue is ICorDebugHandleValue) { return this; @@ -219,12 +227,12 @@ namespace Debugger if (deRef is ICorDebugHeapValue2) { return new Value(appDomain, ((ICorDebugHeapValue2)deRef).CreateHandle(CorDebugHandleType.HANDLE_STRONG)); } else { - // For exampe int* is a refernce not pointing to heap + // For exampe int* is a reference not pointing to heap // TODO: It isn't permanent return this; } } else { - return this.Box(); + return this.Box(evalThread); } } @@ -242,13 +250,13 @@ namespace Debugger } /// Copy the acutal value from some other Value object - public void SetValue(Value newValue) + public void SetValue(Thread evalThread, Value newValue) { ICorDebugValue newCorValue = newValue.CorValue; if (this.CorValue is ICorDebugReferenceValue) { if (!(newCorValue is ICorDebugReferenceValue)) - newCorValue = newValue.Box().CorValue; + newCorValue = newValue.Box(evalThread).CorValue; ((ICorDebugReferenceValue)this.CorValue).SetValue(((ICorDebugReferenceValue)newCorValue).GetValue()); } else { this.CorGenericValue.SetRawValue(newValue.CorGenericValue.GetRawValue()); @@ -273,22 +281,24 @@ namespace Debugger return CorGenericValue.GetValue(this.Type.PrimitiveType); } } - set { - if (this.Type.FullName == typeof(string).FullName) { - this.SetValue(Eval.NewString(this.AppDomain, value.ToString())); - } else { - if (this.Type.PrimitiveType == null) - throw new DebuggerException("Value is not a primitive type"); - if (value == null) - throw new DebuggerException("Can not set primitive value to null"); - object newValue; - try { - newValue = Convert.ChangeType(value, this.Type.PrimitiveType); - } catch { - throw new NotSupportedException("Can not convert " + value.GetType().ToString() + " to " + this.Type.PrimitiveType.ToString()); - } - CorGenericValue.SetValue(newValue); + } + + public void SetPrimitiveValue(Thread evalThread, object value) + { + if (this.Type.FullName == typeof(string).FullName) { + this.SetValue(evalThread, Eval.NewString(evalThread, value.ToString())); + } else { + if (this.Type.PrimitiveType == null) + throw new DebuggerException("Value is not a primitive type"); + if (value == null) + throw new DebuggerException("Can not set primitive value to null"); + object newValue; + try { + newValue = Convert.ChangeType(value, this.Type.PrimitiveType); + } catch { + throw new NotSupportedException("Can not convert " + value.GetType().ToString() + " to " + this.Type.PrimitiveType.ToString()); } + CorGenericValue.SetValue(newValue); } } @@ -370,10 +380,10 @@ namespace Debugger return CorArrayValue.GetElement(indices); } - public void SetArrayElement(int[] elementIndices, Value newVal) + public void SetArrayElement(Thread evalThread, int[] elementIndices, Value newVal) { Value elem = GetArrayElement(elementIndices); - elem.SetValue(newVal); + elem.SetValue(evalThread, newVal); } /// Returns all elements in the array @@ -409,88 +419,85 @@ namespace Debugger } } - #region Convenience overload methods - /// Get a field or property of an object with a given name. /// Null if not found - public Value GetMemberValue(string name) + public Value GetMemberValue(Thread evalThread, string name) { MemberInfo memberInfo = this.Type.GetMember(name, DebugType.BindingFlagsAllInScope, DebugType.IsFieldOrNonIndexedProperty); if (memberInfo == null) return null; - return GetMemberValue(memberInfo); + return GetMemberValue(evalThread, memberInfo); } /// Get the value of given member. - public Value GetMemberValue(MemberInfo memberInfo, params Value[] arguments) + public Value GetMemberValue(Thread evalThread, MemberInfo memberInfo, params Value[] arguments) { - return GetMemberValue(this, memberInfo, arguments); + return GetMemberValue(evalThread, this, memberInfo, arguments); } - #endregion - /// Get the value of given member. /// null if member is static - public static Value GetMemberValue(Value objectInstance, MemberInfo memberInfo, params Value[] arguments) + public static Value GetMemberValue(Thread evalThread, Value objectInstance, MemberInfo memberInfo, params Value[] arguments) { if (memberInfo is FieldInfo) { if (arguments.Length > 0) throw new GetValueException("Arguments can not be used for a field"); - return GetFieldValue(objectInstance, (FieldInfo)memberInfo); + return GetFieldValue(evalThread, objectInstance, (FieldInfo)memberInfo); } else if (memberInfo is PropertyInfo) { - return GetPropertyValue(objectInstance, (PropertyInfo)memberInfo, arguments); + return GetPropertyValue(evalThread, objectInstance, (PropertyInfo)memberInfo, arguments); } else if (memberInfo is MethodInfo) { - return InvokeMethod(objectInstance, (MethodInfo)memberInfo, arguments); + return InvokeMethod(evalThread, objectInstance, (MethodInfo)memberInfo, arguments); } throw new DebuggerException("Unknown member type: " + memberInfo.GetType()); } - #region Convenience overload methods - - /// Get the value of given field. - public Value GetFieldValue(FieldInfo fieldInfo) + public static void SetFieldValue(Thread evalThread, Value objectInstance, FieldInfo fieldInfo, Value newValue) { - return Value.GetFieldValue(this, fieldInfo); + Value val = GetFieldValue(evalThread, objectInstance, fieldInfo); + if (!fieldInfo.FieldType.IsAssignableFrom(newValue.Type)) + throw new GetValueException("Can not assign {0} to {1}", newValue.Type.FullName, fieldInfo.FieldType.FullName); + val.SetValue(evalThread, newValue); } - #endregion + /// Get the value of given instance field. + public Value GetFieldValue(string name) + { + FieldInfo fieldInfo = this.Type.GetMember(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null); + if (fieldInfo == null) + throw new DebuggerException("Field '{0}' not found", name); + + return new Value(this.AppDomain, GetFieldCorValue(null, this, fieldInfo)); + } - public static void SetFieldValue(Value objectInstance, FieldInfo fieldInfo, Value newValue) + /// Get the value of given field. + public Value GetFieldValue(Thread evalThread, FieldInfo fieldInfo) { - Value val = GetFieldValue(objectInstance, fieldInfo); - if (!fieldInfo.FieldType.IsAssignableFrom(newValue.Type)) - throw new GetValueException("Can not assign {0} to {1}", newValue.Type.FullName, fieldInfo.FieldType.FullName); - val.SetValue(newValue); + return Value.GetFieldValue(evalThread, this, fieldInfo); } /// Get the value of given field. + /// Thread to use for thread-local storage /// null if field is static - public static Value GetFieldValue(Value objectInstance, FieldInfo fieldInfo) + public static Value GetFieldValue(Thread evalThread, Value objectInstance, FieldInfo fieldInfo) { CheckObject(objectInstance, fieldInfo); if (fieldInfo.IsStatic && fieldInfo.IsLiteral) { - return GetLiteralValue((DebugFieldInfo)fieldInfo); + return GetLiteralValue(evalThread, (DebugFieldInfo)fieldInfo); } else { return new Value( ((DebugFieldInfo)fieldInfo).AppDomain, - GetFieldCorValue(objectInstance, fieldInfo) + GetFieldCorValue(evalThread, objectInstance, fieldInfo) ); } } - static ICorDebugValue GetFieldCorValue(Value objectInstance, FieldInfo fieldInfo) + static ICorDebugValue GetFieldCorValue(Thread contextThread, Value objectInstance, FieldInfo fieldInfo) { - Process process = ((DebugFieldInfo)fieldInfo).Process; - // Current frame is used to resolve context specific static values (eg. ThreadStatic) ICorDebugFrame curFrame = null; - if (process.IsPaused && - process.SelectedThread != null && - process.SelectedThread.MostRecentStackFrame != null && - process.SelectedThread.MostRecentStackFrame.CorILFrame != null) - { - curFrame = process.SelectedThread.MostRecentStackFrame.CorILFrame; + if (contextThread != null && contextThread.MostRecentStackFrame != null && contextThread.MostRecentStackFrame.CorILFrame != null) { + curFrame = contextThread.MostRecentStackFrame.CorILFrame; } try { @@ -504,76 +511,54 @@ namespace Debugger } } - static Value GetLiteralValue(DebugFieldInfo fieldInfo) + static Value GetLiteralValue(Thread evalThread, DebugFieldInfo fieldInfo) { CorElementType corElemType = (CorElementType)fieldInfo.FieldProps.ConstantType; if (corElemType == CorElementType.CLASS) { // Only null literals are allowed - return Eval.CreateValue(fieldInfo.AppDomain, null); + return Eval.CreateValue(evalThread, null); } else if (corElemType == CorElementType.STRING) { string str = Marshal.PtrToStringUni(fieldInfo.FieldProps.ConstantPtr, (int)fieldInfo.FieldProps.ConstantStringLength); - return Eval.CreateValue(fieldInfo.AppDomain, str); + return Eval.CreateValue(evalThread, str); } else { DebugType type = DebugType.CreateFromType(fieldInfo.AppDomain.Mscorlib, DebugType.CorElementTypeToManagedType(corElemType)); if (fieldInfo.FieldType.IsEnum && fieldInfo.FieldType.GetEnumUnderlyingType() == type) { - Value val = Eval.NewObjectNoConstructor((DebugType)fieldInfo.FieldType); - Value backingField = val.GetMemberValue("value__"); + Value val = Eval.NewObjectNoConstructor(evalThread, (DebugType)fieldInfo.FieldType); + Value backingField = val.GetMemberValue(evalThread, "value__"); backingField.CorGenericValue.SetValue(fieldInfo.FieldProps.ConstantPtr); return val; } else { - Value val = Eval.NewObjectNoConstructor(type); + Value val = Eval.NewObjectNoConstructor(evalThread, type); val.CorGenericValue.SetValue(fieldInfo.FieldProps.ConstantPtr); return val; } } } - #region Convenience overload methods - /// Get the value of the property using the get accessor - public Value GetPropertyValue(PropertyInfo propertyInfo, params Value[] arguments) + public Value GetPropertyValue(Thread evalThread, PropertyInfo propertyInfo, params Value[] arguments) { - return GetPropertyValue(this, propertyInfo, arguments); + return GetPropertyValue(evalThread, this, propertyInfo, arguments); } - #endregion - /// Get the value of the property using the get accessor - public static Value GetPropertyValue(Value objectInstance, PropertyInfo propertyInfo, params Value[] arguments) + public static Value GetPropertyValue(Thread evalThread, Value objectInstance, PropertyInfo propertyInfo, params Value[] arguments) { CheckObject(objectInstance, propertyInfo); if (propertyInfo.GetGetMethod() == null) throw new GetValueException("Property does not have a get method"); - Value val = Value.InvokeMethod(objectInstance, (DebugMethodInfo)propertyInfo.GetGetMethod(), arguments); - - return val; - } - - #region Convenience overload methods - - /// Set the value of the property using the set accessor - public Value SetPropertyValue(PropertyInfo propertyInfo, Value newValue) - { - return SetPropertyValue(this, propertyInfo, null, newValue); + return Value.InvokeMethod(evalThread, objectInstance, (DebugMethodInfo)propertyInfo.GetGetMethod(), arguments); } /// Set the value of the property using the set accessor - public Value SetPropertyValue(PropertyInfo propertyInfo, Value[] arguments, Value newValue) + public Value SetPropertyValue(Thread evalThread, PropertyInfo propertyInfo, Value[] arguments, Value newValue) { - return SetPropertyValue(this, propertyInfo, arguments, newValue); + return SetPropertyValue(evalThread, this, propertyInfo, arguments, newValue); } /// Set the value of the property using the set accessor - public static Value SetPropertyValue(Value objectInstance, PropertyInfo propertyInfo, Value newValue) - { - return SetPropertyValue(objectInstance, propertyInfo, null, newValue); - } - - #endregion - - /// Set the value of the property using the set accessor - public static Value SetPropertyValue(Value objectInstance, PropertyInfo propertyInfo, Value[] arguments, Value newValue) + public static Value SetPropertyValue(Thread evalThread, Value objectInstance, PropertyInfo propertyInfo, Value[] arguments, Value newValue) { CheckObject(objectInstance, propertyInfo); @@ -585,25 +570,22 @@ namespace Debugger allParams[0] = newValue; arguments.CopyTo(allParams, 1); - return Value.InvokeMethod(objectInstance, (DebugMethodInfo)propertyInfo.GetSetMethod(), allParams); + return Value.InvokeMethod(evalThread, objectInstance, (DebugMethodInfo)propertyInfo.GetSetMethod(), allParams); } - #region Convenience overload methods - /// Synchronously invoke the method - public Value InvokeMethod(MethodInfo methodInfo, params Value[] arguments) + public Value InvokeMethod(Thread evalThread, MethodInfo methodInfo, params Value[] arguments) { - return InvokeMethod(this, methodInfo, arguments); + return InvokeMethod(evalThread, this, methodInfo, arguments); } - #endregion - /// Synchronously invoke the method - public static Value InvokeMethod(Value objectInstance, MethodInfo methodInfo, params Value[] arguments) + public static Value InvokeMethod(Thread evalThread, Value objectInstance, MethodInfo methodInfo, params Value[] arguments) { CheckObject(objectInstance, methodInfo); return Eval.InvokeMethod( + evalThread, (DebugMethodInfo)methodInfo, methodInfo.IsStatic ? null : objectInstance, arguments ?? new Value[0] @@ -611,32 +593,30 @@ namespace Debugger } /// Invoke the ToString() method - public string InvokeToString(int maxLength = int.MaxValue) + public string InvokeToString(Thread evalThread, int maxLength = int.MaxValue) { + if (this.IsNull) return AsString(maxLength); if (this.Type.IsPrimitive) return AsString(maxLength); if (this.Type.FullName == typeof(string).FullName) return AsString(maxLength); if (this.Type.IsPointer) return "0x" + this.PointerAddress.ToString("X"); // if (!IsObject) // Can invoke on primitives DebugMethodInfo methodInfo = (DebugMethodInfo)this.AppDomain.ObjectType.GetMethod("ToString", new DebugType[] {}); - return Eval.InvokeMethod(methodInfo, this, new Value[] {}).AsString(maxLength); + return Eval.InvokeMethod(evalThread, methodInfo, this, new Value[] {}).AsString(maxLength); } - #region Convenience overload methods - /// Asynchronously invoke the method - public Eval AsyncInvokeMethod(MethodInfo methodInfo, params Value[] arguments) + public Eval AsyncInvokeMethod(Thread evalThread, MethodInfo methodInfo, params Value[] arguments) { - return AsyncInvokeMethod(this, methodInfo, arguments); + return AsyncInvokeMethod(evalThread, this, methodInfo, arguments); } - #endregion - /// Asynchronously invoke the method - public static Eval AsyncInvokeMethod(Value objectInstance, MethodInfo methodInfo, params Value[] arguments) + public static Eval AsyncInvokeMethod(Thread evalThread, Value objectInstance, MethodInfo methodInfo, params Value[] arguments) { CheckObject(objectInstance, methodInfo); return Eval.AsyncInvokeMethod( + evalThread, (DebugMethodInfo)methodInfo, methodInfo.IsStatic ? null : objectInstance, arguments ?? new Value[0] diff --git a/src/AddIns/Debugger/Debugger.Tests/Debugger.Tests.csproj b/src/AddIns/Debugger/Debugger.Tests/Debugger.Tests.csproj index 82684e0616..9c117cdddf 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Debugger.Tests.csproj +++ b/src/AddIns/Debugger/Debugger.Tests/Debugger.Tests.csproj @@ -77,6 +77,10 @@ {3A9AE6AA-BC07-4A2F-972C-581E3AE2F195} NRefactory + + {EC06F96A-AEEC-49D6-B03D-AB87C6EB674C} + Debugger.AddIn + {1D18D788-F7EE-4585-A23B-34DC8EC63CB8} Debugger.Core diff --git a/src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs b/src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs index 9082f28cef..467695b5fd 100644 --- a/src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs +++ b/src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs @@ -31,11 +31,9 @@ namespace Debugger.Tests protected XmlElement snapshotNode; protected int shapshotID; - public StackFrame SelectedStackFrame { - get { - return process.SelectedStackFrame; - } - } + public Thread CurrentThread { get; private set; } + public StackFrame CurrentStackFrame { get; private set; } + public Thread EvalThread { get { return this.CurrentThread; } } public void Continue() { @@ -196,37 +194,40 @@ namespace Debugger.Tests log = ""; lastLogMessage = null; - process = debugger.Start(exeFilename, Path.GetDirectoryName(exeFilename), testName); + process = debugger.Start(exeFilename, Path.GetDirectoryName(exeFilename), testName, false); process.LogMessage += delegate(object sender, MessageEventArgs e) { log += e.Message; lastLogMessage = e.Message; LogEvent("LogMessage", e.Message.Replace("\r",@"\r").Replace("\n",@"\n")); }; - process.Modules.Added += delegate(object sender, CollectionItemEventArgs e) { - LogEvent("ModuleLoaded", e.Item.Name + (e.Item.HasSymbols ? " (Has symbols)" : " (No symbols)")); - }; - process.Paused += delegate(object sender, ProcessEventArgs e) { - LogEvent("DebuggingPaused", e.Process.PauseSession.PausedReason.ToString() + " " + e.Process.SelectedStackFrame.NextStatement.ToString()); + process.ModuleLoaded += delegate(object sender, ModuleEventArgs e) { + LogEvent("ModuleLoaded", e.Module.Name + (e.Module.HasSymbols ? " (Has symbols)" : " (No symbols)")); }; -// process.DebuggingResumed += delegate(object sender, ProcessEventArgs e) { -// LogEvent("DebuggingResumed", e.Process.PausedReason.ToString()); -// }; - process.ExceptionThrown += delegate(object sender, ExceptionEventArgs e) { - StringBuilder msg = new StringBuilder(); - if (process.SelectedThread.InterceptException(e.Exception)) { - msg.Append(e.Exception.ToString()); + process.Paused += delegate(object sender, DebuggerEventArgs e) { + this.CurrentThread = e.Thread; + if (e.Thread != null && e.Thread.IsInValidState) { + this.CurrentStackFrame = e.Thread.MostRecentStackFrame; } else { - // For example, happens on stack overflow - msg.Append("Could not intercept: "); - msg.Append(e.Exception.ToString()); + this.CurrentStackFrame = null; + } + if (e.ExceptionThrown != null) { + StringBuilder msg = new StringBuilder(); + if (CurrentThread.InterceptException(e.ExceptionThrown)) { + msg.Append(e.ExceptionThrown.ToString()); + } else { + // For example, happens on stack overflow + msg.Append("Could not intercept: "); + msg.Append(e.ExceptionThrown.ToString()); + } + LogEvent("ExceptionThrown", msg.ToString()); } - LogEvent("ExceptionThrown", msg.ToString()); + LogEvent("Paused", CurrentStackFrame != null ? CurrentStackFrame.NextStatement.ToString() : string.Empty); }; - process.Exited += delegate(object sender, EventArgs e) { - LogEvent("ProcessExited", null); + process.Exited += delegate(object sender, DebuggerEventArgs e) { + LogEvent("Exited", null); }; - LogEvent("ProcessStarted", null); + LogEvent("Started", null); if (wait) { process.WaitForPause(); diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/AppDomain_Tests.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/AppDomain_Tests.cs index 99b3c792c1..9434bc8042 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/AppDomain_Tests.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/AppDomain_Tests.cs @@ -39,12 +39,12 @@ namespace Debugger.Tests { { StartTest(); - DebugType type1 = process.SelectedStackFrame.GetLocalVariableValue("one").Type; - DebugType type1b = process.SelectedStackFrame.GetLocalVariableValue("one").Type; + DebugType type1 = this.CurrentStackFrame.GetLocalVariableValue("one").Type; + DebugType type1b = this.CurrentStackFrame.GetLocalVariableValue("one").Type; ObjectDump("SameDomainEqual", type1 == type1b); process.Continue(); - ObjectDump("AppDomainName", process.SelectedStackFrame.GetLocalVariableValue("appDomainName").AsString()); - DebugType type2 = process.SelectedStackFrame.GetLocalVariableValue("two").Type; + ObjectDump("AppDomainName", this.CurrentStackFrame.GetLocalVariableValue("appDomainName").AsString()); + DebugType type2 = this.CurrentStackFrame.GetLocalVariableValue("two").Type; ObjectDump("OtherDomainEqual", type1 == type2); ObjectDump("AppDomainsEqual", type1.AppDomain == type2.AppDomain); ObjectDump("AppDomainIDsEqual", type1.AppDomain.ID == type2.AppDomain.ID); @@ -60,19 +60,19 @@ namespace Debugger.Tests { - + mscorlib.dll (No symbols) AppDomain_Tests.exe (Has symbols) - Break AppDomain_Tests.cs:13,4-13,40 + AppDomain_Tests.cs:13,4-13,40 True mscorlib.dll (No symbols) AppDomain_Tests.exe (Has symbols) - Break AppDomain_Tests.cs:26,4-26,40 + AppDomain_Tests.cs:26,4-26,40 myDomain Id=2 False False False - + #endif // EXPECTED_OUTPUT diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/Breakpoint_Tests.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/Breakpoint_Tests.cs index 0909840898..366f58621c 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/Breakpoint_Tests.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/Breakpoint_Tests.cs @@ -28,8 +28,8 @@ namespace Debugger.Tests { [NUnit.Framework.Test] public void Breakpoint_Tests() { - Breakpoint breakpoint1 = debugger.Breakpoints.Add(@"Breakpoint_Tests.cs", 14); - Breakpoint breakpoint2 = debugger.Breakpoints.Add(@"Breakpoint_Tests.cs", 15); + Breakpoint breakpoint1 = debugger.AddBreakpoint(@"Breakpoint_Tests.cs", 14); + Breakpoint breakpoint2 = debugger.AddBreakpoint(@"Breakpoint_Tests.cs", 15); StartTest(); @@ -57,23 +57,23 @@ namespace Debugger.Tests { - + mscorlib.dll (No symbols) Breakpoint_Tests.exe (Has symbols) System.dll (No symbols) - Break Breakpoint_Tests.cs:12,4-12,40 + Breakpoint_Tests.cs:12,4-12,40 @@ -81,23 +81,23 @@ namespace Debugger.Tests { System.Configuration.dll (No symbols) System.Xml.dll (No symbols) Main 1\r\n - Breakpoint Breakpoint_Tests.cs:14,4-14,49 + Breakpoint_Tests.cs:14,4-14,49 Main 2\r\n - Breakpoint Breakpoint_Tests.cs:16,4-16,49 + Breakpoint_Tests.cs:16,4-16,49 Main 3\r\n - Break Breakpoint_Tests.cs:17,4-17,40 - + Breakpoint_Tests.cs:17,4-17,40 + diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_DebuggeeKilled.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_DebuggeeKilled.cs index 74cf7f1c03..57d8a0df02 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_DebuggeeKilled.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_DebuggeeKilled.cs @@ -42,11 +42,11 @@ namespace Debugger.Tests { - + mscorlib.dll (No symbols) ControlFlow_DebuggeeKilled.exe (Has symbols) - Break ControlFlow_DebuggeeKilled.cs:12,4-12,40 - + ControlFlow_DebuggeeKilled.cs:12,4-12,40 + #endif // EXPECTED_OUTPUT diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_MainThreadExit.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_MainThreadExit.cs index 7b91fbf995..288d04de36 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_MainThreadExit.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_MainThreadExit.cs @@ -55,29 +55,26 @@ namespace Debugger.Tests { - + mscorlib.dll (No symbols) ControlFlow_MainThreadExit.exe (Has symbols) - Break ControlFlow_MainThreadExit.cs:20,4-20,40 + ControlFlow_MainThreadExit.cs:20,4-20,40 + Capacity="4" + Count="2"> + RuntimeValue="{System.Threading.Thread}" /> - ForcedBreak ControlFlow_MainThreadExit.cs:25,4-25,26 + + Capacity="4" + Count="2"> @@ -100,17 +96,15 @@ namespace Debugger.Tests { + RuntimeValue="{System.Threading.Thread}" /> - + #endif // EXPECTED_OUTPUT diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_NoBreak.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_NoBreak.cs index 04bda9d16c..b7c0b8de19 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_NoBreak.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_NoBreak.cs @@ -36,10 +36,10 @@ namespace Debugger.Tests { - + mscorlib.dll (No symbols) ControlFlow_NoBreak.exe (Has symbols) - + #endif // EXPECTED_OUTPUT diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_Stepping.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_Stepping.cs index d1b99fbe00..1e9c702976 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_Stepping.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_Stepping.cs @@ -119,69 +119,69 @@ namespace Debugger.Tests { { StartTest(); - SourcecodeSegment start = process.SelectedStackFrame.NextStatement; + SourcecodeSegment start = this.CurrentStackFrame.NextStatement; foreach (bool jmcEnabled in new bool[] {true, true, false}) { ObjectDump("Log", "Starting run with JMC=" + jmcEnabled.ToString()); - process.SelectedStackFrame.SetIP(start.Filename, start.StartLine + 1, start.StartColumn); + this.CurrentStackFrame.SetIP(start.Filename, start.StartLine + 1, start.StartColumn, false); process.Options.EnableJustMyCode = jmcEnabled; process.Options.StepOverSingleLineProperties = true; process.Options.StepOverFieldAccessProperties = true; - process.SelectedStackFrame.StepInto(); // 42.ToString() - Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name); + this.CurrentStackFrame.StepInto(); // 42.ToString() + Assert.AreEqual("Main", this.CurrentStackFrame.MethodInfo.Name); if (jmcEnabled) { - process.SelectedStackFrame.StepInto(); // StepRoot - Assert.AreEqual("StepRight", process.SelectedStackFrame.MethodInfo.Name); - process.SelectedStackFrame.StepOut(); - process.SelectedStackFrame.StepOver(); // Finish the step out - Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name); + this.CurrentStackFrame.StepInto(); // StepRoot + Assert.AreEqual("StepRight", this.CurrentStackFrame.MethodInfo.Name); + this.CurrentStackFrame.StepOut(); + this.CurrentStackFrame.StepOver(); // Finish the step out + Assert.AreEqual("Main", this.CurrentStackFrame.MethodInfo.Name); } else { - process.SelectedStackFrame.StepInto(); // StepRoot - Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name); + this.CurrentStackFrame.StepInto(); // StepRoot + Assert.AreEqual("Main", this.CurrentStackFrame.MethodInfo.Name); } - process.SelectedStackFrame.StepInto(); // Generated default constructor - Assert.AreEqual("Target", process.SelectedStackFrame.MethodInfo.Name); - process.SelectedStackFrame.StepOut(); - process.SelectedStackFrame.StepOver(); // Finish the step out - Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name); + this.CurrentStackFrame.StepInto(); // Generated default constructor + Assert.AreEqual("Target", this.CurrentStackFrame.MethodInfo.Name); + this.CurrentStackFrame.StepOut(); + this.CurrentStackFrame.StepOver(); // Finish the step out + Assert.AreEqual("Main", this.CurrentStackFrame.MethodInfo.Name); - process.SelectedStackFrame.StepInto(); // ShortProperty - Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name); + this.CurrentStackFrame.StepInto(); // ShortProperty + Assert.AreEqual("Main", this.CurrentStackFrame.MethodInfo.Name); - process.SelectedStackFrame.StepInto(); // FieldProperty - Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name); + this.CurrentStackFrame.StepInto(); // FieldProperty + Assert.AreEqual("Main", this.CurrentStackFrame.MethodInfo.Name); - process.SelectedStackFrame.StepInto(); // CatchExcpetion - Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name); + this.CurrentStackFrame.StepInto(); // CatchExcpetion + Assert.AreEqual("Main", this.CurrentStackFrame.MethodInfo.Name); if (jmcEnabled) { - process.SelectedStackFrame.StepInto(); // ZigZag1 - process.SelectedStackFrame.StepOver(); - process.SelectedStackFrame.StepOver(); - Assert.AreEqual("ZigZag2", process.SelectedStackFrame.MethodInfo.Name); - process.SelectedStackFrame.StepInto(); - Assert.AreEqual("ZigZag2", process.SelectedStackFrame.MethodInfo.Name); - Assert.AreEqual(3, process.SelectedStackFrame.NextStatement.StartColumn); - process.SelectedStackFrame.StepOut(); - process.SelectedStackFrame.StepOver(); // Finish the step out - Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name); + this.CurrentStackFrame.StepInto(); // ZigZag1 + this.CurrentStackFrame.StepOver(); + this.CurrentStackFrame.StepOver(); + Assert.AreEqual("ZigZag2", this.CurrentStackFrame.MethodInfo.Name); + this.CurrentStackFrame.StepInto(); + Assert.AreEqual("ZigZag2", this.CurrentStackFrame.MethodInfo.Name); + Assert.AreEqual(3, this.CurrentStackFrame.NextStatement.StartColumn); + this.CurrentStackFrame.StepOut(); + this.CurrentStackFrame.StepOver(); // Finish the step out + Assert.AreEqual("Main", this.CurrentStackFrame.MethodInfo.Name); } else { - process.SelectedStackFrame.StepInto(); // ZigZag1 - Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name); + this.CurrentStackFrame.StepInto(); // ZigZag1 + Assert.AreEqual("Main", this.CurrentStackFrame.MethodInfo.Name); } - process.SelectedStackFrame.StepInto(); // MyEvent - Assert.AreEqual("Event2", process.SelectedStackFrame.MethodInfo.Name); - process.SelectedStackFrame.StepOut(); - Assert.AreEqual("Event4", process.SelectedStackFrame.MethodInfo.Name); - process.SelectedStackFrame.StepOut(); - process.SelectedStackFrame.StepOver(); // Finish the step out - Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name); + this.CurrentStackFrame.StepInto(); // MyEvent + Assert.AreEqual("Event2", this.CurrentStackFrame.MethodInfo.Name); + this.CurrentStackFrame.StepOut(); + Assert.AreEqual("Event4", this.CurrentStackFrame.MethodInfo.Name); + this.CurrentStackFrame.StepOut(); + this.CurrentStackFrame.StepOver(); // Finish the step out + Assert.AreEqual("Main", this.CurrentStackFrame.MethodInfo.Name); } // Restore default state @@ -198,79 +198,76 @@ namespace Debugger.Tests { - + mscorlib.dll (No symbols) ControlFlow_Stepping.exe (Has symbols) - Break ControlFlow_Stepping.cs:98,4-98,40 + ControlFlow_Stepping.cs:98,4-98,40 Starting run with JMC=True - SetIP ControlFlow_Stepping.cs:99,4-99,37 - StepComplete ControlFlow_Stepping.cs:100,4-100,15 - StepComplete ControlFlow_Stepping.cs:23,27-23,28 - StepComplete ControlFlow_Stepping.cs:100,4-100,15 - StepComplete ControlFlow_Stepping.cs:101,4-101,36 - StepComplete ControlFlow_Stepping.cs:26,25-26,26 - StepComplete ControlFlow_Stepping.cs:101,4-101,36 - StepComplete ControlFlow_Stepping.cs:102,4-102,26 - StepComplete ControlFlow_Stepping.cs:103,4-103,26 - StepComplete ControlFlow_Stepping.cs:104,4-104,21 - StepComplete ControlFlow_Stepping.cs:105,4-105,14 + ControlFlow_Stepping.cs:100,4-100,15 + ControlFlow_Stepping.cs:23,27-23,28 + ControlFlow_Stepping.cs:100,4-100,15 + ControlFlow_Stepping.cs:101,4-101,36 + ControlFlow_Stepping.cs:26,25-26,26 + ControlFlow_Stepping.cs:101,4-101,36 + ControlFlow_Stepping.cs:102,4-102,26 + ControlFlow_Stepping.cs:103,4-103,26 + ControlFlow_Stepping.cs:104,4-104,21 + ControlFlow_Stepping.cs:105,4-105,14 System.dll (No symbols) - StepComplete ControlFlow_Stepping.cs:58,3-58,4 - StepComplete ControlFlow_Stepping.cs:59,4-59,46 + ControlFlow_Stepping.cs:58,3-58,4 + ControlFlow_Stepping.cs:59,4-59,46 System.Configuration.dll (No symbols) System.Xml.dll (No symbols) ZigZag2 - StepComplete ControlFlow_Stepping.cs:60,4-60,14 - StepComplete ControlFlow_Stepping.cs:58,3-58,4 + ControlFlow_Stepping.cs:60,4-60,14 + ControlFlow_Stepping.cs:58,3-58,4 ZigZag2 - StepComplete ControlFlow_Stepping.cs:105,4-105,14 - StepComplete ControlFlow_Stepping.cs:106,4-106,35 - StepComplete ControlFlow_Stepping.cs:87,50-87,51 - StepComplete ControlFlow_Stepping.cs:90,50-90,51 - StepComplete ControlFlow_Stepping.cs:106,4-106,35 - StepComplete ControlFlow_Stepping.cs:107,3-107,4 + ControlFlow_Stepping.cs:105,4-105,14 + ControlFlow_Stepping.cs:106,4-106,35 + ControlFlow_Stepping.cs:87,50-87,51 + ControlFlow_Stepping.cs:90,50-90,51 + ControlFlow_Stepping.cs:106,4-106,35 + ControlFlow_Stepping.cs:107,3-107,4 Starting run with JMC=True - SetIP ControlFlow_Stepping.cs:99,4-99,37 - StepComplete ControlFlow_Stepping.cs:100,4-100,15 - StepComplete ControlFlow_Stepping.cs:23,27-23,28 - StepComplete ControlFlow_Stepping.cs:100,4-100,15 - StepComplete ControlFlow_Stepping.cs:101,4-101,36 - StepComplete ControlFlow_Stepping.cs:26,25-26,26 - StepComplete ControlFlow_Stepping.cs:101,4-101,36 - StepComplete ControlFlow_Stepping.cs:102,4-102,26 - StepComplete ControlFlow_Stepping.cs:103,4-103,26 - StepComplete ControlFlow_Stepping.cs:104,4-104,21 - StepComplete ControlFlow_Stepping.cs:105,4-105,14 - StepComplete ControlFlow_Stepping.cs:58,3-58,4 - StepComplete ControlFlow_Stepping.cs:59,4-59,46 + ControlFlow_Stepping.cs:100,4-100,15 + ControlFlow_Stepping.cs:23,27-23,28 + ControlFlow_Stepping.cs:100,4-100,15 + ControlFlow_Stepping.cs:101,4-101,36 + ControlFlow_Stepping.cs:26,25-26,26 + ControlFlow_Stepping.cs:101,4-101,36 + ControlFlow_Stepping.cs:102,4-102,26 + ControlFlow_Stepping.cs:103,4-103,26 + ControlFlow_Stepping.cs:104,4-104,21 + ControlFlow_Stepping.cs:105,4-105,14 + ControlFlow_Stepping.cs:58,3-58,4 + ControlFlow_Stepping.cs:59,4-59,46 ZigZag2 - StepComplete ControlFlow_Stepping.cs:60,4-60,14 - StepComplete ControlFlow_Stepping.cs:58,3-58,4 + ControlFlow_Stepping.cs:60,4-60,14 + ControlFlow_Stepping.cs:58,3-58,4 ZigZag2 - StepComplete ControlFlow_Stepping.cs:105,4-105,14 - StepComplete ControlFlow_Stepping.cs:106,4-106,35 - StepComplete ControlFlow_Stepping.cs:87,50-87,51 - StepComplete ControlFlow_Stepping.cs:90,50-90,51 - StepComplete ControlFlow_Stepping.cs:106,4-106,35 - StepComplete ControlFlow_Stepping.cs:107,3-107,4 + ControlFlow_Stepping.cs:105,4-105,14 + ControlFlow_Stepping.cs:106,4-106,35 + ControlFlow_Stepping.cs:87,50-87,51 + ControlFlow_Stepping.cs:90,50-90,51 + ControlFlow_Stepping.cs:106,4-106,35 + ControlFlow_Stepping.cs:107,3-107,4 Starting run with JMC=False - SetIP ControlFlow_Stepping.cs:99,4-99,37 - StepComplete ControlFlow_Stepping.cs:100,4-100,15 - StepComplete ControlFlow_Stepping.cs:101,4-101,36 - StepComplete ControlFlow_Stepping.cs:26,25-26,26 - StepComplete ControlFlow_Stepping.cs:101,4-101,36 - StepComplete ControlFlow_Stepping.cs:102,4-102,26 - StepComplete ControlFlow_Stepping.cs:103,4-103,26 - StepComplete ControlFlow_Stepping.cs:104,4-104,21 - StepComplete ControlFlow_Stepping.cs:105,4-105,14 + ControlFlow_Stepping.cs:100,4-100,15 + ControlFlow_Stepping.cs:101,4-101,36 + ControlFlow_Stepping.cs:26,25-26,26 + ControlFlow_Stepping.cs:101,4-101,36 + ControlFlow_Stepping.cs:102,4-102,26 + ControlFlow_Stepping.cs:103,4-103,26 + ControlFlow_Stepping.cs:104,4-104,21 + ControlFlow_Stepping.cs:105,4-105,14 ZigZag2 ZigZag2 - StepComplete ControlFlow_Stepping.cs:106,4-106,35 - StepComplete ControlFlow_Stepping.cs:87,50-87,51 - StepComplete ControlFlow_Stepping.cs:90,50-90,51 - StepComplete ControlFlow_Stepping.cs:106,4-106,35 - StepComplete ControlFlow_Stepping.cs:107,3-107,4 - + ControlFlow_Stepping.cs:106,4-106,35 + ControlFlow_Stepping.cs:87,50-87,51 + ControlFlow_Stepping.cs:90,50-90,51 + ControlFlow_Stepping.cs:106,4-106,35 + ControlFlow_Stepping.cs:107,3-107,4 + #endif // EXPECTED_OUTPUT diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_TerminatePausedProcess.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_TerminatePausedProcess.cs index ddf35a769f..cd566ee64c 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_TerminatePausedProcess.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_TerminatePausedProcess.cs @@ -38,16 +38,16 @@ namespace Debugger.Tests { - + mscorlib.dll (No symbols) ControlFlow_TerminatePausedProcess.exe (Has symbols) - Break ControlFlow_TerminatePausedProcess.cs:12,4-12,40 - - + ControlFlow_TerminatePausedProcess.cs:12,4-12,40 + + mscorlib.dll (No symbols) ControlFlow_TerminatePausedProcess.exe (Has symbols) - Break ControlFlow_TerminatePausedProcess.cs:12,4-12,40 - + ControlFlow_TerminatePausedProcess.cs:12,4-12,40 + #endif // EXPECTED_OUTPUT diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_TerminateRunningProcess.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_TerminateRunningProcess.cs index 9feda4d2e1..0707949069 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_TerminateRunningProcess.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_TerminateRunningProcess.cs @@ -30,11 +30,11 @@ namespace Debugger.Tests { { for(int i = 0; i < 2; i++) { StartTest(); - process.SelectedStackFrame.StepOver(); + this.CurrentStackFrame.StepOver(); process.Paused += delegate { Assert.Fail("Should not have received any callbacks after Terminate"); }; - process.SelectedStackFrame.AsyncStepOver(); + this.CurrentStackFrame.AsyncStepOver(); ObjectDump("Log", "Calling terminate"); process.Terminate(); } @@ -50,20 +50,20 @@ namespace Debugger.Tests { - + mscorlib.dll (No symbols) ControlFlow_TerminateRunningProcess.exe (Has symbols) - Break ControlFlow_TerminateRunningProcess.cs:16,4-16,40 - StepComplete ControlFlow_TerminateRunningProcess.cs:17,4-17,26 + ControlFlow_TerminateRunningProcess.cs:16,4-16,40 + ControlFlow_TerminateRunningProcess.cs:17,4-17,26 Calling terminate - - + + mscorlib.dll (No symbols) ControlFlow_TerminateRunningProcess.exe (Has symbols) - Break ControlFlow_TerminateRunningProcess.cs:16,4-16,40 - StepComplete ControlFlow_TerminateRunningProcess.cs:17,4-17,26 + ControlFlow_TerminateRunningProcess.cs:16,4-16,40 + ControlFlow_TerminateRunningProcess.cs:17,4-17,26 Calling terminate - + #endif // EXPECTED_OUTPUT diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/DebugType_CompilerGeneratedClasses.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/DebugType_CompilerGeneratedClasses.cs index c958cb2df9..ef103f4b71 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/DebugType_CompilerGeneratedClasses.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/DebugType_CompilerGeneratedClasses.cs @@ -88,10 +88,10 @@ namespace Debugger.Tests { - + mscorlib.dll (No symbols) DebugType_CompilerGeneratedClasses.exe (Has symbols) - Break DebugType_CompilerGeneratedClasses.cs:34,5-34,41 + DebugType_CompilerGeneratedClasses.cs:34,5-34,41 - Break DebugType_CompilerGeneratedClasses.cs:53,6-53,42 + DebugType_CompilerGeneratedClasses.cs:53,6-53,42 - Break DebugType_CompilerGeneratedClasses.cs:50,7-50,43 + DebugType_CompilerGeneratedClasses.cs:50,7-50,43 nestedDelegArg = 402 instanceField = "instance field value" staticField = "static field value" - + #endif // EXPECTED_OUTPUT diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/DebugType_Tests.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/DebugType_Tests.cs index 409265caeb..f96761b388 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/DebugType_Tests.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/DebugType_Tests.cs @@ -213,12 +213,11 @@ namespace Debugger.Tests { { ObjectDump( msg, - SelectedStackFrame.MethodInfo.GetLocalVariables(SelectedStackFrame.IP).Select(v => new LocalVariable() { Name = v.Name, Type = v.LocalType, Value = v.GetValue(process.SelectedStackFrame)}) + this.CurrentStackFrame.MethodInfo.GetLocalVariables(this.CurrentStackFrame.IP).Select(v => new LocalVariable() { Name = v.Name, Type = v.LocalType, Value = v.GetValue(this.CurrentStackFrame)}) ); } [NUnit.Framework.Test] - [NUnit.Framework.Ignore("Broken after Siegfried added the IsGeneric implementation; can't adjust test easily as I'm on .NET 4.5")] public void DebugType_Tests() { if (IsDotnet45Installed()) @@ -232,12 +231,12 @@ namespace Debugger.Tests { process.Options.StepOverSingleLineProperties = false; process.Options.StepOverFieldAccessProperties = true; - ObjectDump("DefinedTypes", process.Modules["DebugType_Tests.exe"].GetNamesOfDefinedTypes()); - ObjectDump("DefinedTypes", process.Modules["DebugType_Tests.exe"].GetDefinedTypes()); + ObjectDump("DefinedTypes", process.GetModule("DebugType_Tests.exe").GetNamesOfDefinedTypes()); + ObjectDump("DefinedTypes", process.GetModule("DebugType_Tests.exe").GetDefinedTypes()); - ObjectDump("Members", process.SelectedStackFrame.GetLocalVariableValue("members").Type.GetMembers(DebugType.BindingFlagsAllDeclared)); - ObjectDump("Access-Members", process.SelectedStackFrame.GetLocalVariableValue("access").Type.GetMembers()); - ObjectDump("MyInterfaceImpl-Members", process.SelectedStackFrame.GetLocalVariableValue("myInterfaceImpl").Type.GetMembers()); + ObjectDump("Members", this.CurrentStackFrame.GetLocalVariableValue("members").Type.GetMembers(DebugType.BindingFlagsAllDeclared)); + ObjectDump("Access-Members", this.CurrentStackFrame.GetLocalVariableValue("access").Type.GetMembers()); + ObjectDump("MyInterfaceImpl-Members", this.CurrentStackFrame.GetLocalVariableValue("myInterfaceImpl").Type.GetMembers()); DumpLocalVariables(); EndTest(); @@ -251,10 +250,10 @@ namespace Debugger.Tests { - + mscorlib.dll (No symbols) DebugType_Tests.exe (Has symbols) - Break DebugType_Tests.cs:167,4-167,40 + DebugType_Tests.cs:167,4-167,40 @@ -688,6 +687,8 @@ namespace Debugger.Tests { FullName="Int32 Debugger.Tests.DebugType_Tests+MyInterfaceImpl`1[System.Int32].Fun(Debugger.Tests.DebugType_Tests+MyClass a, Debugger.Tests.DebugType_Tests+MyStruct b, System.Object m)" FullNameWithoutParameterNames="Int32 Debugger.Tests.DebugType_Tests+MyInterfaceImpl`1[System.Int32].Fun(Debugger.Tests.DebugType_Tests+MyClass, Debugger.Tests.DebugType_Tests+MyStruct, System.Object)" GetLocalVariables="{Debugger.Tests.DebugType_Tests+MyInterfaceImpl`1[System.Int32] this}" + IsGenericMethod="True" + IsGenericMethodDefinition="True" Name="Fun" ReturnType="System.Int32" /> @@ -698,6 +699,8 @@ namespace Debugger.Tests { FullName="Object[] Debugger.Tests.DebugType_Tests+MyInterfaceImpl`1[System.Int32].Fun2(System.Int32** iPtrPtr, System.Object[,] mdArray, System.Collections.Generic.List`1+Enumerator[System.Object] listEnum)" FullNameWithoutParameterNames="Object[] Debugger.Tests.DebugType_Tests+MyInterfaceImpl`1[System.Int32].Fun2(System.Int32**, System.Object[,], System.Collections.Generic.List`1+Enumerator[System.Object])" GetLocalVariables="{Debugger.Tests.DebugType_Tests+MyInterfaceImpl`1[System.Int32] this}" + IsGenericMethod="True" + IsGenericMethodDefinition="True" Name="Fun2" ReturnType="System.Object[]" /> @@ -1679,7 +1682,7 @@ namespace Debugger.Tests { - + #endif // EXPECTED_OUTPUT diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/DynamicCode.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/DynamicCode.cs index 311ce0f98b..68d88ab56f 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/DynamicCode.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/DynamicCode.cs @@ -56,9 +56,9 @@ namespace Debugger.Tests { { StartTest(); - process.SelectedStackFrame.StepOver(); - process.SelectedStackFrame.StepInto(); - Assert.AreEqual("Source.txt", process.SelectedStackFrame.NextStatement.Filename); + this.CurrentStackFrame.StepOver(); + this.CurrentStackFrame.StepInto(); + Assert.AreEqual("Source.txt", this.CurrentStackFrame.NextStatement.Filename); EndTest(); } @@ -71,16 +71,16 @@ namespace Debugger.Tests { - + mscorlib.dll (No symbols) DynamicCode.exe (Has symbols) DynamicllyGeneratedAssembly (No symbols) ISymWrapper.dll (No symbols) System.dll (No symbols) - Break DynamicCode.cs:42,4-42,40 - StepComplete DynamicCode.cs:43,4-43,73 - StepComplete Source.txt:1,1-1,100 - + DynamicCode.cs:42,4-42,40 + DynamicCode.cs:43,4-43,73 + Source.txt:1,1-1,100 + #endif // EXPECTED_OUTPUT diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/Exception_Custom.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/Exception_Custom.cs index afbe5d7973..43fa4167b2 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/Exception_Custom.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/Exception_Custom.cs @@ -46,12 +46,12 @@ namespace Debugger.Tests { - + mscorlib.dll (No symbols) Exception_Custom.exe (Has symbols) Debugger.Tests.MyException: test2 ---> Debugger.Tests.MyException: test1 - ExceptionIntercepted Exception_Custom.cs:23,5-23,39 - + Exception_Custom.cs:23,5-23,39 + #endif // EXPECTED_OUTPUT diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/ExpressionEvaluator_Tests.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/ExpressionEvaluator_Tests.cs index 2aa62276b7..876fed301f 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/ExpressionEvaluator_Tests.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/ExpressionEvaluator_Tests.cs @@ -205,15 +205,15 @@ namespace Debugger.Tests { public void ExpressionEvaluator_Tests() { StartTest(); - process.SelectedStackFrame.StepOver(); - process.SelectedStackFrame.StepOver(); // Start worker thread + this.CurrentStackFrame.StepOver(); + this.CurrentStackFrame.StepOver(); // Start worker thread EvalAll(expressionsInput); // Test member hiding / overloading - Value myClass = SelectedStackFrame.GetLocalVariableValue("myClass").GetPermanentReference(); - Expression myClassExpr = SelectedStackFrame.MethodInfo.GetLocalVariable(SelectedStackFrame.IP, "myClass").GetExpression(); + Value myClass = this.CurrentStackFrame.GetLocalVariableValue("myClass").GetPermanentReference(this.EvalThread); + Expression myClassExpr = this.CurrentStackFrame.MethodInfo.GetLocalVariable(this.CurrentStackFrame.IP, "myClass").GetExpression(); List expressions = new List(); foreach(MemberInfo memberInfo in myClass.Type.GetFieldsAndNonIndexedProperties(DebugType.BindingFlagsAll)) { @@ -245,12 +245,12 @@ namespace Debugger.Tests { // Test type round tripping - foreach(DebugLocalVariableInfo locVar in process.SelectedStackFrame.MethodInfo.GetLocalVariables()) { + foreach(DebugLocalVariableInfo locVar in this.CurrentStackFrame.MethodInfo.GetLocalVariables()) { if (locVar.Name.StartsWith("complexType")) { TypeReference complexTypeRef = locVar.LocalType.GetTypeReference(); string code = "typeof(" + complexTypeRef.PrettyPrint() + ")"; TypeOfExpression complexTypeRefRT = (TypeOfExpression)ExpressionEvaluator.Parse(code, SupportedLanguage.CSharp); - DebugType type = complexTypeRefRT.TypeReference.ResolveType(process.SelectedStackFrame.AppDomain); + DebugType type = complexTypeRefRT.TypeReference.ResolveType(this.CurrentStackFrame.AppDomain); string status = locVar.LocalType.FullName == type.FullName ? "ok" : "fail"; ObjectDumpToString("TypeResulution", string.Format(" {0} = {1} ({2})", code, type.FullName, status)); } @@ -258,15 +258,15 @@ namespace Debugger.Tests { // Type equality - DebugLocalVariableInfo loc = SelectedStackFrame.MethodInfo.GetLocalVariable(SelectedStackFrame.IP, "list"); + DebugLocalVariableInfo loc = this.CurrentStackFrame.MethodInfo.GetLocalVariable(this.CurrentStackFrame.IP, "list"); Type locType = loc.LocalType; - Type valType = loc.GetValue(SelectedStackFrame).Type; + Type valType = loc.GetValue(this.CurrentStackFrame).Type; ObjectDump("TypesIdentitcal", object.ReferenceEquals(locType, valType)); ObjectDump("TypesEqual", locType == valType); - ObjectDump("WorkerThreadMoved", process.SelectedStackFrame.GetThisValue().GetMemberValue("WorkerThreadMoved").AsString()); + ObjectDump("WorkerThreadMoved", this.CurrentStackFrame.GetThisValue().GetMemberValue(this.EvalThread, "WorkerThreadMoved").AsString()); process.Continue(); - ObjectDump("WorkerThreadMoved", process.SelectedStackFrame.GetThisValue().GetMemberValue("WorkerThreadMoved").AsString()); + ObjectDump("WorkerThreadMoved", this.CurrentStackFrame.GetThisValue().GetMemberValue(this.EvalThread, "WorkerThreadMoved").AsString()); EndTest(); } @@ -286,8 +286,8 @@ namespace Debugger.Tests { restultFmted = null; } else { try { - Value result = ICSharpCode.NRefactory.Visitors.ExpressionEvaluator.Evaluate(expr, SupportedLanguage.CSharp, process.SelectedStackFrame); - restultFmted = ICSharpCode.NRefactory.Visitors.ExpressionEvaluator.FormatValue(result); + Value result = ICSharpCode.NRefactory.Visitors.ExpressionEvaluator.Evaluate(expr, SupportedLanguage.CSharp, this.CurrentStackFrame); + restultFmted = ICSharpCode.NRefactory.Visitors.ExpressionEvaluator.FormatValue(this.EvalThread, result); } catch (GetValueException e) { restultFmted = e.Message; } diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/Process_MemoryReadWrite.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/Process_MemoryReadWrite.cs index e09fa7c808..f7ef425378 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/Process_MemoryReadWrite.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/Process_MemoryReadWrite.cs @@ -26,8 +26,8 @@ namespace Debugger.Tests { { StartTest(); - ulong addrHello = process.SelectedStackFrame.GetLocalVariableValue("hello").Address; - ulong addrWorld = process.SelectedStackFrame.GetLocalVariableValue("world").Address; + ulong addrHello = this.CurrentStackFrame.GetLocalVariableValue("hello").Address; + ulong addrWorld = this.CurrentStackFrame.GetLocalVariableValue("world").Address; addrHello = DeRef(process.ReadMemory(addrHello, 4)); addrWorld = DeRef(process.ReadMemory(addrWorld, 4)); @@ -65,17 +65,17 @@ namespace Debugger.Tests { - + mscorlib.dll (No symbols) Process_MemoryReadWrite.exe (Has symbols) System.dll (No symbols) - Break Process_MemoryReadWrite.cs:14,4-14,40 + Process_MemoryReadWrite.cs:14,4-14,40 5 0 0 0 48 0 65 0 6C 0 6C 0 6F 0 6 0 0 0 20 0 20 0 20 0 20 0 20 0 21 0 System.Configuration.dll (No symbols) System.Xml.dll (No symbols) Hello world!\r\n - + #endif // EXPECTED_OUTPUT diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Callstack.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Callstack.cs index de081d4cb2..7a08d6acac 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Callstack.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Callstack.cs @@ -33,11 +33,11 @@ namespace Debugger.Tests { { StartTest(); - ObjectDump("Callstack", process.SelectedThread.GetCallstack()); - process.SelectedStackFrame.StepOut(); - ObjectDump("Callstack", process.SelectedThread.GetCallstack()); - process.SelectedStackFrame.StepOut(); - ObjectDump("Callstack", process.SelectedThread.GetCallstack()); + ObjectDump("Callstack", this.CurrentThread.GetCallstack()); + this.CurrentStackFrame.StepOut(); + ObjectDump("Callstack", this.CurrentThread.GetCallstack()); + this.CurrentStackFrame.StepOut(); + ObjectDump("Callstack", this.CurrentThread.GetCallstack()); EndTest(); } @@ -50,10 +50,10 @@ namespace Debugger.Tests { - + mscorlib.dll (No symbols) StackFrame_Callstack.exe (Has symbols) - Break StackFrame_Callstack.cs:22,4-22,40 + StackFrame_Callstack.cs:22,4-22,40 - StepComplete StackFrame_Callstack.cs:17,4-17,11 + StackFrame_Callstack.cs:17,4-17,11 - StepComplete StackFrame_Callstack.cs:12,4-12,11 + StackFrame_Callstack.cs:12,4-12,11 - + #endif // EXPECTED_OUTPUT diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Lifetime.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Lifetime.cs index bc5636dc40..b6b85829f9 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Lifetime.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Lifetime.cs @@ -36,21 +36,21 @@ namespace Debugger.Tests { { StartTest(); - StackFrame stackFrame = process.SelectedStackFrame; - ObjectDump("SelectedStackFrame", process.SelectedStackFrame); + StackFrame stackFrame = this.CurrentStackFrame; + ObjectDump("SelectedStackFrame", this.CurrentStackFrame); process.Continue(); // Go to the SubFunction ObjectDump("Old StackFrame", stackFrame); - ObjectDump("SelectedStackFrame", process.SelectedStackFrame); + ObjectDump("SelectedStackFrame", this.CurrentStackFrame); process.Continue(); // Go back to Function ObjectDump("Old StackFrame", stackFrame); - ObjectDump("SelectedStackFrame", process.SelectedStackFrame); + ObjectDump("SelectedStackFrame", this.CurrentStackFrame); process.Continue(); // Setp out of function - ObjectDump("Main", process.SelectedStackFrame); + ObjectDump("Main", this.CurrentStackFrame); ObjectDump("Old StackFrame", stackFrame); - ObjectDump("SelectedStackFrame", process.SelectedStackFrame); + ObjectDump("SelectedStackFrame", this.CurrentStackFrame); EndTest(); } @@ -63,10 +63,10 @@ namespace Debugger.Tests { - + mscorlib.dll (No symbols) StackFrame_Lifetime.exe (Has symbols) - Break StackFrame_Lifetime.cs:18,4-18,40 + StackFrame_Lifetime.cs:18,4-18,40 - Break StackFrame_Lifetime.cs:25,4-25,40 + StackFrame_Lifetime.cs:25,4-25,40 - Break StackFrame_Lifetime.cs:20,4-20,40 + StackFrame_Lifetime.cs:20,4-20,40 - Break StackFrame_Lifetime.cs:13,4-13,40 + StackFrame_Lifetime.cs:13,4-13,40
- + #endif // EXPECTED_OUTPUT diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_SetIP.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_SetIP.cs index 1edc275a26..23f9a15278 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_SetIP.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_SetIP.cs @@ -26,9 +26,9 @@ namespace Debugger.Tests { { StartTest(); - Assert.IsNotNull(process.SelectedStackFrame.CanSetIP("StackFrame_SetIP.cs", 12, 0)); - Assert.IsNull(process.SelectedStackFrame.CanSetIP("StackFrame_SetIP.cs", 100, 0)); - process.SelectedStackFrame.SetIP("StackFrame_SetIP.cs", 12, 0); + Assert.IsNotNull(this.CurrentStackFrame.SetIP("StackFrame_SetIP.cs", 12, 0, true)); + Assert.IsNull(this.CurrentStackFrame.SetIP("StackFrame_SetIP.cs", 100, 0, true)); + this.CurrentStackFrame.SetIP("StackFrame_SetIP.cs", 12, 0, false); process.Continue(); Assert.AreEqual("1\r\n1\r\n", log); @@ -43,18 +43,17 @@ namespace Debugger.Tests { - + mscorlib.dll (No symbols) StackFrame_SetIP.exe (Has symbols) System.dll (No symbols) System.Configuration.dll (No symbols) System.Xml.dll (No symbols) 1\r\n - Break StackFrame_SetIP.cs:13,4-13,40 - SetIP StackFrame_SetIP.cs:12,4-12,44 + StackFrame_SetIP.cs:13,4-13,40 1\r\n - Break StackFrame_SetIP.cs:13,4-13,40 - + StackFrame_SetIP.cs:13,4-13,40 + #endif // EXPECTED_OUTPUT diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Tests.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Tests.cs index bbd7013d2a..f2f3d84764 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Tests.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Tests.cs @@ -54,10 +54,10 @@ namespace Debugger.Tests { - + mscorlib.dll (No symbols) StackFrame_Tests.exe (Has symbols) - Break StackFrame_Tests.cs:13,5-13,41 + StackFrame_Tests.cs:13,5-13,41 - Break StackFrame_Tests.cs:16,5-16,41 + StackFrame_Tests.cs:16,5-16,41 - Break StackFrame_Tests.cs:19,4-19,40 + StackFrame_Tests.cs:19,4-19,40 - Break StackFrame_Tests.cs:23,4-23,40 + StackFrame_Tests.cs:23,4-23,40 - + #endif // EXPECTED_OUTPUT diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_VariablesLifetime.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_VariablesLifetime.cs index 720052911f..5041ce0a07 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_VariablesLifetime.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_VariablesLifetime.cs @@ -46,15 +46,15 @@ namespace Debugger.Tests { StartTest(); // 1 - Enter program - argument = process.SelectedStackFrame.GetArgumentValue(0); - local = process.SelectedStackFrame.GetLocalVariableValue("local"); - @class = process.SelectedStackFrame.GetThisValue().GetMemberValue("class"); + argument = this.CurrentStackFrame.GetArgumentValue(0); + local = this.CurrentStackFrame.GetLocalVariableValue("local"); + @class = this.CurrentStackFrame.GetThisValue().GetMemberValue(this.EvalThread, "class"); ObjectDump("argument", argument); ObjectDump("local", local); ObjectDump("@class", @class); process.Continue(); // 2 - Go to the SubFunction - localInSubFunction = process.SelectedStackFrame.GetLocalVariableValue("localInSubFunction"); + localInSubFunction = this.CurrentStackFrame.GetLocalVariableValue("localInSubFunction"); ObjectDump("argument", argument); ObjectDump("local", local); ObjectDump("@class", @class); @@ -71,7 +71,7 @@ namespace Debugger.Tests { ObjectDump("local", local); ObjectDump("@class", @class); ObjectDump("localInSubFunction", @localInSubFunction); - localInSubFunction = process.SelectedStackFrame.GetLocalVariableValue("localInSubFunction"); + localInSubFunction = this.CurrentStackFrame.GetLocalVariableValue("localInSubFunction"); ObjectDump("localInSubFunction(new)", @localInSubFunction); process.Continue(); // 5 - Setp out of both functions @@ -91,10 +91,10 @@ namespace Debugger.Tests { - + mscorlib.dll (No symbols) StackFrame_VariablesLifetime.exe (Has symbols) - Break StackFrame_VariablesLifetime.cs:21,4-21,40 + StackFrame_VariablesLifetime.cs:21,4-21,40 - Break StackFrame_VariablesLifetime.cs:30,4-30,40 + StackFrame_VariablesLifetime.cs:30,4-30,40 - Break StackFrame_VariablesLifetime.cs:23,4-23,40 + StackFrame_VariablesLifetime.cs:23,4-23,40 - Break StackFrame_VariablesLifetime.cs:30,4-30,40 + StackFrame_VariablesLifetime.cs:30,4-30,40 - Break StackFrame_VariablesLifetime.cs:15,4-15,40 + StackFrame_VariablesLifetime.cs:15,4-15,40 - + #endif // EXPECTED_OUTPUT diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/Thread_Tests.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/Thread_Tests.cs index 09b28a4390..c8af696246 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/Thread_Tests.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/Thread_Tests.cs @@ -9,6 +9,7 @@ namespace Debugger.Tests { public static void Main() { + System.Diagnostics.Debugger.Break(); System.Threading.Thread.CurrentThread.Priority = System.Threading.ThreadPriority.AboveNormal; System.Diagnostics.Debugger.Break(); System.Threading.Thread.CurrentThread.Name = "ThreadName"; @@ -24,21 +25,14 @@ namespace Debugger.Tests { [NUnit.Framework.Test] public void Thread_Tests() { - debugger.Processes.Added += debugger_ProcessStarted; StartTest(); - debugger.Processes.Added -= debugger_ProcessStarted; - ObjectDump("Thread", process.SelectedThread); + ObjectDump("Thread", this.CurrentThread); + process.Continue(); + ObjectDump("Thread", this.CurrentThread); process.Continue(); - ObjectDump("Thread", process.SelectedThread); + ObjectDump("Thread", this.CurrentThread); EndTest(); } - - void debugger_ProcessStarted(object sender, CollectionItemEventArgs e) - { - e.Item.Threads.Added += delegate(object sender2, CollectionItemEventArgs f) { - ObjectDump("ThreadStartedEvent", f.Item); - }; - } } } #endif @@ -48,58 +42,43 @@ namespace Debugger.Tests { - + mscorlib.dll (No symbols) - + Thread_Tests.exe (Has symbols) + Thread_Tests.cs:12,4-12,40 + - - Thread_Tests.exe (Has symbols) - Break Thread_Tests.cs:13,4-13,40 + RuntimeValue="{System.Threading.Thread}" /> + + Thread_Tests.cs:14,4-14,40 + RuntimeValue="{System.Threading.Thread}" /> - Break Thread_Tests.cs:15,4-15,40 + Thread_Tests.cs:16,4-16,40 + RuntimeValue="{System.Threading.Thread}" /> - - - - + #endif // EXPECTED_OUTPUT diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/Value_Tests.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/Value_Tests.cs index 6eebf3999c..2021910972 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/Value_Tests.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/Value_Tests.cs @@ -40,11 +40,11 @@ namespace Debugger.Tests { DumpLocalVariables(); - Value array = process.SelectedStackFrame.GetLocalVariableValue("array").GetPermanentReference(); - ObjectDump("array.Length", array.GetMemberValue("Length")); + Value array = this.CurrentStackFrame.GetLocalVariableValue("array").GetPermanentReference(this.EvalThread); + ObjectDump("array.Length", array.GetMemberValue(this.EvalThread, "Length")); ObjectDump("array", array); - Value lbArray = process.SelectedStackFrame.GetLocalVariableValue("lbArray").GetPermanentReference(); + Value lbArray = this.CurrentStackFrame.GetLocalVariableValue("lbArray").GetPermanentReference(this.EvalThread); ObjectDump("lbArray", lbArray); ObjectDump("lbArray-10-20", lbArray.GetArrayElement(new int[] {10, 20})); @@ -59,10 +59,10 @@ namespace Debugger.Tests { - + mscorlib.dll (No symbols) Value_Tests.exe (Has symbols) - Break Value_Tests.cs:27,4-27,40 + Value_Tests.cs:27,4-27,40 - + #endif // EXPECTED_OUTPUT diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/_HelloWorldTest.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/_HelloWorldTest.cs index d32fa7f838..f667725372 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/_HelloWorldTest.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/_HelloWorldTest.cs @@ -36,15 +36,15 @@ namespace Debugger.Tests { - + mscorlib.dll (No symbols) _HelloWorldTest.exe (Has symbols) System.dll (No symbols) System.Configuration.dll (No symbols) System.Xml.dll (No symbols) Hello world!\r\n - Break _HelloWorldTest.cs:14,4-14,40 - + _HelloWorldTest.cs:14,4-14,40 + #endif // EXPECTED_OUTPUT diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs index f3cad8d692..8a95352026 100755 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CodeEditorView.cs @@ -246,7 +246,7 @@ namespace ICSharpCode.AvalonEdit.AddIn #region Tooltip ToolTip toolTip; - Popup popup; + Popup popupToolTip; void TextEditorMouseHover(object sender, MouseEventArgs e) { @@ -287,26 +287,19 @@ namespace ICSharpCode.AvalonEdit.AddIn ToolTipRequestService.RequestToolTip(args); } + if (!TryCloseExistingPopup(false)) { + return; + } + if (args.ContentToShow != null) { - var contentToShowITooltip = args.ContentToShow as ITooltip; + popupToolTip = args.ContentToShow as Popup; - if (contentToShowITooltip != null && contentToShowITooltip.ShowAsPopup) { - if (!(args.ContentToShow is UIElement)) { - throw new NotSupportedException("Content to show in Popup must be UIElement: " + args.ContentToShow); - } - if (popup == null) { - popup = CreatePopup(); - } - // if popup was only first level, hovering somewhere else closes it - if (TryCloseExistingPopup(false)) { - - // when popup content decides to close, close the popup - contentToShowITooltip.Closed += (closedSender, closedArgs) => { popup.IsOpen = false; }; - popup.Child = (UIElement)args.ContentToShow; - //ICSharpCode.SharpDevelop.Debugging.DebuggerService.CurrentDebugger.IsProcessRunningChanged - SetPopupPosition(popup, e); - popup.IsOpen = true; - } + if (popupToolTip != null) { + var popupPosition = GetPopupPosition(e); + popupToolTip.HorizontalOffset = popupPosition.X; + popupToolTip.VerticalOffset = popupPosition.Y; + popupToolTip.IsOpen = true; + popupToolTip.StaysOpen = true; // We will close it ourselves e.Handled = true; } else { if (toolTip == null) { @@ -328,35 +321,19 @@ namespace ICSharpCode.AvalonEdit.AddIn toolTip.IsOpen = true; e.Handled = true; } - } else { - // close popup if mouse hovered over empty area - if (popup != null) { - e.Handled = true; - } - TryCloseExistingPopup(false); } } - bool TryCloseExistingPopup(bool hard) + bool TryCloseExistingPopup(bool mouseClick) { - bool canClose = true; - if (popup != null) { - var popupContentITooltip = popup.Child as ITooltip; - if (popupContentITooltip != null) { - canClose = popupContentITooltip.Close(hard); - } - if (canClose) { - popup.IsOpen = false; + if (popupToolTip != null) { + if (popupToolTip.IsOpen && !mouseClick && popupToolTip is ITooltip && !((ITooltip)popupToolTip).CloseOnHoverEnd) { + return false; // Popup does not want to be closed yet } + popupToolTip.IsOpen = false; + popupToolTip = null; } - return canClose; - } - - void SetPopupPosition(Popup popup, MouseEventArgs mouseArgs) - { - var popupPosition = GetPopupPosition(mouseArgs); - popup.HorizontalOffset = popupPosition.X; - popup.VerticalOffset = popupPosition.Y; + return true; } /// Returns Popup position based on mouse position, in device independent units @@ -379,17 +356,6 @@ namespace ICSharpCode.AvalonEdit.AddIn return positionInPixels.TransformFromDevice(this); } - Popup CreatePopup() - { - popup = new Popup(); - popup.Closed += PopupClosed; - popup.AllowsTransparency = true; - popup.PlacementTarget = this; // required for property inheritance - popup.Placement = PlacementMode.Absolute; - popup.StaysOpen = true; - return popup; - } - void TextEditorMouseHoverStopped(object sender, MouseEventArgs e) { if (toolTip != null) { @@ -400,7 +366,7 @@ namespace ICSharpCode.AvalonEdit.AddIn void TextEditorMouseLeave(object sender, MouseEventArgs e) { - if (popup != null && !popup.IsMouseOver) { + if (popupToolTip != null && !popupToolTip.IsMouseOver) { // do not close popup if mouse moved from editor to popup TryCloseExistingPopup(false); } @@ -411,11 +377,6 @@ namespace ICSharpCode.AvalonEdit.AddIn toolTip = null; } - void PopupClosed(object sender, EventArgs e) - { - popup = null; - } - #region GetTooltipTextForCollapsedSection string GetTooltipTextForCollapsedSection(FoldingSection foldingSection) { diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CustomizableHighlightingColorizer.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CustomizableHighlightingColorizer.cs index 97ecfdeaef..47268c4c23 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CustomizableHighlightingColorizer.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CustomizableHighlightingColorizer.cs @@ -31,6 +31,7 @@ namespace ICSharpCode.AvalonEdit.AddIn public const string LinkText = "Link text"; public const string BreakpointMarker = "Breakpoint"; public const string InstructionPointerMarker = "Current statement"; + public const string ColumnRuler = "Column ruler"; public static void ApplyCustomizationsToDefaultElements(TextEditor textEditor, IEnumerable customizations) { @@ -43,7 +44,7 @@ namespace ICSharpCode.AvalonEdit.AddIn textEditor.TextArea.TextView.ClearValue(TextView.NonPrintableCharacterBrushProperty); textEditor.TextArea.TextView.ClearValue(TextView.LinkTextForegroundBrushProperty); textEditor.TextArea.TextView.ClearValue(TextView.LinkTextBackgroundBrushProperty); - textEditor.TextArea.TextView.ClearValue(TextView.ColumnRulerBrushProperty); + textEditor.TextArea.TextView.ClearValue(TextView.ColumnRulerPenProperty); // 'assigned' flags are used so that the first matching customization wins. // This is necessary because more specific customizations come first in the list @@ -110,12 +111,12 @@ namespace ICSharpCode.AvalonEdit.AddIn if (color.Background != null) textEditor.TextArea.TextView.LinkTextBackgroundBrush = CreateFrozenBrush(color.Background.Value); break; - case ColumnRulerRenderer.Name: + case ColumnRuler: if (assignedColumnRulerColor) continue; assignedColumnRulerColor = true; if (color.Foreground != null) - textEditor.TextArea.TextView.ColumnRulerBrush = CreateFrozenBrush(color.Foreground.Value); + textEditor.TextArea.TextView.ColumnRulerPen = CreateFrozenPen(color.Foreground.Value); break; } } @@ -347,5 +348,12 @@ namespace ICSharpCode.AvalonEdit.AddIn brush.Freeze(); return brush; } + + static Pen CreateFrozenPen(Color color) + { + Pen pen = new Pen(CreateFrozenBrush(color), 1); + pen.Freeze(); + return pen; + } } } diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Options/HighlightingOptions.xaml.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Options/HighlightingOptions.xaml.cs index b2f7dad566..4a46f0fe43 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Options/HighlightingOptions.xaml.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Options/HighlightingOptions.xaml.cs @@ -431,14 +431,14 @@ namespace ICSharpCode.AvalonEdit.AddIn.Options items.Add(currentStatementMarker); IHighlightingItem columnRuler = new SimpleHighlightingItem( - ColumnRulerRenderer.Name, + CustomizableHighlightingColorizer.ColumnRuler, ta => { ta.Document.Text = "some line with a lot of text"; ta.TextView.Options.ColumnRulerPosition = 15; ta.TextView.Options.ShowColumnRuler = true; }) { - Foreground = ColumnRulerRenderer.DefaultForeground + Foreground = Colors.LightGray }; columnRuler = new CustomizedHighlightingItem(customizationList, columnRuler, language, canSetFont: false, canSetBackground: false); columnRuler.PropertyChanged += item_PropertyChanged; diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/XmlDoc/XmlDocTooltipProvider.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/XmlDoc/XmlDocTooltipProvider.cs index 1dd2047a18..e1c0bb1484 100644 --- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/XmlDoc/XmlDocTooltipProvider.cs +++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/XmlDoc/XmlDocTooltipProvider.cs @@ -4,6 +4,7 @@ using System; using System.Windows; using System.Windows.Controls; +using System.Windows.Controls.Primitives; using System.Windows.Documents; using System.Windows.Media; using ICSharpCode.AvalonEdit.AddIn.Options; @@ -34,7 +35,7 @@ namespace ICSharpCode.AvalonEdit.AddIn.XmlDoc } } - sealed class FlowDocumentTooltip : Border, ITooltip + sealed class FlowDocumentTooltip : Popup, ITooltip { FlowDocumentScrollViewer viewer; @@ -42,26 +43,23 @@ namespace ICSharpCode.AvalonEdit.AddIn.XmlDoc { viewer = new FlowDocumentScrollViewer(); viewer.Document = document; - this.Child = viewer; - - this.Background = SystemColors.InfoBrush; + Border border = new Border { + Background = SystemColors.InfoBrush, + BorderBrush = SystemColors.InfoTextBrush, + BorderThickness = new Thickness(1), + MaxHeight = 400, + Child = viewer + }; + this.Child = border; viewer.Foreground = SystemColors.InfoTextBrush; - this.BorderBrush = SystemColors.InfoTextBrush; - this.BorderThickness = new Thickness(1); - this.MaxHeight = 400; document.FontSize = CodeEditorOptions.Instance.FontSize; } public event RoutedEventHandler Closed { add {} remove {} } - public bool ShowAsPopup { + public bool CloseOnHoverEnd { get { return true; } } - - public bool Close(bool mouseClick) - { - return true; - } } object CreateTooltip(IType type) diff --git a/src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/CodeView.cs b/src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/CodeView.cs index aab1ac03d0..e5c89b553b 100644 --- a/src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/CodeView.cs +++ b/src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/CodeView.cs @@ -76,7 +76,7 @@ namespace ICSharpCode.ILSpyAddIn.ViewContent #region Popup ToolTip toolTip; - Popup popup; + Popup popupToolTip; void TextEditorMouseHover(object sender, MouseEventArgs e) { @@ -92,24 +92,19 @@ namespace ICSharpCode.ILSpyAddIn.ViewContent ToolTipRequestService.RequestToolTip(args); } + if (!TryCloseExistingPopup(false)) { + return; + } + if (args.ContentToShow != null) { - var contentToShowITooltip = args.ContentToShow as ITooltip; + popupToolTip = args.ContentToShow as Popup; - if (contentToShowITooltip != null && contentToShowITooltip.ShowAsPopup) { - if (!(args.ContentToShow is UIElement)) { - throw new NotSupportedException("Content to show in Popup must be UIElement: " + args.ContentToShow); - } - if (popup == null) { - popup = CreatePopup(); - } - if (TryCloseExistingPopup(false)) { - // when popup content decides to close, close the popup - contentToShowITooltip.Closed += (closedSender, closedArgs) => { popup.IsOpen = false; }; - popup.Child = (UIElement)args.ContentToShow; - //ICSharpCode.SharpDevelop.Debugging.DebuggerService.CurrentDebugger.IsProcessRunningChanged - SetPopupPosition(popup, e); - popup.IsOpen = true; - } + if (popupToolTip != null) { + var popupPosition = GetPopupPosition(e); + popupToolTip.HorizontalOffset = popupPosition.X; + popupToolTip.VerticalOffset = popupPosition.Y; + popupToolTip.IsOpen = true; + popupToolTip.StaysOpen = true; // We will close it ourselves e.Handled = true; } else { if (toolTip == null) { @@ -131,35 +126,19 @@ namespace ICSharpCode.ILSpyAddIn.ViewContent toolTip.IsOpen = true; e.Handled = true; } - } else { - // close popup if mouse hovered over empty area - if (popup != null) { - e.Handled = true; - } - TryCloseExistingPopup(false); } } bool TryCloseExistingPopup(bool mouseClick) { - bool canClose = true; - if (popup != null) { - var popupContentITooltip = popup.Child as ITooltip; - if (popupContentITooltip != null) { - canClose = popupContentITooltip.Close(mouseClick); - } - if (canClose) { - popup.IsOpen = false; + if (popupToolTip != null) { + if (popupToolTip.IsOpen && !mouseClick && popupToolTip is ITooltip && !((ITooltip)popupToolTip).CloseOnHoverEnd) { + return false; // Popup does not want to be closed yet } + popupToolTip.IsOpen = false; + popupToolTip = null; } - return canClose; - } - - void SetPopupPosition(Popup popup, MouseEventArgs mouseArgs) - { - var popupPosition = GetPopupPosition(mouseArgs); - popup.HorizontalOffset = popupPosition.X; - popup.VerticalOffset = popupPosition.Y; + return true; } /// Returns Popup position based on mouse position, in device independent units @@ -182,17 +161,6 @@ namespace ICSharpCode.ILSpyAddIn.ViewContent return positionInPixels.TransformFromDevice(this); } - Popup CreatePopup() - { - popup = new Popup(); - popup.Closed += (s, e) => popup = null; - popup.AllowsTransparency = true; - popup.PlacementTarget = this; // required for property inheritance - popup.Placement = PlacementMode.Absolute; - popup.StaysOpen = true; - return popup; - } - void TextEditorMouseHoverStopped(object sender, MouseEventArgs e) { if (toolTip != null) { @@ -205,7 +173,7 @@ namespace ICSharpCode.ILSpyAddIn.ViewContent void TextEditorMouseLeave(object sender, MouseEventArgs e) { - if (popup != null && !popup.IsMouseOver) { + if (popupToolTip != null && !popupToolTip.IsMouseOver) { // do not close popup if mouse moved from editor to popup TryCloseExistingPopup(false); } diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/ColumnRulerRenderer.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/ColumnRulerRenderer.cs index f809b57de4..bcf5772d76 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/ColumnRulerRenderer.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/ColumnRulerRenderer.cs @@ -8,18 +8,17 @@ using System.Windows.Media; using ICSharpCode.AvalonEdit.Rendering; using ICSharpCode.AvalonEdit.Utils; -namespace ICSharpCode.AvalonEdit +namespace ICSharpCode.AvalonEdit.Rendering { /// /// Renders a ruler at a certain column. /// - public class ColumnRulerRenderer : IBackgroundRenderer + sealed class ColumnRulerRenderer : IBackgroundRenderer { Pen pen; int column; TextView textView; - public const string Name = "Column ruler"; public static readonly Color DefaultForeground = Colors.LightGray; public ColumnRulerRenderer(TextView textView) @@ -37,15 +36,14 @@ namespace ICSharpCode.AvalonEdit get { return KnownLayer.Background; } } - public void SetRuler(int column, Brush brush) + public void SetRuler(int column, Pen pen) { if (this.column != column) { this.column = column; textView.InvalidateLayer(this.Layer); } - if (pen.Brush != brush) { - this.pen = new Pen(brush, 1); - this.pen.Freeze(); + if (this.pen != pen) { + this.pen = pen; textView.InvalidateLayer(this.Layer); } } diff --git a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs index 5355858c57..e8c19f53cf 100644 --- a/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs +++ b/src/Libraries/AvalonEdit/ICSharpCode.AvalonEdit/Rendering/TextView.cs @@ -54,7 +54,7 @@ namespace ICSharpCode.AvalonEdit.Rendering backgroundRenderers = new ObserveAddRemoveCollection(BackgroundRenderer_Added, BackgroundRenderer_Removed); columnRulerRenderer = new ColumnRulerRenderer(this); this.Options = new TextEditorOptions(); - this.columnRulerRenderer.SetRuler(Options.ColumnRulerPosition, ColumnRulerBrush); + this.columnRulerRenderer.SetRuler(Options.ColumnRulerPosition, ColumnRulerPen); Debug.Assert(singleCharacterElementGenerator != null); // assert that the option change created the builtin element generators @@ -204,13 +204,10 @@ namespace ICSharpCode.AvalonEdit.Rendering OptionChanged(this, e); } - // PropertyName == null means all properties are changed - if (e.PropertyName == null || e.PropertyName == "ColumnRulerPosition" || e.PropertyName == "ShowColumnRuler") { - if (Options.ShowColumnRuler) - columnRulerRenderer.SetRuler(Options.ColumnRulerPosition, ColumnRulerBrush); - else - columnRulerRenderer.SetRuler(-1, ColumnRulerBrush); - } + if (Options.ShowColumnRuler) + columnRulerRenderer.SetRuler(Options.ColumnRulerPosition, ColumnRulerPen); + else + columnRulerRenderer.SetRuler(-1, ColumnRulerPen); UpdateBuiltinElementGeneratorsFromOptions(); Redraw(); @@ -1951,24 +1948,33 @@ namespace ICSharpCode.AvalonEdit.Rendering InvalidateDefaultTextMetrics(); Redraw(); } + if (e.Property == ColumnRulerPenProperty) { + columnRulerRenderer.SetRuler(this.Options.ColumnRulerPosition, this.ColumnRulerPen); + } } - public static readonly DependencyProperty ColumnRulerBrushProperty = - DependencyProperty.Register("ColumnRulerBrush", typeof(Brush), typeof(TextView), - new FrameworkPropertyMetadata(Brushes.LightGray, OnUpdateBrushes)); - - public Brush ColumnRulerBrush { - get { return (Brush)GetValue(ColumnRulerBrushProperty); } - set { SetValue(ColumnRulerBrushProperty, value); } - } + /// + /// The pen used to draw the column ruler. + /// + /// + public static readonly DependencyProperty ColumnRulerPenProperty = + DependencyProperty.Register("ColumnRulerBrush", typeof(Pen), typeof(TextView), + new FrameworkPropertyMetadata(CreateFrozenPen(Brushes.LightGray))); - public static void OnUpdateBrushes(DependencyObject d, DependencyPropertyChangedEventArgs e) + static Pen CreateFrozenPen(SolidColorBrush brush) { - TextView view = d as TextView; - if (view == null) return; - if (e.Property == ColumnRulerBrushProperty) - view.columnRulerRenderer.SetRuler(view.Options.ColumnRulerPosition, (Brush)e.NewValue); + Pen pen = new Pen(brush, 1); + pen.Freeze(); + return pen; } + /// + /// Gets/Sets the pen used to draw the column ruler. + /// + /// + public Pen ColumnRulerPen { + get { return (Pen)GetValue(ColumnRulerPenProperty); } + set { SetValue(ColumnRulerPenProperty, value); } + } } } diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin b/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin index b8bfada506..caf3d4c544 100755 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin @@ -1142,12 +1142,12 @@ + class = "ICSharpCode.SharpDevelop.Bookmarks.DeleteMark"/> + class = "ICSharpCode.SharpDevelop.Bookmarks.DeleteAllMarks"/> diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index f7e840c8fa..bab5fa831b 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -94,9 +94,6 @@ Src\Project\MSBuildEngine\ExtendedBinaryReader.cs - - ListViewPad.xaml - @@ -372,10 +369,6 @@ - - - - @@ -661,8 +654,6 @@ - - @@ -815,7 +806,7 @@ - + @@ -851,13 +842,11 @@ - - diff --git a/src/Main/Base/Project/Src/Bookmarks/BookmarkBase.cs b/src/Main/Base/Project/Src/Bookmarks/BookmarkBase.cs index 97044671de..6b650d8951 100644 --- a/src/Main/Base/Project/Src/Bookmarks/BookmarkBase.cs +++ b/src/Main/Base/Project/Src/Bookmarks/BookmarkBase.cs @@ -3,8 +3,11 @@ using System; using System.Windows.Input; +using System.Windows.Media; + using ICSharpCode.NRefactory; using ICSharpCode.NRefactory.Editor; +using ICSharpCode.SharpDevelop.Editor; namespace ICSharpCode.SharpDevelop.Bookmarks { @@ -155,6 +158,10 @@ namespace ICSharpCode.SharpDevelop.Bookmarks get { return DefaultBookmarkImage; } } + public ImageSource ImageSource { + get { return this.Image != null ? this.Image.ImageSource : null; } + } + public virtual void MouseDown(MouseButtonEventArgs e) { } diff --git a/src/Main/Base/Project/Src/Bookmarks/BookmarkConverter.cs b/src/Main/Base/Project/Src/Bookmarks/BookmarkConverter.cs index 1d65aad0b3..ada0bb7036 100644 --- a/src/Main/Base/Project/Src/Bookmarks/BookmarkConverter.cs +++ b/src/Main/Base/Project/Src/Bookmarks/BookmarkConverter.cs @@ -63,24 +63,6 @@ namespace ICSharpCode.SharpDevelop.Bookmarks bbm.Condition = script; bookmark = bbm; break; - case "PinBookmark": - var pin = new PinBookmark(fileName, new TextLocation(lineNumber, columnNumber)); - pin.Comment = v[4]; - pin.PinPosition = - new Point - { - X = double.Parse(v[5], culture), - Y = double.Parse(v[6], culture) - }; - - // pop-up nodes - pin.SavedNodes = new System.Collections.Generic.List>(); - for (int i = 7; i < v.Length; i+=3) { - pin.SavedNodes.Add(new Tuple(v[i], v[i+1], v[i+2])); - } - - bookmark = pin; - break; default: bookmark = new Bookmark(fileName, new TextLocation(lineNumber, columnNumber)); break; @@ -101,10 +83,7 @@ namespace ICSharpCode.SharpDevelop.Bookmarks } else if (bookmark is Debugging.BreakpointBookmark) { b.Append("Breakpoint"); } else { - if (bookmark is PinBookmark) - b.Append("PinBookmark"); - else - b.Append("Bookmark"); + b.Append("Bookmark"); } b.Append('|'); b.Append(bookmark.FileName); @@ -135,27 +114,6 @@ namespace ICSharpCode.SharpDevelop.Bookmarks b.Append(bbm.Condition); } - if (bookmark is PinBookmark) { - var pin = (PinBookmark)bookmark; - b.Append('|'); - b.Append(pin.Comment ?? string.Empty); - - // popup position - b.Append('|'); - b.Append(pin.PinPosition.Value.X); - b.Append('|'); - b.Append(pin.PinPosition.Value.Y); - - //popup nodes - foreach(var node in pin.Nodes) { - b.Append('|'); - b.Append(node.ImageName); - b.Append('|'); - b.Append(node.FullName); - b.Append('|'); - b.Append(node.Text); - } - } return b.ToString(); } else { return base.ConvertTo(context, culture, value, destinationType); diff --git a/src/Main/Base/Project/Src/Bookmarks/Pad/BookmarkPad.cs b/src/Main/Base/Project/Src/Bookmarks/Pad/BookmarkPad.cs index 333b05a8d9..491cb932f2 100644 --- a/src/Main/Base/Project/Src/Bookmarks/Pad/BookmarkPad.cs +++ b/src/Main/Base/Project/Src/Bookmarks/Pad/BookmarkPad.cs @@ -3,12 +3,11 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Windows; using System.Windows.Controls; - using ICSharpCode.Core; using ICSharpCode.Core.Presentation; -using ICSharpCode.SharpDevelop.Bookmarks.Pad.Controls; using ICSharpCode.SharpDevelop.Debugging; using ICSharpCode.SharpDevelop.Gui; @@ -16,108 +15,57 @@ namespace ICSharpCode.SharpDevelop.Bookmarks { public sealed class BookmarkPad : BookmarkPadBase { - static BookmarkPad instance; - - public static BookmarkPad Instance { - get { - if (instance == null) { - WorkbenchSingleton.Workbench.GetPad(typeof(BookmarkPad)).CreatePad(); - } - return instance; - } - } - - protected override ToolBar CreateToolBar() + public BookmarkPad() { - ToolBar toolbar = ToolBarService.CreateToolBar(myPanel, this, "/SharpDevelop/Pads/BookmarkPad/Toolbar"); - toolbar.SetValue(Grid.RowProperty, 0); - return toolbar; + ToolBar toolbar = ToolBarService.CreateToolBar((UIElement)this.Control, this, "/SharpDevelop/Pads/BookmarkPad/Toolbar"); + this.control.Children.Add(toolbar); } - protected override void CreateColumns() { } - - public BookmarkPad() + protected override bool ShowBookmarkInThisPad(SDBookmark bookmark) { - instance = this; - myPanel.Children.Add(CreateToolBar()); - listView.HideColumns(2, 0); + return bookmark.IsVisibleInBookmarkPad && !(bookmark is BreakpointBookmark); } } public abstract class BookmarkPadBase : AbstractPadContent { - protected Grid myPanel = new Grid(); - protected ListViewPad listView = new ListViewPad(); + protected BookmarkPadContent control; public override object Control { - get { - return myPanel; - } + get { return this.control; } } - public ListViewPadItemModel CurrentItem { - get { - return listView.CurrentItem; - } + public ListView ListView { + get { return this.control.listView; } } - protected abstract ToolBar CreateToolBar(); + public ItemCollection Items { + get { return this.control.listView.Items; } + } - protected abstract void CreateColumns(); + public SDBookmark SelectedItem { + get { return (SDBookmark)this.control.listView.SelectedItem; } + } protected BookmarkPadBase() { - myPanel.RowDefinitions.Add(new RowDefinition { Height = GridLength.Auto }); - myPanel.RowDefinitions.Add(new RowDefinition()); - listView.SetValue(Grid.RowProperty, 1); - myPanel.Children.Add(listView); + this.control = new BookmarkPadContent(); + this.control.InitializeComponent(); BookmarkManager.Added += BookmarkManagerAdded; BookmarkManager.Removed += BookmarkManagerRemoved; - foreach (SDBookmark mark in BookmarkManager.Bookmarks) { - AddMark(mark); - } - - listView.ItemActivated += new EventHandler(OnItemActivated); - } - - public IEnumerable AllItems { - get { - foreach (var item in listView.ItemCollection) { - yield return item; + foreach (SDBookmark bookmark in BookmarkManager.Bookmarks) { + if (ShowBookmarkInThisPad(bookmark)) { + this.Items.Add(bookmark); } } - } - - public ListViewPadItemModel NextItem { - get { - return this.listView.NextItem; - } - } - - public ListViewPadItemModel PreviousItem { - get { - return this.listView.PreviousItem; - } - } - - public void EnableDisableAll() - { - bool isOneChecked = false; - foreach (var node in AllItems) { - if (node.IsChecked) { - isOneChecked = true; - break; - } - } - foreach (var node in AllItems) - node.IsChecked = !isOneChecked; - } - - public void SelectItem(ListViewPadItemModel model) - { - listView.CurrentItem = model; + + this.control.listView.MouseDoubleClick += delegate { + SDBookmark bm = this.control.listView.SelectedItem as SDBookmark; + if (bm != null) + OnItemActivated(bm); + }; } public override void Dispose() @@ -126,60 +74,23 @@ namespace ICSharpCode.SharpDevelop.Bookmarks BookmarkManager.Removed -= BookmarkManagerRemoved; } - void AddMark(SDBookmark mark) - { - if (!ShowBookmarkInThisPad(mark)) - return; - - var model = new ListViewPadItemModel(mark); - model.PropertyChanged += OnModelPropertyChanged; - listView.Add(model); - } + protected abstract bool ShowBookmarkInThisPad(SDBookmark mark); - protected virtual bool ShowBookmarkInThisPad(SDBookmark mark) + protected virtual void OnItemActivated(SDBookmark bm) { - return mark.IsVisibleInBookmarkPad && !(mark is BreakpointBookmark); - } - - protected virtual void OnItemActivated(object sender, EventArgs e) - { - var node = CurrentItem; - if (node != null) { - SDBookmark mark = node.Mark as SDBookmark; - if (mark != null) { - FileService.JumpToFilePosition(mark.FileName, mark.LineNumber, 1); - } - } + FileService.JumpToFilePosition(bm.FileName, bm.LineNumber, 1); } void BookmarkManagerAdded(object sender, BookmarkEventArgs e) - { - AddMark(e.Bookmark); - } - - void BookmarkManagerRemoved(object sender, BookmarkEventArgs e) { if (ShowBookmarkInThisPad(e.Bookmark)) { - var model = listView.Remove(e.Bookmark); - if (model != null) - model.PropertyChanged -= OnModelPropertyChanged; + this.Items.Add(e.Bookmark); } } - void OnModelPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) + void BookmarkManagerRemoved(object sender, BookmarkEventArgs e) { - var model = sender as ListViewPadItemModel; - if (e.PropertyName == "IsChecked") { - if (model.Mark is BreakpointBookmark) { - var bpm = model.Mark as BreakpointBookmark; - bpm.IsEnabled = model.IsChecked; - if (model.IsChecked) { - model.Image = string.IsNullOrEmpty(model.Condition) ? BreakpointBookmark.BreakpointImage.ImageSource : BreakpointBookmark.BreakpointConditionalImage.ImageSource; - } else { - model.Image = BreakpointBookmark.DisabledBreakpointImage.ImageSource; - } - } - } + this.Items.Remove(e.Bookmark); } } } \ No newline at end of file diff --git a/src/Main/Base/Project/Src/Bookmarks/Pad/BookmarkPadContent.xaml b/src/Main/Base/Project/Src/Bookmarks/Pad/BookmarkPadContent.xaml new file mode 100644 index 0000000000..b29cd843b6 --- /dev/null +++ b/src/Main/Base/Project/Src/Bookmarks/Pad/BookmarkPadContent.xaml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Main/Base/Project/Src/Bookmarks/Pad/BookmarkPadToolbarCommands.cs b/src/Main/Base/Project/Src/Bookmarks/Pad/BookmarkPadToolbarCommands.cs index a665d2f839..6b00672959 100644 --- a/src/Main/Base/Project/Src/Bookmarks/Pad/BookmarkPadToolbarCommands.cs +++ b/src/Main/Base/Project/Src/Bookmarks/Pad/BookmarkPadToolbarCommands.cs @@ -7,116 +7,65 @@ using System.Linq; using System.Windows.Forms; using ICSharpCode.Core; -using ICSharpCode.SharpDevelop.Bookmarks.Pad.Controls; using ICSharpCode.SharpDevelop.Debugging; namespace ICSharpCode.SharpDevelop.Bookmarks { - #region Goto Commands - public abstract class NextPrevBookmarkPadCommand : AbstractMenuCommand - { - public void Run(ListViewPadItemModel item) - { - var bookmarkBase = (BookmarkPadBase)Owner; - - if (item == null) return; - - // get current mark - var mark = item.Mark as SDBookmark; - int line = mark.LineNumber; - var fileName = mark.FileName; - - SDBookmark bookmark; - if (item.Mark is BreakpointBookmark) { - var bookmarks = DebuggerService.Breakpoints; - bookmark = bookmarks.FirstOrDefault(b => b.LineNumber == line && b.FileName == fileName); - if (bookmark == null && bookmarks.Count > 0) { - bookmark = bookmarks[0]; // jump around to first bookmark - } - } - else { - var bookmarks = BookmarkManager.Bookmarks; - bookmark = bookmarks.FirstOrDefault(b => b.LineNumber == line && b.FileName == fileName); - if (bookmark == null && bookmarks.Count > 0) { - bookmark = bookmarks[0]; // jump around to first bookmark - } - } - - if (bookmark != null) { - FileService.JumpToFilePosition(bookmark.FileName, bookmark.LineNumber, bookmark.ColumnNumber); - } - - // select in tree - bookmarkBase.SelectItem(item); - } - } - - public sealed class NextBookmarkPadCommand : NextPrevBookmarkPadCommand + public sealed class NextBookmarkPadCommand : AbstractMenuCommand { public override void Run() { - var bookmarkBase = (BookmarkPadBase)Owner; - var nextItem = bookmarkBase.NextItem; - - Run(nextItem); + BookmarkPadBase pad = (BookmarkPadBase)this.Owner; + if (pad.ListView.Items.Count > 0) { + pad.ListView.SelectedIndex = (pad.ListView.SelectedIndex + 1) % pad.ListView.Items.Count; + FileService.JumpToFilePosition(pad.SelectedItem.FileName, pad.SelectedItem.LineNumber, pad.SelectedItem.ColumnNumber); + } } } - public sealed class PrevBookmarkPadCommand : NextPrevBookmarkPadCommand + public sealed class PrevBookmarkPadCommand : AbstractMenuCommand { public override void Run() { - var bookmarkBase = (BookmarkPadBase)Owner; - var prevItem = bookmarkBase.PreviousItem; - - Run(prevItem); - } - } - #endregion Goto Commands - - #region Delete BookMark(s) commands - - public abstract class AbstractDeleteMarkClass : AbstractMenuCommand - { - protected void deleteBookMark (SDBookmark bookmark) { - if (bookmark == null) return; - if (bookmark is BreakpointBookmark) return; - ICSharpCode.SharpDevelop.Bookmarks.BookmarkManager.RemoveMark(bookmark); + BookmarkPadBase pad = (BookmarkPadBase)this.Owner; + if (pad.ListView.Items.Count > 0) { + pad.ListView.SelectedIndex = (pad.ListView.SelectedIndex - 1 + pad.ListView.Items.Count) % pad.ListView.Items.Count; + FileService.JumpToFilePosition(pad.SelectedItem.FileName, pad.SelectedItem.LineNumber, pad.SelectedItem.ColumnNumber); + } } } - /// - /// Deletes all s in the BookMarkPad. - /// - public class DeleteAllMarks : AbstractDeleteMarkClass + public class DeleteAllMarks : AbstractMenuCommand { public override void Run() { - BookmarkManager.RemoveAll(b => !(b is BreakpointBookmark)); + BookmarkPadBase pad = (BookmarkPadBase)this.Owner; + foreach(SDBookmark bm in pad.Items.OfType().ToList()) { + BookmarkManager.RemoveMark(bm); + } } } - /// - /// Deletes the currently selected or - /// - public class DeleteMark : AbstractDeleteMarkClass + public class DeleteMark : AbstractMenuCommand { public override void Run() { - var node = ((BookmarkPadBase)Owner).CurrentItem; - if (node == null) return; - - deleteBookMark(node.Mark as SDBookmark); + BookmarkPadBase pad = (BookmarkPadBase)this.Owner; + if (pad.SelectedItem != null) { + BookmarkManager.RemoveMark(pad.SelectedItem); + } } } - #endregion Delete BookMark(s) commands - public class EnableDisableAll : AbstractMenuCommand { public override void Run() { - ((BookmarkPadBase)Owner).EnableDisableAll(); + BookmarkPadBase pad = (BookmarkPadBase)this.Owner; + bool anyEnabled = pad.Items.OfType().Any(bp => bp.IsEnabled); + foreach (var bp in pad.Items.OfType()) { + bp.IsEnabled = !anyEnabled; + } } } } diff --git a/src/Main/Base/Project/Src/Bookmarks/Pad/Controls/ListViewPad.xaml b/src/Main/Base/Project/Src/Bookmarks/Pad/Controls/ListViewPad.xaml deleted file mode 100644 index dbc714cc73..0000000000 --- a/src/Main/Base/Project/Src/Bookmarks/Pad/Controls/ListViewPad.xaml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/Main/Base/Project/Src/Bookmarks/Pad/Controls/ListViewPad.xaml.cs b/src/Main/Base/Project/Src/Bookmarks/Pad/Controls/ListViewPad.xaml.cs deleted file mode 100644 index 4876bbbf7d..0000000000 --- a/src/Main/Base/Project/Src/Bookmarks/Pad/Controls/ListViewPad.xaml.cs +++ /dev/null @@ -1,241 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using System; -using System.Collections.ObjectModel; -using System.ComponentModel; -using System.IO; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Input; -using System.Windows.Media; - -using ICSharpCode.Core; -using ICSharpCode.SharpDevelop.Debugging; - -namespace ICSharpCode.SharpDevelop.Bookmarks.Pad.Controls -{ - /// - /// ListViewPad inside WPF pads. - /// - public sealed partial class ListViewPad : UserControl - { - ObservableCollection itemCollection = new ObservableCollection(); - - public ObservableCollection ItemCollection { - get { return itemCollection; } - } - - public event EventHandler ItemActivated; - - public ListViewPad() - { - InitializeComponent(); - - this.MyListView.PreviewMouseDoubleClick += new MouseButtonEventHandler(ListViewPad_PreviewMouseDoubleClick); - this.MyListView.KeyDown += new KeyEventHandler(ListViewPad_KeyDown); - } - - public ListViewPadItemModel CurrentItem { - get { - if (MyListView.SelectedItem == null && MyListView.Items.Count > 0) - this.MyListView.SelectedItem = MyListView.Items[0]; - - return MyListView.SelectedItem as ListViewPadItemModel; - } - set { - if (value == null) return; - - this.MyListView.SelectedItem = value; - } - } - - public ListViewPadItemModel NextItem { - get { - bool found = false; - foreach (var line in ItemCollection) { - if (found) - return line; - if (line == CurrentItem) - found = true; - } - - return null; - } - } - - public ListViewPadItemModel PreviousItem { - get { - bool found = false; - ListViewPadItemModel prev = null; - foreach (var line in ItemCollection) { - if (found) - return prev; - if (line == CurrentItem) { - found = true; - } - else { - prev = line; - } - } - - return prev; - } - } - - public void Add(ListViewPadItemModel item) - { - if (item == null) return; - ItemCollection.Add(item); - } - - public ListViewPadItemModel Remove(SDBookmark bookmark) - { - if (bookmark is CurrentLineBookmark) - return null; - - foreach (var model in itemCollection) { - SDBookmark currentBookmark = model.Mark as SDBookmark; - - if (bookmark.FileName == currentBookmark.FileName && - bookmark.LineNumber == currentBookmark.LineNumber) { - ItemCollection.Remove(model); - return model; - } - } - - return null; - } - - public void AddColumn(string header, DataTemplate cellTemplate) - { - GridViewColumn column = new GridViewColumn(); - column.Header = header; - column.CellTemplate = cellTemplate; - ((GridView)this.MyListView.View).Columns.Add(column); - } - - /// - /// Indexes from end to start. - /// - /// - public void HideColumns(params int[] columnIndexes) - { - foreach(int i in columnIndexes) - ((GridView)MyListView.View).Columns.RemoveAt(i); - } - - private void ListViewPad_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e) - { - var handler = ItemActivated; - - if (handler != null) - ItemActivated(this, EventArgs.Empty); - } - - private void ListViewPad_KeyDown(object sender, KeyEventArgs e) - { - if (e.Key == Key.Escape) { - this.MyListView.UnselectAll(); - e.Handled = true; - } - } - } - - public sealed class ListViewPadItemModel : INotifyPropertyChanged - { - bool isChecked; - object tag; - string language; - string condition; - ImageSource imageSource; - - public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged; - - public ListViewPadItemModel(SDBookmark mark) - { - if (mark is BreakpointBookmark) { - isChecked = ((BreakpointBookmark)mark).IsEnabled; - condition = ((BreakpointBookmark)mark).Condition; - language = ((BreakpointBookmark)mark).ScriptLanguage; - } - - imageSource = mark.Image.ImageSource; - - Location = GetLocation(mark); - Mark = mark; - tag = this; - } - - public bool IsChecked { - get { - return isChecked; - } - set { - if (value != isChecked) - { - isChecked = value; - NotifyPropertyChanged("IsChecked"); - } - } - } - - public SDBookmark Mark { - get; set; - } - - public ImageSource Image { - get { return imageSource; } - set { - imageSource = value; - NotifyPropertyChanged("Image"); - } - } - - public string Location { - get; private set; - } - - public string Language { - get { return language; } - set { - language = value; - NotifyPropertyChanged("Language"); - } - } - - public string Condition { - get { return condition; } - set { - condition = value; - NotifyPropertyChanged("Condition"); - } - } - - public object Tag { - get { return tag;} - set { - tag = value; - NotifyPropertyChanged("Tag"); - } - } - - public override string ToString() - { - return Location; - } - - private string GetLocation(SDBookmark bookmark) - { - return string.Format(StringParser.Parse("${res:MainWindow.Windows.BookmarkPad.LineText}"), - Path.GetFileName(bookmark.FileName), bookmark.LineNumber); - } - - private void NotifyPropertyChanged(string property) - { - if (PropertyChanged != null) { - PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(property)); - } - } - } -} \ No newline at end of file diff --git a/src/Main/Base/Project/Src/Bookmarks/Pad/Nodes/BookmarkFolderNode.cs b/src/Main/Base/Project/Src/Bookmarks/Pad/Nodes/BookmarkFolderNode.cs deleted file mode 100644 index d30b5ed142..0000000000 --- a/src/Main/Base/Project/Src/Bookmarks/Pad/Nodes/BookmarkFolderNode.cs +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using System; -using System.Collections.Generic; -using System.Drawing; -using System.IO; -using System.Windows.Forms; - -using ICSharpCode.Core; -using ICSharpCode.SharpDevelop.Gui; - -namespace ICSharpCode.SharpDevelop.Bookmarks -{ - /// - /// Description of SearchFolderNode. - /// - public class BookmarkFolderNode : ExtFolderNode - { - List marks = new List(); - string fileName; - string fileNameText; - string occurences; - Image icon; - - public List Marks { - get { - return marks; - } - } - - public BookmarkFolderNode(string fileName) - { - drawDefault = false; - this.fileName = fileName; - fileNameText = Path.GetFileName(fileName) + StringParser.Parse(" ${res:MainWindow.Windows.SearchResultPanel.In} ") + Path.GetDirectoryName(fileName); - icon = IconService.GetBitmap(IconService.GetImageForFile(fileName)); - Nodes.Add(new TreeNode()); - } - - public void SetText() - { - if (marks.Count == 1) { - occurences = " (1 bookmark)"; - } else { - occurences = " (" + marks.Count + " bookmarks)"; - } - this.Text = fileNameText + occurences; - } - - protected override int MeasureItemWidth(DrawTreeNodeEventArgs e) - { - Graphics g = e.Graphics; - int x = MeasureTextWidth(g, fileNameText, RegularBigFont); - x += MeasureTextWidth(g, occurences, ItalicBigFont); - if (icon != null) { - x += icon.Width; - } - return x + 3; - } - protected override void DrawForeground(DrawTreeNodeEventArgs e) - { - Graphics g = e.Graphics; - float x = e.Bounds.X; - if (icon != null) { - g.DrawImage(icon, x, e.Bounds.Y, icon.Width, icon.Height); - x += icon.Width + 2; - } - DrawText(e, fileNameText, SystemBrushes.WindowText, RegularBigFont, ref x); - DrawText(e, occurences, SystemBrushes.GrayText, ItalicBigFont, ref x); - } - - public void AddMark(SDBookmark mark) - { - int index = -1; - for (int i = 0; i < marks.Count; ++i) { - if (mark.LineNumber < marks[i].LineNumber) { - index = i; - break; - } - } - if (index < 0) - marks.Add(mark); - else - marks.Insert(index, mark); - - if (isInitialized) { - BookmarkNode newNode = new BookmarkNode(mark); - if (index < 0) - Nodes.Add(newNode); - else - Nodes.Insert(index, newNode); - newNode.EnsureVisible(); - } - SetText(); - } - - public void RemoveMark(SDBookmark mark) - { - marks.Remove(mark); - if (isInitialized) { - for (int i = 0; i < Nodes.Count; ++i) { - if (((BookmarkNode)Nodes[i]).Bookmark == mark) { - Nodes.RemoveAt(i); - break; - } - } - } - SetText(); - } - - protected override void Initialize() - { - Nodes.Clear(); - if (marks.Count > 0) { -// IDocument document = marks[0].Document; -// if (document != null && document.HighlightingStrategy == null) { -// document.HighlightingStrategy = HighlightingStrategyFactory.CreateHighlightingStrategyForFile(fileName); -// } - foreach (SDBookmark mark in marks) { - TreeNode newResult = new BookmarkNode(mark); - Nodes.Add(newResult); - } - } - } - } -} diff --git a/src/Main/Base/Project/Src/Bookmarks/Pad/Nodes/BookmarkNode.cs b/src/Main/Base/Project/Src/Bookmarks/Pad/Nodes/BookmarkNode.cs deleted file mode 100644 index 746a95120f..0000000000 --- a/src/Main/Base/Project/Src/Bookmarks/Pad/Nodes/BookmarkNode.cs +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using System; -using System.Drawing; -using System.Windows.Forms; - -using ICSharpCode.SharpDevelop.Gui; - -namespace ICSharpCode.SharpDevelop.Bookmarks -{ - /// - /// ExtTreeNode representing a bookmark. - /// - public class BookmarkNode : ExtTreeNode - { - SDBookmark bookmark; - //LineSegment line; - - SizeF spaceSize; - static StringFormat sf = (StringFormat)System.Drawing.StringFormat.GenericTypographic.Clone(); - - string positionText; - - public SDBookmark Bookmark { - get { - return bookmark; - } - } - - public BookmarkNode(SDBookmark bookmark) - { - drawDefault = false; - this.bookmark = bookmark; - Tag = bookmark; -// Checked = bookmark.IsEnabled; - positionText = "(" + (bookmark.LineNumber) + ") "; - - bookmark.DocumentChanged += BookmarkDocumentChanged; - bookmark.LineNumberChanged += BookmarkLineNumberChanged; - if (bookmark.Document != null) { - BookmarkDocumentChanged(null, null); - } else { - Text = positionText; - } - } - - public override void CheckedChanged() - { -// bookmark.IsEnabled = Checked; - } - - void BookmarkDocumentChanged(object sender, EventArgs e) - { - if (bookmark.Document != null) { -// line = bookmark.Document.GetLineSegment(Math.Min(bookmark.LineNumber, bookmark.Document.TotalNumberOfLines)); -// Text = positionText + bookmark.Document.GetText(line); - } - } - - void BookmarkLineNumberChanged(object sender, EventArgs e) - { - positionText = "(" + (bookmark.LineNumber) + ") "; - BookmarkDocumentChanged(sender, e); - } - - protected override int MeasureItemWidth(DrawTreeNodeEventArgs e) - { - Graphics g = e.Graphics; - int x = MeasureTextWidth(g, positionText, BoldMonospacedFont); -// if (line != null && !line.IsDeleted) { -// x += MeasureTextWidth(g, bookmark.Document.GetText(line).Replace("\t", " "), BoldMonospacedFont); -// } - return x; - } - - protected override void DrawForeground(DrawTreeNodeEventArgs e) - { - Graphics g = e.Graphics; - float x = e.Bounds.X; - DrawText(e, positionText, SystemBrushes.WindowText, RegularBigFont, ref x); - - spaceSize = g.MeasureString("-", RegularBigFont, new PointF(0, 0), StringFormat.GenericTypographic); - -// if (line != null && !line.IsDeleted) { -// DrawLine(g, line, e.Bounds.Y, x, e.State); -// } - } - - public override void ActivateItem() - { - FileService.JumpToFilePosition(bookmark.FileName, bookmark.LineNumber, 1); - } - - /* - float DrawDocumentWord(Graphics g, string word, PointF position, Font font, Color foreColor) - { - if (word == null || word.Length == 0) { - return 0f; - } - SizeF wordSize = g.MeasureString(word, font, 32768, sf); - - g.DrawString(word, - font, - BrushRegistry.GetBrush(foreColor), - position, - sf); - return wordSize.Width; - } - - void DrawLine(Graphics g, LineSegment line, float yPos, float xPos, TreeNodeStates state) - { - int logicalX = 0; - if (line.Words != null) { - foreach (TextWord word in line.Words) { - switch (word.Type) { - case TextWordType.Space: - xPos += spaceSize.Width; - logicalX++; - break; - case TextWordType.Tab: - xPos += spaceSize.Width * 4; - logicalX++; - break; - case TextWordType.Word: - xPos += DrawDocumentWord(g, - word.Word, - new PointF(xPos, yPos), - word.Bold ? BoldMonospacedFont : RegularMonospacedFont, - GetTextColor(state, word.Color) - ); - logicalX += word.Word.Length; - break; - } - } - } else { -// DrawDocumentWord(g, -// bookmark.Document.GetText(line), -// new PointF(xPos, yPos), -// RegularMonospacedFont, -// GetTextColor(state, Color.Black) -// ); - } - }*/ - } -} diff --git a/src/Main/Base/Project/Src/Bookmarks/SDBookmark.cs b/src/Main/Base/Project/Src/Bookmarks/SDBookmark.cs index 189d83d794..94a55a05b4 100644 --- a/src/Main/Base/Project/Src/Bookmarks/SDBookmark.cs +++ b/src/Main/Base/Project/Src/Bookmarks/SDBookmark.cs @@ -3,6 +3,7 @@ using System; using System.ComponentModel; +using System.IO; using ICSharpCode.Core; using ICSharpCode.NRefactory; @@ -33,6 +34,10 @@ namespace ICSharpCode.SharpDevelop.Bookmarks } } + public string FileNameAndLineNumber { + get { return string.Format(StringParser.Parse("${res:MainWindow.Windows.BookmarkPad.LineText}"), Path.GetFileName(this.FileName), this.LineNumber); } + } + public event EventHandler FileNameChanged; protected virtual void OnFileNameChanged(EventArgs e) diff --git a/src/Main/Base/Project/Src/Commands/DebugCommands.cs b/src/Main/Base/Project/Src/Commands/DebugCommands.cs index acca2c1cff..a17029e0bf 100644 --- a/src/Main/Base/Project/Src/Commands/DebugCommands.cs +++ b/src/Main/Base/Project/Src/Commands/DebugCommands.cs @@ -7,7 +7,6 @@ using System.Linq; using System.Windows.Forms; using ICSharpCode.Core; using ICSharpCode.SharpDevelop.Bookmarks; -using ICSharpCode.SharpDevelop.Bookmarks.Pad.Controls; using ICSharpCode.SharpDevelop.Debugging; using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Gui; @@ -139,31 +138,6 @@ namespace ICSharpCode.SharpDevelop.Project.Commands } } - public class RemoveAllBreakpointsCommand : AbstractMenuCommand - { - public override void Run() - { - BookmarkManager.RemoveAll(b => b is BreakpointBookmark); - } - } - - public class DeleteBreakpointCommand : AbstractMenuCommand - { - public override void Run() - { - if (Owner == null || !(Owner is BookmarkPadBase)) return; - - var bookmarkBase = (BookmarkPadBase)Owner; - var item = bookmarkBase.CurrentItem; - - if (item == null) return; - - if (item.Mark is BreakpointBookmark) { - BookmarkManager.RemoveMark(item.Mark); - } - } - } - public class AttachToProcessCommand : AbstractMenuCommand { public override void Run() diff --git a/src/Main/Base/Project/Src/Editor/ITooltip.cs b/src/Main/Base/Project/Src/Editor/ITooltip.cs index def96396f1..5e338ff1d5 100644 --- a/src/Main/Base/Project/Src/Editor/ITooltip.cs +++ b/src/Main/Base/Project/Src/Editor/ITooltip.cs @@ -6,30 +6,9 @@ using System.Windows; namespace ICSharpCode.SharpDevelop.Editor { - /// - /// Content of text editor tooltip (used as ), - /// specifying whether it should be displayed in a WPF Popup. - /// public interface ITooltip { - /// - /// If true, this ITooltip will be displayed in a WPF Popup. - /// Otherwise it will be displayed in a WPF Tooltip. - /// WPF Popups are (unlike WPF Tooltips) focusable. - /// - bool ShowAsPopup { get; } - - /// - /// Closes this tooltip. - /// - /// True if close request is raised - /// because of mouse click on some SharpDevelop GUI element. - /// True if Close succeeded (that is, can close). False otherwise. - bool Close(bool mouseClick); - - /// - /// Occurs when this tooltip decides to close. - /// - event RoutedEventHandler Closed; + /// Should the tooltip close when the mouse moves away? + bool CloseOnHoverEnd { get; } } } diff --git a/src/Main/Base/Project/Src/Project/Solution/Solution.cs b/src/Main/Base/Project/Src/Project/Solution/Solution.cs index 7fcac06c00..a71adc0474 100644 --- a/src/Main/Base/Project/Src/Project/Solution/Solution.cs +++ b/src/Main/Base/Project/Src/Project/Solution/Solution.cs @@ -404,7 +404,7 @@ namespace ICSharpCode.SharpDevelop.Project } else if (versionNumber == SolutionVersionVS11) { sw.WriteLine("# Visual Studio 11"); } - sw.WriteLine("# SharpDevelop " + RevisionClass.FullVersion); + sw.WriteLine("# SharpDevelop " + RevisionClass.Major + "." + RevisionClass.Minor); sw.Write(projectSection.ToString()); sw.Write(globalSection.ToString()); diff --git a/src/Main/Base/Project/Src/Services/Debugger/BreakpointBookmark.cs b/src/Main/Base/Project/Src/Services/Debugger/BreakpointBookmark.cs index 5adc72d02c..80ccd3807d 100644 --- a/src/Main/Base/Project/Src/Services/Debugger/BreakpointBookmark.cs +++ b/src/Main/Base/Project/Src/Services/Debugger/BreakpointBookmark.cs @@ -29,6 +29,8 @@ namespace ICSharpCode.SharpDevelop.Debugging string condition; string scriptLanguage; + public event EventHandler ConditionChanged; + public string ScriptLanguage { get { return scriptLanguage; } set { scriptLanguage = value; } @@ -36,7 +38,15 @@ namespace ICSharpCode.SharpDevelop.Debugging public string Condition { get { return condition; } - set { condition = value; } + set { + if (condition != value) { + condition = value; + this.Action = string.IsNullOrEmpty(condition) ? BreakpointAction.Break : BreakpointAction.Condition; + if (ConditionChanged != null) + ConditionChanged(this, EventArgs.Empty); + Redraw(); + } + } } public BreakpointAction Action { @@ -51,6 +61,8 @@ namespace ICSharpCode.SharpDevelop.Debugging } } + public object InternalBreakpointObject { get; set; } + public virtual bool IsHealthy { get { return isHealthy; diff --git a/src/Main/Base/Project/Src/Services/Debugger/CurrentLineBookmark.cs b/src/Main/Base/Project/Src/Services/Debugger/CurrentLineBookmark.cs index a3e53649da..fb83cacdf1 100644 --- a/src/Main/Base/Project/Src/Services/Debugger/CurrentLineBookmark.cs +++ b/src/Main/Base/Project/Src/Services/Debugger/CurrentLineBookmark.cs @@ -118,7 +118,7 @@ namespace ICSharpCode.SharpDevelop.Debugging // because Drag'N'Drop operation has finished WorkbenchSingleton.SafeThreadAsyncCall( delegate { - DebuggerService.CurrentDebugger.SetInstructionPointer(this.FileName, lineNumber, 1); + DebuggerService.CurrentDebugger.SetInstructionPointer(this.FileName, lineNumber, 1, false); }); } } diff --git a/src/Main/Base/Project/Src/Services/Debugger/DefaultDebugger.cs b/src/Main/Base/Project/Src/Services/Debugger/DefaultDebugger.cs index fddeb79656..da96bba580 100644 --- a/src/Main/Base/Project/Src/Services/Debugger/DefaultDebugger.cs +++ b/src/Main/Base/Project/Src/Services/Debugger/DefaultDebugger.cs @@ -125,12 +125,7 @@ namespace ICSharpCode.SharpDevelop.Debugging { } - public bool CanSetInstructionPointer(string filename, int line, int column) - { - return false; - } - - public bool SetInstructionPointer(string filename, int line, int column) + public bool SetInstructionPointer(string filename, int line, int column, bool dryRun) { return false; } diff --git a/src/Main/Base/Project/Src/Services/Debugger/IDebugger.cs b/src/Main/Base/Project/Src/Services/Debugger/IDebugger.cs index 2f50e683b7..7c2a5a3c16 100644 --- a/src/Main/Base/Project/Src/Services/Debugger/IDebugger.cs +++ b/src/Main/Base/Project/Src/Services/Debugger/IDebugger.cs @@ -78,17 +78,11 @@ namespace ICSharpCode.SharpDevelop.Debugging void Detach(); - /// - /// Queries the debugger whether it is possible to set the instruction pointer to a given position. - /// - /// True if possible. False otherwise - bool CanSetInstructionPointer(string filename, int line, int column); - /// /// Set the instruction pointer to a given position. /// /// True if successful. False otherwise - bool SetInstructionPointer(string filename, int line, int column); + bool SetInstructionPointer(string filename, int line, int column, bool dryRun); /// /// Ocurrs when the debugger is starting. diff --git a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/IPinDebuggerControl.cs b/src/Main/Base/Project/Src/Services/Debugger/Tooltips/IPinDebuggerControl.cs deleted file mode 100644 index 835aaa0e25..0000000000 --- a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/IPinDebuggerControl.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using System; -using System.Collections.Generic; -using System.Windows; - -using ICSharpCode.SharpDevelop.Bookmarks; - -namespace ICSharpCode.SharpDevelop.Debugging -{ - public interface IPinDebuggerControl - { - void Open(); - void Close(); - PinBookmark Mark { get; set; } - IEnumerable ItemsSource { set; } - Point Location { get; set; } - } -} diff --git a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/ITreeNode.cs b/src/Main/Base/Project/Src/Services/Debugger/Tooltips/ITreeNode.cs deleted file mode 100644 index 59762e5870..0000000000 --- a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/ITreeNode.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using System; -using System.Collections.Generic; -using System.Windows.Media; - -namespace ICSharpCode.SharpDevelop.Debugging -{ - /// - /// Node that can be bound to . - /// - public interface ITreeNode : IComparable - { - string Name { get; } - - string FullName { get; } - - string ImageName { get; } - - string Text { get; } - - bool CanSetText { get; } - - string Type { get; } - - ImageSource ImageSource { get; } - - IEnumerable ChildNodes { get; } - - bool HasChildNodes { get; } - - IEnumerable VisualizerCommands { get; } - - bool HasVisualizerCommands { get; } - - bool IsPinned { get; set; } - - bool SetText(string newValue); - } -} diff --git a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/PinBookmark.cs b/src/Main/Base/Project/Src/Services/Debugger/Tooltips/PinBookmark.cs deleted file mode 100644 index ac940c25eb..0000000000 --- a/src/Main/Base/Project/Src/Services/Debugger/Tooltips/PinBookmark.cs +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Windows; -using ICSharpCode.Core; -using ICSharpCode.NRefactory; -using ICSharpCode.SharpDevelop.Debugging; - -namespace ICSharpCode.SharpDevelop.Bookmarks -{ - public class PinBookmark : SDBookmark - { - string tooltip; - - public IPinDebuggerControl Popup { get; set; } - - public static readonly IImage PinImage = new ResourceServiceImage("Bookmarks.Pin"); - - public PinBookmark(FileName fileName, TextLocation location) : base(fileName, location) - { - Nodes = new ObservableCollection(); - IsVisibleInBookmarkPad = false; - } - - /// - /// Pin's position relative to the layer BUT ABSOLUTE TO THE SCREEN. - /// - public Nullable PinPosition { get; set; } - - /// - /// Nodes inside the pin control. - /// - public ObservableCollection Nodes { get; set; } - - /// - /// Image, Name, Text - /// - public List> SavedNodes { get; set; } - - public string Comment { get; set; } - - public override IImage Image { - get { - return PinImage; - } - } - - public string Tooltip { - get { return tooltip; } - set { tooltip = value; } - } - - public override bool CanDragDrop { - get { return true; } - } - - public override void Drop(int lineNumber) - { - this.Location = new TextLocation(lineNumber, ColumnNumber); - } - } - - public static class PinBookmarkExtensions - { - public static bool ContainsNode(this PinBookmark mark, ITreeNode node) - { - if (mark == null) - throw new ArgumentNullException("mark is null"); - if (node == null) - throw new ArgumentNullException("Node is null"); - - foreach (var currentNode in mark.Nodes) { - if (node.FullName == currentNode.FullName) - return true; - } - - return false; - } - - public static void RemoveNode(this PinBookmark mark, ITreeNode node) - { - if (mark == null) - throw new ArgumentNullException("mark is null"); - if (node == null) - throw new ArgumentNullException("Node is null"); - - foreach (var currentNode in mark.Nodes) { - if (node.FullName == currentNode.FullName) { - mark.Nodes.Remove(currentNode); - return; - } - } - } - } -}