diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000000..fbfb41be87
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,3 @@
+*.cs text diff=csharp
+*.sln text eol=crlf
+*.csproj text eol=crlf
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/ParallelStacksViewCommands.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/ParallelStacksViewCommands.cs
index c6b85ebf0c..3e037502bc 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/ParallelStacksViewCommands.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/ParallelStacksViewCommands.cs
@@ -1,82 +1,82 @@
-// 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 ICSharpCode.Core;
-
-namespace ICSharpCode.SharpDevelop.Gui.Pads
-{
- public sealed class ShowZoomControlCommand : AbstractCheckableMenuCommand
- {
- ParallelStackPad pad;
-
- public override object Owner {
- get { return base.Owner; }
- set {
- if (!(value is ParallelStackPad))
- throw new Exception("Owner has to be a ParallelStackPad");
- pad = value as ParallelStackPad;
- base.Owner = value;
- }
- }
-
- public override bool IsChecked {
- get { return pad.IsZoomControlVisible; }
- set { pad.IsZoomControlVisible = value; }
- }
- }
-
- public sealed class ToggleMethodViewCommand : AbstractCheckableMenuCommand
- {
- ParallelStackPad pad;
-
- public override object Owner {
- get { return base.Owner; }
- set {
- if (!(value is ParallelStackPad))
- throw new Exception("Owner has to be a AbstractConsolePad");
- pad = value as ParallelStackPad;
- base.Owner = value;
- }
- }
-
- public override bool IsChecked {
- get { return pad.IsMethodView; }
- set { pad.IsMethodView = value; }
- }
- }
-
- public sealed class ParallelStacksViewCommand : AbstractComboBoxCommand
- {
- ParallelStackPad pad;
- ComboBox box;
-
- protected override void OnOwnerChanged(EventArgs e)
- {
- this.pad = this.Owner as ParallelStackPad;
- if (this.pad == null)
- return;
-
- box = this.ComboBox as ComboBox;
-
- if (this.box == null)
- return;
-
- foreach (var name in Enum.GetNames(typeof(ParallelStacksView)))
- box.Items.Add(name);
-
- box.SelectedIndex = 0;
-
- base.OnOwnerChanged(e);
- }
-
- public override void Run()
- {
- if (this.pad != null && this.box != null) {
- pad.ParallelStacksView = (ParallelStacksView)Enum.Parse(typeof(ParallelStacksView), box.SelectedValue.ToString());
- }
- base.Run();
- }
- }
+// 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 ICSharpCode.Core;
+
+namespace ICSharpCode.SharpDevelop.Gui.Pads
+{
+ public sealed class ShowZoomControlCommand : AbstractCheckableMenuCommand
+ {
+ ParallelStackPad pad;
+
+ public override object Owner {
+ get { return base.Owner; }
+ set {
+ if (!(value is ParallelStackPad))
+ throw new Exception("Owner has to be a ParallelStackPad");
+ pad = value as ParallelStackPad;
+ base.Owner = value;
+ }
+ }
+
+ public override bool IsChecked {
+ get { return pad.IsZoomControlVisible; }
+ set { pad.IsZoomControlVisible = value; }
+ }
+ }
+
+ public sealed class ToggleMethodViewCommand : AbstractCheckableMenuCommand
+ {
+ ParallelStackPad pad;
+
+ public override object Owner {
+ get { return base.Owner; }
+ set {
+ if (!(value is ParallelStackPad))
+ throw new Exception("Owner has to be a AbstractConsolePad");
+ pad = value as ParallelStackPad;
+ base.Owner = value;
+ }
+ }
+
+ public override bool IsChecked {
+ get { return pad.IsMethodView; }
+ set { pad.IsMethodView = value; }
+ }
+ }
+
+ public sealed class ParallelStacksViewCommand : AbstractComboBoxCommand
+ {
+ ParallelStackPad pad;
+ ComboBox box;
+
+ protected override void OnOwnerChanged(EventArgs e)
+ {
+ this.pad = this.Owner as ParallelStackPad;
+ if (this.pad == null)
+ return;
+
+ box = this.ComboBox as ComboBox;
+
+ if (this.box == null)
+ return;
+
+ foreach (var name in Enum.GetNames(typeof(ParallelStacksView)))
+ box.Items.Add(name);
+
+ box.SelectedIndex = 0;
+
+ base.OnOwnerChanged(e);
+ }
+
+ public override void Run()
+ {
+ if (this.pad != null && this.box != null) {
+ pad.ParallelStacksView = (ParallelStacksView)Enum.Parse(typeof(ParallelStacksView), box.SelectedValue.ToString());
+ }
+ base.Run();
+ }
+ }
}
\ No newline at end of file
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/SelectLanguageCommand.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/SelectLanguageCommand.cs
index b117571b31..8cddba8ae9 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/SelectLanguageCommand.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/SelectLanguageCommand.cs
@@ -1,47 +1,47 @@
-// 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 Debugger;
-using Debugger.AddIn;
-using ICSharpCode.Core;
-using ICSharpCode.NRefactory;
-using ICSharpCode.SharpDevelop.Debugging;
-using ICSharpCode.SharpDevelop.Services;
-using System.Windows.Controls;
-
-namespace ICSharpCode.SharpDevelop.Gui.Pads
-{
- class SelectLanguageCommand : AbstractComboBoxCommand
- {
- ConsolePad pad;
- ComboBox box;
-
- protected override void OnOwnerChanged(EventArgs e)
- {
- this.pad = this.Owner as ConsolePad;
- if (this.pad == null)
- return;
-
- box = this.ComboBox as ComboBox;
-
- if (this.box == null)
- return;
-
- foreach (var name in Enum.GetNames(typeof(SupportedLanguage)))
- box.Items.Add(name);
-
- box.SelectedIndex = 0;
-
- base.OnOwnerChanged(e);
- }
-
- public override void Run()
- {
- if (this.pad != null && this.box != null) {
- pad.SelectedLanguage = (SupportedLanguage)Enum.Parse(typeof(SupportedLanguage), box.SelectedValue.ToString());
- }
- base.Run();
- }
- }
-}
+// 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 Debugger;
+using Debugger.AddIn;
+using ICSharpCode.Core;
+using ICSharpCode.NRefactory;
+using ICSharpCode.SharpDevelop.Debugging;
+using ICSharpCode.SharpDevelop.Services;
+using System.Windows.Controls;
+
+namespace ICSharpCode.SharpDevelop.Gui.Pads
+{
+ class SelectLanguageCommand : AbstractComboBoxCommand
+ {
+ ConsolePad pad;
+ ComboBox box;
+
+ protected override void OnOwnerChanged(EventArgs e)
+ {
+ this.pad = this.Owner as ConsolePad;
+ if (this.pad == null)
+ return;
+
+ box = this.ComboBox as ComboBox;
+
+ if (this.box == null)
+ return;
+
+ foreach (var name in Enum.GetNames(typeof(SupportedLanguage)))
+ box.Items.Add(name);
+
+ box.SelectedIndex = 0;
+
+ base.OnOwnerChanged(e);
+ }
+
+ public override void Run()
+ {
+ if (this.pad != null && this.box != null) {
+ pad.SelectedLanguage = (SupportedLanguage)Enum.Parse(typeof(SupportedLanguage), box.SelectedValue.ToString());
+ }
+ base.Run();
+ }
+ }
+}
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerPad.cs
index 9e712e5176..01afc5418c 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerPad.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerPad.cs
@@ -1,85 +1,85 @@
-// 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;
- }
- }
-}
+// 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/ObjectGraphPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs
index 1617201833..e220e6f336 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs
@@ -1,72 +1,72 @@
-// 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();
- }
- }
-}
+// 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/DrawSurface.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/DrawSurface.xaml.cs
index 22b9aa63fa..8b7600186a 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/DrawSurface.xaml.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/DrawSurface.xaml.cs
@@ -1,71 +1,71 @@
-// 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.Shapes;
-
-using Microsoft.Windows.Themes;
-
-namespace Debugger.AddIn.Pads.ParallelPad
-{
- public partial class DrawSurface : UserControl
- {
- private ScaleTransform zoom = new ScaleTransform();
-
- public DrawSurface()
- {
- InitializeComponent();
-
- ContentControl.LayoutTransform = zoom;
- }
-
- public void SetGraph(ParallelStacksGraph graph)
- {
- this.ParallelStacksLayout.Graph = graph;
-
- if (graph == null)
- this.ParallelStacksLayout.CancelLayout();
- else
- this.ParallelStacksLayout.Relayout();
- }
-
- public bool IsZoomControlVisible {
- get { return ZoomControl.Visibility == Visibility.Visible; }
- set {
- if (value)
- ZoomControl.Visibility = Visibility.Visible;
- else
- ZoomControl.Visibility = Visibility.Hidden;
- }
- }
-
- #region Zoom
-
- void SliderControl_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
- {
- if (e.OldValue == 0)
- return;
-
- double value = (e.NewValue / 5d) * 100;
-
- this.PercentText.Text = string.Format("{0}%", value);
-
- // zoom canvas
- zoom.ScaleX = e.NewValue / 5d;
- zoom.ScaleY = e.NewValue / 5d;
- zoom.CenterX = drawingSurface.ActualWidth / 2d;
- zoom.CenterY = drawingSurface.ActualHeight / 2d;
- }
-
- void Reset_Click(object sender, RoutedEventArgs e)
- {
- this.SliderControl.Value = 5;
- }
-
- #endregion
- }
+// 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.Shapes;
+
+using Microsoft.Windows.Themes;
+
+namespace Debugger.AddIn.Pads.ParallelPad
+{
+ public partial class DrawSurface : UserControl
+ {
+ private ScaleTransform zoom = new ScaleTransform();
+
+ public DrawSurface()
+ {
+ InitializeComponent();
+
+ ContentControl.LayoutTransform = zoom;
+ }
+
+ public void SetGraph(ParallelStacksGraph graph)
+ {
+ this.ParallelStacksLayout.Graph = graph;
+
+ if (graph == null)
+ this.ParallelStacksLayout.CancelLayout();
+ else
+ this.ParallelStacksLayout.Relayout();
+ }
+
+ public bool IsZoomControlVisible {
+ get { return ZoomControl.Visibility == Visibility.Visible; }
+ set {
+ if (value)
+ ZoomControl.Visibility = Visibility.Visible;
+ else
+ ZoomControl.Visibility = Visibility.Hidden;
+ }
+ }
+
+ #region Zoom
+
+ void SliderControl_ValueChanged(object sender, RoutedPropertyChangedEventArgs e)
+ {
+ if (e.OldValue == 0)
+ return;
+
+ double value = (e.NewValue / 5d) * 100;
+
+ this.PercentText.Text = string.Format("{0}%", value);
+
+ // zoom canvas
+ zoom.ScaleX = e.NewValue / 5d;
+ zoom.ScaleY = e.NewValue / 5d;
+ zoom.CenterX = drawingSurface.ActualWidth / 2d;
+ zoom.CenterY = drawingSurface.ActualHeight / 2d;
+ }
+
+ void Reset_Click(object sender, RoutedEventArgs e)
+ {
+ this.SliderControl.Value = 5;
+ }
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs
index 8feecd7c33..6b5c0915ac 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs
@@ -1,674 +1,674 @@
-// 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.Text;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Media;
-using System.Windows.Threading;
-using Debugger;
-using Debugger.AddIn.Pads.ParallelPad;
-using Debugger.AddIn.TreeModel;
-using ICSharpCode.AvalonEdit.Rendering;
-using ICSharpCode.Core;
-using ICSharpCode.Core.Presentation;
-using ICSharpCode.NRefactory;
-using ICSharpCode.SharpDevelop.Bookmarks;
-using ICSharpCode.SharpDevelop.Debugging;
-using ICSharpCode.SharpDevelop.Editor;
-using ICSharpCode.SharpDevelop.Gui.Pads;
-
-namespace ICSharpCode.SharpDevelop.Gui.Pads
-{
- public enum ParallelStacksView
- {
- Threads,
- Tasks
- }
-
- public class ParallelStackPad : DebuggerPad
- {
- DrawSurface surface;
- Process debuggedProcess;
- ParallelStacksGraph graph;
- List currentThreadStacks = new List();
- ParallelStacksView parallelStacksView;
- StackFrame selectedFrame;
- bool isMethodView;
-
- #region Overrides
-
- protected override void InitializeComponents()
- {
- 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;
- }
-
- DebuggerService.DebugStarted += OnReset;
- DebuggerService.DebugStopped += OnReset;
-
- InvalidatePad();
- }
-
- protected override void RefreshPad()
- {
- if (debuggedProcess == null || debuggedProcess.IsRunning) {
- return;
- }
-
- LoggingService.InfoFormatted("Start refresh: {0}" + Environment.NewLine, parallelStacksView);
-
- currentThreadStacks.Clear();
-
- using(new PrintTimes("Create stacks")) {
- try {
- // create all simple ThreadStacks
- foreach (Thread thread in debuggedProcess.Threads) {
- var t = thread;
- debuggedProcess.EnqueueWork(Dispatcher.CurrentDispatcher, () => CreateThreadStack(t));
- }
- }
- catch(AbortedBecauseDebuggeeResumedException) { }
- catch(System.Exception) {
- if (debuggedProcess == null || debuggedProcess.HasExited) {
- // Process unexpectedly exited
- } else {
- throw;
- }
- }
- }
- using(new PrintTimes("Run algorithm")) {
- if (isMethodView)
- {
- // build method view for threads
- CreateMethodViewStacks();
- }
- else
- {
- // normal view
- CreateCommonStacks();
- }
- }
-
- using(new PrintTimes("Graph refresh")) {
- // paint the ThreadStaks
- graph = new ParallelStacksGraph();
- foreach (var stack in this.currentThreadStacks.FindAll(ts => ts.ThreadStackParents == null ))
- {
- graph.AddVertex(stack);
-
- // add the children
- AddChildren(stack);
- }
-
- if (graph.VertexCount > 0)
- surface.SetGraph(graph);
- }
- }
-
- protected override ToolBar BuildToolBar()
- {
- return ToolBarService.CreateToolBar(panel, this, "/SharpDevelop/Pads/ParallelStacksPad/ToolBar");
- }
-
- #endregion
-
- #region Public Properties
-
- public ParallelStacksView ParallelStacksView {
- get { return parallelStacksView; }
- set {
- parallelStacksView = value;
- InvalidatePad();
- }
- }
-
- public bool IsMethodView {
- get { return isMethodView; }
- set {
- isMethodView = value;
- InvalidatePad();
- }
- }
-
- public bool IsZoomControlVisible {
- get { return surface.IsZoomControlVisible; }
- set { surface.IsZoomControlVisible = value; }
- }
-
- #endregion
-
- #region Private Methods
-
- void OnReset(object sender, EventArgs e)
- {
- currentThreadStacks.Clear();
- selectedFrame = null;
-
- // remove all
- 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)
- return;
-
- foreach (var ts in parent.ThreadStackChildren)
- {
- if (ts == null) continue;
-
- graph.AddVertex(ts);
- graph.AddEdge(new ParallelStacksEdge(parent, ts));
-
- if (ts.ThreadStackChildren == null || ts.ThreadStackChildren.Count == 0)
- continue;
-
- AddChildren(ts);
- }
- }
-
- void CreateCommonStacks()
- {
- // stack.ItemCollection order
- // 0 -> top of stack = S.C
- // 1 -> ............ = S.B
- // .......................
- // n -> bottom of stack = [External Methods]
-
- // ThreadStacks with common frame
- var commonFrameThreads = new Dictionary>();
-
- bool isOver = false;
- while (true) {
-
- for (int i = currentThreadStacks.Count - 1; i >=0; --i) {
- var stack = currentThreadStacks[i];
- if (stack.ItemCollection.Count == 0) {
- currentThreadStacks.Remove(stack);
- continue;
- }
- }
- //get all thread stacks with common start frame
- foreach (var stack in currentThreadStacks) {
- int count = stack.ItemCollection.Count;
- ParallelStackFrameModel frame = stack.ItemCollection[count - 1];
- string fullname = frame.MethodName + stack.Level.ToString();
-
- if (!commonFrameThreads.ContainsKey(fullname))
- commonFrameThreads.Add(fullname, new List());
-
- if (!commonFrameThreads[fullname].Contains(stack))
- commonFrameThreads[fullname].Add(stack);
- }
-
- // for every list of common stacks, find split place and add them to currentThreadStacks
- foreach (var frameName in commonFrameThreads.Keys) {
- var listOfCurrentStacks = commonFrameThreads[frameName];
-
- if (listOfCurrentStacks.Count == 1) // just skip the parents
- {
- isOver = true; // we finish when all are pseodo-parents: no more spliting
- continue;
- }
-
- isOver = false;
-
- // find the frameIndex where we can split
- int frameIndex = 0;
- string fn = string.Empty;
- bool canContinue = true;
-
- while(canContinue) {
- for (int i = 0; i < listOfCurrentStacks.Count; ++i) {
- var stack = listOfCurrentStacks[i];
- if (stack.ItemCollection.Count == frameIndex)
- {
- canContinue = false;
- break;
- }
-
- ParallelStackFrameModel item = stack.ItemCollection[stack.ItemCollection.Count - frameIndex - 1];
-
- string currentName = item.MethodName;
-
- if (i == 0) {
- fn = currentName;
- continue;
- }
-
- if (fn == currentName)
- continue;
- else {
- canContinue = false;
- break;
- }
- }
- if (canContinue)
- frameIndex++;
- }
-
- // remove last [frameIndex] and create a new ThreadStack as the parent of what remained in the children
- var threadIds = new List();
- var parentItems = new Stack();
-
- while (frameIndex > 0) {
- for (int i = 0 ; i < listOfCurrentStacks.Count; ++i) {
- var stack = listOfCurrentStacks[i];
- int indexToRemove = stack.ItemCollection.Count - 1;
-
- #if DEBUG
- ParallelStackFrameModel d_item = stack.ItemCollection[indexToRemove];
- string name = d_item.MethodName;
- #endif
- if (i == 0)
- parentItems.Push(stack.ItemCollection[indexToRemove]);
-
- stack.ItemCollection.RemoveAt(indexToRemove);
- }
-
- frameIndex--;
- }
-
- // update thread ids
- for (int i = 0 ; i < listOfCurrentStacks.Count; ++i)
- threadIds.AddRange(listOfCurrentStacks[i].ThreadIds);
-
- // remove stacks with no items
- for (int i = listOfCurrentStacks.Count - 1; i >= 0; --i) {
- var stack = listOfCurrentStacks[i];
- if (stack.ItemCollection.Count == 0)
- listOfCurrentStacks.Remove(stack);
- }
-
- // increase the Level
- for (int i = 0 ; i < listOfCurrentStacks.Count; ++i)
- listOfCurrentStacks[i].Level++;
-
- // create new parent stack
- ThreadStack commonParent = new ThreadStack();
- commonParent.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, threadIds.ToArray());
- commonParent.ItemCollection = parentItems.ToObservable();
- commonParent.Process = debuggedProcess;
- commonParent.StackSelected += OnThreadStackSelected;
- commonParent.FrameSelected += OnFrameSelected;
- commonParent.IsSelected = commonParent.ThreadIds.Contains(debuggedProcess.SelectedThread.ID);
- // add new children
- foreach (var stack in listOfCurrentStacks) {
- if (stack.ItemCollection.Count == 0)
- {
- currentThreadStacks.Remove(stack);
- continue;
- }
- ParallelStackFrameModel item = stack.ItemCollection[stack.ItemCollection.Count - 1];
- // add the parent to the parent
- if (stack.ThreadStackParents != null) {
- // remove stack from it's parent because it will have the commonParent as parent
- stack.ThreadStackParents[0].ThreadStackChildren.Remove(stack);
- commonParent.ThreadStackParents = stack.ThreadStackParents.Clone();
- commonParent.ThreadStackParents[0].ThreadStackChildren.Add(commonParent);
- // set level
- commonParent.Level = stack.Level - 1;
- }
- else
- stack.ThreadStackParents = new List();
-
- // update thread ids
- if (commonParent.ThreadStackParents != null) {
- commonParent.ThreadStackParents[0].UpdateThreadIds(
- parallelStacksView == ParallelStacksView.Tasks,
- commonParent.ThreadIds.ToArray());
- }
-
- stack.ThreadStackParents.Clear();
- stack.ThreadStackParents.Add(commonParent);
- string currentName = item.MethodName + stack.Level.ToString();;
-
- // add name or add to list
- if (!commonFrameThreads.ContainsKey(currentName)) {
- var newList = new List();
- newList.Add(stack);
- commonFrameThreads.Add(currentName, newList);
- }
- else {
- var list = commonFrameThreads[currentName];
- list.Add(stack);
- }
- }
-
- commonParent.ThreadStackChildren = listOfCurrentStacks.Clone();
- commonFrameThreads[frameName].Clear();
- commonFrameThreads[frameName].Add(commonParent);
- currentThreadStacks.Add(commonParent);
-
- // exit and retry
- break;
- }
-
- if (isOver || currentThreadStacks.Count == 0)
- break;
- }
- }
-
- void CreateMethodViewStacks()
- {
- var list = new List, ObservableCollection, List>>();
-
- // find all threadstacks that contains the selected frame
- for (int i = currentThreadStacks.Count - 1; i >= 0; --i) {
- var tuple = currentThreadStacks[i].ItemCollection.SplitStack(selectedFrame, currentThreadStacks[i].ThreadIds);
- if (tuple != null)
- list.Add(tuple);
- }
-
- currentThreadStacks.Clear();
-
- // common
- ThreadStack common = new ThreadStack();
- var observ = new ObservableCollection();
- bool dummy = false;
- ParallelStackFrameModel obj = CreateItemForFrame(selectedFrame, ref dummy);
- obj.Image = PresentationResourceService.GetImage("Icons.48x48.CurrentFrame").Source;
- observ.Add(obj);
- common.ItemCollection = observ;
- common.StackSelected += OnThreadStackSelected;
- common.FrameSelected += OnFrameSelected;
- common.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, selectedFrame.Thread.ID);
- common.Process = debuggedProcess;
- common.ThreadStackChildren = new List();
- common.ThreadStackParents = new List();
-
- // for all thread stacks, split them in 2 :
- // one that invokes the method frame, second that get's invoked by current method frame
- foreach (var tuple in list) {
- // add top
- if (tuple.Item1.Count > 0)
- {
- ThreadStack topStack = new ThreadStack();
- topStack.ItemCollection = tuple.Item1;
- topStack.StackSelected += OnThreadStackSelected;
- topStack.FrameSelected += OnFrameSelected;
- topStack.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, tuple.Item3.ToArray());
- topStack.Process = debuggedProcess;
- topStack.ThreadStackParents = new List();
- topStack.ThreadStackParents.Add(common);
-
- currentThreadStacks.Add(topStack);
- common.ThreadStackChildren.Add(topStack);
- }
-
- // add bottom
- if(tuple.Item2.Count > 0)
- {
- ThreadStack bottomStack = new ThreadStack();
- bottomStack.ItemCollection = tuple.Item2;
- bottomStack.StackSelected += OnThreadStackSelected;
- bottomStack.FrameSelected += OnFrameSelected;
- bottomStack.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, tuple.Item3.ToArray());
- bottomStack.Process = debuggedProcess;
- bottomStack.ThreadStackChildren = new List();
- bottomStack.ThreadStackChildren.Add(common);
- common.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, tuple.Item3.ToArray());
- common.ThreadStackParents.Add(bottomStack);
- currentThreadStacks.Add(bottomStack);
- }
- }
-
- currentThreadStacks.Add(common);
- common.IsSelected = true;
- }
-
- void CreateThreadStack(Thread thread)
- {
- var items = CreateItems(thread);
- if (items == null || items.Count == 0)
- return;
-
- ThreadStack threadStack = new ThreadStack();
- threadStack.StackSelected += OnThreadStackSelected;
- threadStack.FrameSelected += OnFrameSelected;
- threadStack.Process = debuggedProcess;
- threadStack.ItemCollection = items;
- threadStack.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, thread.ID);
-
- if (debuggedProcess.SelectedThread != null) {
- threadStack.IsSelected = threadStack.ThreadIds.Contains(debuggedProcess.SelectedThread.ID);
- if (selectedFrame == null)
- selectedFrame = debuggedProcess.SelectedStackFrame;
- }
-
- currentThreadStacks.Add(threadStack);
- }
-
- ObservableCollection CreateItems(Thread thread)
- {
- bool lastItemIsExternalMethod = false;
- int noTasks = 0;
- var result = new ObservableCollection();
- var callstack = thread.GetCallstack(100);
-
- if (parallelStacksView == ParallelStacksView.Threads) {
- foreach (StackFrame frame in callstack) {
- ParallelStackFrameModel obj = CreateItemForFrame(frame, ref lastItemIsExternalMethod);
-
- if (obj != null)
- result.Add(obj);
- }
- } else {
- for (int i = 0 ; i < callstack.Length; ++i) {
- StackFrame frame = callstack[i];
- ParallelStackFrameModel obj = CreateItemForFrame(frame, ref lastItemIsExternalMethod);
-
- if (frame.MethodInfo.FullName.IndexOf("System.Threading.Tasks.Task.ExecuteEntry") != -1) {
- noTasks++;
- }
-
- if (noTasks == 1) {
- if (frame.HasSymbols) {
- // create thread stack for the items collected until now
- ThreadStack threadStack = new ThreadStack();
- threadStack.StackSelected += OnThreadStackSelected;
- threadStack.FrameSelected += OnFrameSelected;
- threadStack.Process = debuggedProcess;
- threadStack.ItemCollection = result.Clone();
- threadStack.UpdateThreadIds(true, frame.Thread.ID);
-
- if (debuggedProcess.SelectedThread != null) {
- threadStack.IsSelected = threadStack.ThreadIds.Contains(debuggedProcess.SelectedThread.ID);
- if (selectedFrame == null)
- selectedFrame = debuggedProcess.SelectedStackFrame;
- }
-
- currentThreadStacks.Add(threadStack);
- // reset
- result.Clear();
- noTasks = 0;
- }
- }
-
- if (obj != null)
- result.Add(obj);
- }
-
- // return null if we are dealing with a simple thread
- return noTasks == 0 ? null : result;
- }
-
- return result;
- }
-
- ParallelStackFrameModel CreateItemForFrame(StackFrame frame, ref bool lastItemIsExternalMethod)
- {
- ParallelStackFrameModel model = new ParallelStackFrameModel();
- string fullName;
- if (frame.HasSymbols) {
- // Show the method in the list
- fullName = frame.GetMethodName();
- lastItemIsExternalMethod = false;
- model.FontWeight = FontWeights.Normal;
- model.Foreground = Brushes.Black;
- } else {
- // Show [External methods] in the list
- if (lastItemIsExternalMethod) return null;
- fullName = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ExternalMethods").Trim();
- model.FontWeight = FontWeights.Normal;
- model.Foreground = Brushes.Gray;
- 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()) {
- model.Image = PresentationResourceService.GetImage("Bookmarks.CurrentLine").Source;
- model.IsRunningStackFrame = true;
- } else {
- if (selectedFrame != null && frame.Thread.ID == selectedFrame.Thread.ID &&
- frame.GetMethodName() == selectedFrame.GetMethodName())
- model.Image = PresentationResourceService.GetImage("Icons.48x48.CurrentFrame").Source;
- else
- model.Image = null;
- model.IsRunningStackFrame = false;
- }
-
- model.MethodName = fullName;
-
- return model;
- }
-
- void ToggleSelectedFrameBookmark(Location location)
- {
- // remove all
- BookmarkManager.RemoveAll(b => b is SelectedFrameBookmark);
-
- ITextEditorProvider provider = WorkbenchSingleton.Workbench.ActiveContent as ITextEditorProvider;
- if (provider != null) {
- ITextEditor editor = provider.TextEditor;
- BookmarkManager.AddMark(new SelectedFrameBookmark(editor.FileName, location));
- }
- }
-
- void OnThreadStackSelected(object sender, EventArgs e)
- {
- foreach (var ts in this.currentThreadStacks) {
- if (ts.IsSelected)
- ts.IsSelected = false;
- ts.ClearImages();
- }
- }
-
- void OnFrameSelected(object sender, FrameSelectedEventArgs e)
- {
- selectedFrame = e.Item;
-
- ToggleSelectedFrameBookmark(e.Location);
-
- if (isMethodView)
- InvalidatePad();
- }
-
- #endregion
- }
-
- static class StackFrameExtensions
- {
- internal static string GetMethodName(this StackFrame frame)
- {
- if (frame == null)
- return null;
-
- StringBuilder name = new StringBuilder();
- name.Append(frame.MethodInfo.DeclaringType.FullName);
- name.Append('.');
- name.Append(frame.MethodInfo.Name);
-
- return name.ToString();
- }
- }
-
- static class ParallelStackExtensions
- {
- internal static List Clone(this List listToClone)
- {
- if (listToClone == null)
- return null;
-
- var result = new List();
- foreach (var item in listToClone)
- result.Add(item);
-
- return result;
- }
-
- internal static ObservableCollection Clone(this ObservableCollection collectionToClone)
- {
- if (collectionToClone == null)
- return null;
-
- var result = new ObservableCollection();
- foreach (var item in collectionToClone)
- result.Add(item);
-
- return result;
- }
-
- internal static ObservableCollection ToObservable(this Stack stack)
- {
- if (stack == null)
- throw new NullReferenceException("Stack is null!");
-
- var result = new ObservableCollection();
- while (stack.Count > 0)
- result.Add(stack.Pop());
-
- return result;
- }
-
- internal static Tuple, ObservableCollection, List>
- SplitStack(this ObservableCollection source, StackFrame frame, List threadIds)
- {
- var bottom = new ObservableCollection();
- var top = new ObservableCollection();
-
- int found = 0;
-
- foreach (dynamic item in source) {
- if (item.MethodName == frame.GetMethodName())
- found = 1;
-
- if (found >= 1) {
- if(found > 1)
- bottom.Add(item);
-
- found++;
- }
- else
- top.Add(item);
- }
-
- var result =
- new Tuple, ObservableCollection, List>(top, bottom, threadIds);
-
- return found > 1 ? result : null;
- }
- }
-}
+// 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.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+using System.Windows.Threading;
+using Debugger;
+using Debugger.AddIn.Pads.ParallelPad;
+using Debugger.AddIn.TreeModel;
+using ICSharpCode.AvalonEdit.Rendering;
+using ICSharpCode.Core;
+using ICSharpCode.Core.Presentation;
+using ICSharpCode.NRefactory;
+using ICSharpCode.SharpDevelop.Bookmarks;
+using ICSharpCode.SharpDevelop.Debugging;
+using ICSharpCode.SharpDevelop.Editor;
+using ICSharpCode.SharpDevelop.Gui.Pads;
+
+namespace ICSharpCode.SharpDevelop.Gui.Pads
+{
+ public enum ParallelStacksView
+ {
+ Threads,
+ Tasks
+ }
+
+ public class ParallelStackPad : DebuggerPad
+ {
+ DrawSurface surface;
+ Process debuggedProcess;
+ ParallelStacksGraph graph;
+ List currentThreadStacks = new List();
+ ParallelStacksView parallelStacksView;
+ StackFrame selectedFrame;
+ bool isMethodView;
+
+ #region Overrides
+
+ protected override void InitializeComponents()
+ {
+ 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;
+ }
+
+ DebuggerService.DebugStarted += OnReset;
+ DebuggerService.DebugStopped += OnReset;
+
+ InvalidatePad();
+ }
+
+ protected override void RefreshPad()
+ {
+ if (debuggedProcess == null || debuggedProcess.IsRunning) {
+ return;
+ }
+
+ LoggingService.InfoFormatted("Start refresh: {0}" + Environment.NewLine, parallelStacksView);
+
+ currentThreadStacks.Clear();
+
+ using(new PrintTimes("Create stacks")) {
+ try {
+ // create all simple ThreadStacks
+ foreach (Thread thread in debuggedProcess.Threads) {
+ var t = thread;
+ debuggedProcess.EnqueueWork(Dispatcher.CurrentDispatcher, () => CreateThreadStack(t));
+ }
+ }
+ catch(AbortedBecauseDebuggeeResumedException) { }
+ catch(System.Exception) {
+ if (debuggedProcess == null || debuggedProcess.HasExited) {
+ // Process unexpectedly exited
+ } else {
+ throw;
+ }
+ }
+ }
+ using(new PrintTimes("Run algorithm")) {
+ if (isMethodView)
+ {
+ // build method view for threads
+ CreateMethodViewStacks();
+ }
+ else
+ {
+ // normal view
+ CreateCommonStacks();
+ }
+ }
+
+ using(new PrintTimes("Graph refresh")) {
+ // paint the ThreadStaks
+ graph = new ParallelStacksGraph();
+ foreach (var stack in this.currentThreadStacks.FindAll(ts => ts.ThreadStackParents == null ))
+ {
+ graph.AddVertex(stack);
+
+ // add the children
+ AddChildren(stack);
+ }
+
+ if (graph.VertexCount > 0)
+ surface.SetGraph(graph);
+ }
+ }
+
+ protected override ToolBar BuildToolBar()
+ {
+ return ToolBarService.CreateToolBar(panel, this, "/SharpDevelop/Pads/ParallelStacksPad/ToolBar");
+ }
+
+ #endregion
+
+ #region Public Properties
+
+ public ParallelStacksView ParallelStacksView {
+ get { return parallelStacksView; }
+ set {
+ parallelStacksView = value;
+ InvalidatePad();
+ }
+ }
+
+ public bool IsMethodView {
+ get { return isMethodView; }
+ set {
+ isMethodView = value;
+ InvalidatePad();
+ }
+ }
+
+ public bool IsZoomControlVisible {
+ get { return surface.IsZoomControlVisible; }
+ set { surface.IsZoomControlVisible = value; }
+ }
+
+ #endregion
+
+ #region Private Methods
+
+ void OnReset(object sender, EventArgs e)
+ {
+ currentThreadStacks.Clear();
+ selectedFrame = null;
+
+ // remove all
+ 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)
+ return;
+
+ foreach (var ts in parent.ThreadStackChildren)
+ {
+ if (ts == null) continue;
+
+ graph.AddVertex(ts);
+ graph.AddEdge(new ParallelStacksEdge(parent, ts));
+
+ if (ts.ThreadStackChildren == null || ts.ThreadStackChildren.Count == 0)
+ continue;
+
+ AddChildren(ts);
+ }
+ }
+
+ void CreateCommonStacks()
+ {
+ // stack.ItemCollection order
+ // 0 -> top of stack = S.C
+ // 1 -> ............ = S.B
+ // .......................
+ // n -> bottom of stack = [External Methods]
+
+ // ThreadStacks with common frame
+ var commonFrameThreads = new Dictionary>();
+
+ bool isOver = false;
+ while (true) {
+
+ for (int i = currentThreadStacks.Count - 1; i >=0; --i) {
+ var stack = currentThreadStacks[i];
+ if (stack.ItemCollection.Count == 0) {
+ currentThreadStacks.Remove(stack);
+ continue;
+ }
+ }
+ //get all thread stacks with common start frame
+ foreach (var stack in currentThreadStacks) {
+ int count = stack.ItemCollection.Count;
+ ParallelStackFrameModel frame = stack.ItemCollection[count - 1];
+ string fullname = frame.MethodName + stack.Level.ToString();
+
+ if (!commonFrameThreads.ContainsKey(fullname))
+ commonFrameThreads.Add(fullname, new List());
+
+ if (!commonFrameThreads[fullname].Contains(stack))
+ commonFrameThreads[fullname].Add(stack);
+ }
+
+ // for every list of common stacks, find split place and add them to currentThreadStacks
+ foreach (var frameName in commonFrameThreads.Keys) {
+ var listOfCurrentStacks = commonFrameThreads[frameName];
+
+ if (listOfCurrentStacks.Count == 1) // just skip the parents
+ {
+ isOver = true; // we finish when all are pseodo-parents: no more spliting
+ continue;
+ }
+
+ isOver = false;
+
+ // find the frameIndex where we can split
+ int frameIndex = 0;
+ string fn = string.Empty;
+ bool canContinue = true;
+
+ while(canContinue) {
+ for (int i = 0; i < listOfCurrentStacks.Count; ++i) {
+ var stack = listOfCurrentStacks[i];
+ if (stack.ItemCollection.Count == frameIndex)
+ {
+ canContinue = false;
+ break;
+ }
+
+ ParallelStackFrameModel item = stack.ItemCollection[stack.ItemCollection.Count - frameIndex - 1];
+
+ string currentName = item.MethodName;
+
+ if (i == 0) {
+ fn = currentName;
+ continue;
+ }
+
+ if (fn == currentName)
+ continue;
+ else {
+ canContinue = false;
+ break;
+ }
+ }
+ if (canContinue)
+ frameIndex++;
+ }
+
+ // remove last [frameIndex] and create a new ThreadStack as the parent of what remained in the children
+ var threadIds = new List();
+ var parentItems = new Stack();
+
+ while (frameIndex > 0) {
+ for (int i = 0 ; i < listOfCurrentStacks.Count; ++i) {
+ var stack = listOfCurrentStacks[i];
+ int indexToRemove = stack.ItemCollection.Count - 1;
+
+ #if DEBUG
+ ParallelStackFrameModel d_item = stack.ItemCollection[indexToRemove];
+ string name = d_item.MethodName;
+ #endif
+ if (i == 0)
+ parentItems.Push(stack.ItemCollection[indexToRemove]);
+
+ stack.ItemCollection.RemoveAt(indexToRemove);
+ }
+
+ frameIndex--;
+ }
+
+ // update thread ids
+ for (int i = 0 ; i < listOfCurrentStacks.Count; ++i)
+ threadIds.AddRange(listOfCurrentStacks[i].ThreadIds);
+
+ // remove stacks with no items
+ for (int i = listOfCurrentStacks.Count - 1; i >= 0; --i) {
+ var stack = listOfCurrentStacks[i];
+ if (stack.ItemCollection.Count == 0)
+ listOfCurrentStacks.Remove(stack);
+ }
+
+ // increase the Level
+ for (int i = 0 ; i < listOfCurrentStacks.Count; ++i)
+ listOfCurrentStacks[i].Level++;
+
+ // create new parent stack
+ ThreadStack commonParent = new ThreadStack();
+ commonParent.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, threadIds.ToArray());
+ commonParent.ItemCollection = parentItems.ToObservable();
+ commonParent.Process = debuggedProcess;
+ commonParent.StackSelected += OnThreadStackSelected;
+ commonParent.FrameSelected += OnFrameSelected;
+ commonParent.IsSelected = commonParent.ThreadIds.Contains(debuggedProcess.SelectedThread.ID);
+ // add new children
+ foreach (var stack in listOfCurrentStacks) {
+ if (stack.ItemCollection.Count == 0)
+ {
+ currentThreadStacks.Remove(stack);
+ continue;
+ }
+ ParallelStackFrameModel item = stack.ItemCollection[stack.ItemCollection.Count - 1];
+ // add the parent to the parent
+ if (stack.ThreadStackParents != null) {
+ // remove stack from it's parent because it will have the commonParent as parent
+ stack.ThreadStackParents[0].ThreadStackChildren.Remove(stack);
+ commonParent.ThreadStackParents = stack.ThreadStackParents.Clone();
+ commonParent.ThreadStackParents[0].ThreadStackChildren.Add(commonParent);
+ // set level
+ commonParent.Level = stack.Level - 1;
+ }
+ else
+ stack.ThreadStackParents = new List();
+
+ // update thread ids
+ if (commonParent.ThreadStackParents != null) {
+ commonParent.ThreadStackParents[0].UpdateThreadIds(
+ parallelStacksView == ParallelStacksView.Tasks,
+ commonParent.ThreadIds.ToArray());
+ }
+
+ stack.ThreadStackParents.Clear();
+ stack.ThreadStackParents.Add(commonParent);
+ string currentName = item.MethodName + stack.Level.ToString();;
+
+ // add name or add to list
+ if (!commonFrameThreads.ContainsKey(currentName)) {
+ var newList = new List();
+ newList.Add(stack);
+ commonFrameThreads.Add(currentName, newList);
+ }
+ else {
+ var list = commonFrameThreads[currentName];
+ list.Add(stack);
+ }
+ }
+
+ commonParent.ThreadStackChildren = listOfCurrentStacks.Clone();
+ commonFrameThreads[frameName].Clear();
+ commonFrameThreads[frameName].Add(commonParent);
+ currentThreadStacks.Add(commonParent);
+
+ // exit and retry
+ break;
+ }
+
+ if (isOver || currentThreadStacks.Count == 0)
+ break;
+ }
+ }
+
+ void CreateMethodViewStacks()
+ {
+ var list = new List, ObservableCollection, List>>();
+
+ // find all threadstacks that contains the selected frame
+ for (int i = currentThreadStacks.Count - 1; i >= 0; --i) {
+ var tuple = currentThreadStacks[i].ItemCollection.SplitStack(selectedFrame, currentThreadStacks[i].ThreadIds);
+ if (tuple != null)
+ list.Add(tuple);
+ }
+
+ currentThreadStacks.Clear();
+
+ // common
+ ThreadStack common = new ThreadStack();
+ var observ = new ObservableCollection();
+ bool dummy = false;
+ ParallelStackFrameModel obj = CreateItemForFrame(selectedFrame, ref dummy);
+ obj.Image = PresentationResourceService.GetImage("Icons.48x48.CurrentFrame").Source;
+ observ.Add(obj);
+ common.ItemCollection = observ;
+ common.StackSelected += OnThreadStackSelected;
+ common.FrameSelected += OnFrameSelected;
+ common.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, selectedFrame.Thread.ID);
+ common.Process = debuggedProcess;
+ common.ThreadStackChildren = new List();
+ common.ThreadStackParents = new List();
+
+ // for all thread stacks, split them in 2 :
+ // one that invokes the method frame, second that get's invoked by current method frame
+ foreach (var tuple in list) {
+ // add top
+ if (tuple.Item1.Count > 0)
+ {
+ ThreadStack topStack = new ThreadStack();
+ topStack.ItemCollection = tuple.Item1;
+ topStack.StackSelected += OnThreadStackSelected;
+ topStack.FrameSelected += OnFrameSelected;
+ topStack.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, tuple.Item3.ToArray());
+ topStack.Process = debuggedProcess;
+ topStack.ThreadStackParents = new List();
+ topStack.ThreadStackParents.Add(common);
+
+ currentThreadStacks.Add(topStack);
+ common.ThreadStackChildren.Add(topStack);
+ }
+
+ // add bottom
+ if(tuple.Item2.Count > 0)
+ {
+ ThreadStack bottomStack = new ThreadStack();
+ bottomStack.ItemCollection = tuple.Item2;
+ bottomStack.StackSelected += OnThreadStackSelected;
+ bottomStack.FrameSelected += OnFrameSelected;
+ bottomStack.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, tuple.Item3.ToArray());
+ bottomStack.Process = debuggedProcess;
+ bottomStack.ThreadStackChildren = new List();
+ bottomStack.ThreadStackChildren.Add(common);
+ common.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, tuple.Item3.ToArray());
+ common.ThreadStackParents.Add(bottomStack);
+ currentThreadStacks.Add(bottomStack);
+ }
+ }
+
+ currentThreadStacks.Add(common);
+ common.IsSelected = true;
+ }
+
+ void CreateThreadStack(Thread thread)
+ {
+ var items = CreateItems(thread);
+ if (items == null || items.Count == 0)
+ return;
+
+ ThreadStack threadStack = new ThreadStack();
+ threadStack.StackSelected += OnThreadStackSelected;
+ threadStack.FrameSelected += OnFrameSelected;
+ threadStack.Process = debuggedProcess;
+ threadStack.ItemCollection = items;
+ threadStack.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, thread.ID);
+
+ if (debuggedProcess.SelectedThread != null) {
+ threadStack.IsSelected = threadStack.ThreadIds.Contains(debuggedProcess.SelectedThread.ID);
+ if (selectedFrame == null)
+ selectedFrame = debuggedProcess.SelectedStackFrame;
+ }
+
+ currentThreadStacks.Add(threadStack);
+ }
+
+ ObservableCollection CreateItems(Thread thread)
+ {
+ bool lastItemIsExternalMethod = false;
+ int noTasks = 0;
+ var result = new ObservableCollection();
+ var callstack = thread.GetCallstack(100);
+
+ if (parallelStacksView == ParallelStacksView.Threads) {
+ foreach (StackFrame frame in callstack) {
+ ParallelStackFrameModel obj = CreateItemForFrame(frame, ref lastItemIsExternalMethod);
+
+ if (obj != null)
+ result.Add(obj);
+ }
+ } else {
+ for (int i = 0 ; i < callstack.Length; ++i) {
+ StackFrame frame = callstack[i];
+ ParallelStackFrameModel obj = CreateItemForFrame(frame, ref lastItemIsExternalMethod);
+
+ if (frame.MethodInfo.FullName.IndexOf("System.Threading.Tasks.Task.ExecuteEntry") != -1) {
+ noTasks++;
+ }
+
+ if (noTasks == 1) {
+ if (frame.HasSymbols) {
+ // create thread stack for the items collected until now
+ ThreadStack threadStack = new ThreadStack();
+ threadStack.StackSelected += OnThreadStackSelected;
+ threadStack.FrameSelected += OnFrameSelected;
+ threadStack.Process = debuggedProcess;
+ threadStack.ItemCollection = result.Clone();
+ threadStack.UpdateThreadIds(true, frame.Thread.ID);
+
+ if (debuggedProcess.SelectedThread != null) {
+ threadStack.IsSelected = threadStack.ThreadIds.Contains(debuggedProcess.SelectedThread.ID);
+ if (selectedFrame == null)
+ selectedFrame = debuggedProcess.SelectedStackFrame;
+ }
+
+ currentThreadStacks.Add(threadStack);
+ // reset
+ result.Clear();
+ noTasks = 0;
+ }
+ }
+
+ if (obj != null)
+ result.Add(obj);
+ }
+
+ // return null if we are dealing with a simple thread
+ return noTasks == 0 ? null : result;
+ }
+
+ return result;
+ }
+
+ ParallelStackFrameModel CreateItemForFrame(StackFrame frame, ref bool lastItemIsExternalMethod)
+ {
+ ParallelStackFrameModel model = new ParallelStackFrameModel();
+ string fullName;
+ if (frame.HasSymbols) {
+ // Show the method in the list
+ fullName = frame.GetMethodName();
+ lastItemIsExternalMethod = false;
+ model.FontWeight = FontWeights.Normal;
+ model.Foreground = Brushes.Black;
+ } else {
+ // Show [External methods] in the list
+ if (lastItemIsExternalMethod) return null;
+ fullName = ResourceService.GetString("MainWindow.Windows.Debug.CallStack.ExternalMethods").Trim();
+ model.FontWeight = FontWeights.Normal;
+ model.Foreground = Brushes.Gray;
+ 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()) {
+ model.Image = PresentationResourceService.GetImage("Bookmarks.CurrentLine").Source;
+ model.IsRunningStackFrame = true;
+ } else {
+ if (selectedFrame != null && frame.Thread.ID == selectedFrame.Thread.ID &&
+ frame.GetMethodName() == selectedFrame.GetMethodName())
+ model.Image = PresentationResourceService.GetImage("Icons.48x48.CurrentFrame").Source;
+ else
+ model.Image = null;
+ model.IsRunningStackFrame = false;
+ }
+
+ model.MethodName = fullName;
+
+ return model;
+ }
+
+ void ToggleSelectedFrameBookmark(Location location)
+ {
+ // remove all
+ BookmarkManager.RemoveAll(b => b is SelectedFrameBookmark);
+
+ ITextEditorProvider provider = WorkbenchSingleton.Workbench.ActiveContent as ITextEditorProvider;
+ if (provider != null) {
+ ITextEditor editor = provider.TextEditor;
+ BookmarkManager.AddMark(new SelectedFrameBookmark(editor.FileName, location));
+ }
+ }
+
+ void OnThreadStackSelected(object sender, EventArgs e)
+ {
+ foreach (var ts in this.currentThreadStacks) {
+ if (ts.IsSelected)
+ ts.IsSelected = false;
+ ts.ClearImages();
+ }
+ }
+
+ void OnFrameSelected(object sender, FrameSelectedEventArgs e)
+ {
+ selectedFrame = e.Item;
+
+ ToggleSelectedFrameBookmark(e.Location);
+
+ if (isMethodView)
+ InvalidatePad();
+ }
+
+ #endregion
+ }
+
+ static class StackFrameExtensions
+ {
+ internal static string GetMethodName(this StackFrame frame)
+ {
+ if (frame == null)
+ return null;
+
+ StringBuilder name = new StringBuilder();
+ name.Append(frame.MethodInfo.DeclaringType.FullName);
+ name.Append('.');
+ name.Append(frame.MethodInfo.Name);
+
+ return name.ToString();
+ }
+ }
+
+ static class ParallelStackExtensions
+ {
+ internal static List Clone(this List listToClone)
+ {
+ if (listToClone == null)
+ return null;
+
+ var result = new List();
+ foreach (var item in listToClone)
+ result.Add(item);
+
+ return result;
+ }
+
+ internal static ObservableCollection Clone(this ObservableCollection collectionToClone)
+ {
+ if (collectionToClone == null)
+ return null;
+
+ var result = new ObservableCollection();
+ foreach (var item in collectionToClone)
+ result.Add(item);
+
+ return result;
+ }
+
+ internal static ObservableCollection ToObservable(this Stack stack)
+ {
+ if (stack == null)
+ throw new NullReferenceException("Stack is null!");
+
+ var result = new ObservableCollection();
+ while (stack.Count > 0)
+ result.Add(stack.Pop());
+
+ return result;
+ }
+
+ internal static Tuple, ObservableCollection, List>
+ SplitStack(this ObservableCollection source, StackFrame frame, List threadIds)
+ {
+ var bottom = new ObservableCollection();
+ var top = new ObservableCollection();
+
+ int found = 0;
+
+ foreach (dynamic item in source) {
+ if (item.MethodName == frame.GetMethodName())
+ found = 1;
+
+ if (found >= 1) {
+ if(found > 1)
+ bottom.Add(item);
+
+ found++;
+ }
+ else
+ top.Add(item);
+ }
+
+ var result =
+ new Tuple, ObservableCollection, List>(top, bottom, threadIds);
+
+ return found > 1 ? result : null;
+ }
+ }
+}
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..7f271cc0d5 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs
@@ -1,331 +1,331 @@
-// 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.Dynamic;
-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;
-
-namespace Debugger.AddIn.Pads.ParallelPad
-{
- public class FrameSelectedEventArgs : EventArgs
- {
- public StackFrame Item {
- get;
- private set;
- }
-
- public Location Location {
- get;
- private set;
- }
-
- public FrameSelectedEventArgs(StackFrame item, Location location)
- {
- Item = item;
- Location = location;
- }
- }
-
- public partial class ThreadStack : UserControl
- {
- public static SolidColorBrush SelectedBrush = new SolidColorBrush(Color.FromRgb(84, 169, 255));
-
- public static readonly DependencyProperty IsSelectedProperty =
- DependencyProperty.Register("IsSelected", typeof(bool), typeof(ThreadStack),
- new FrameworkPropertyMetadata());
-
- public event EventHandler StackSelected;
-
- public event EventHandler FrameSelected;
-
- ObservableCollection itemCollection = new ObservableCollection();
-
- ToolTip toolTip = new ToolTip();
- List threadIds = new List();
-
- public ThreadStack()
- {
- InitializeComponent();
- datagrid.ToolTip = toolTip;
- datagrid.ToolTipOpening += OnToolTipOpening;
- datagrid.PreviewMouseMove += new MouseEventHandler(datagrid_PreviewMouseMove);
- datagrid.MouseLeave += delegate { toolTip.IsOpen = false; };
- }
-
- #region Public Properties
-
- public Process Process { get; set; }
-
- public int Level { get; set; }
-
- public bool IsSelected {
- get { return (bool)GetValue(IsSelectedProperty); }
- set {
- if (value) {
- BorderParent.BorderBrush = SelectedBrush;
- BorderParent.BorderThickness = new Thickness(5);
- }
- else {
- BorderParent.BorderBrush = Brushes.Black;
- BorderParent.BorderThickness = new Thickness(3);
- }
-
- SetValue(IsSelectedProperty, value);
-
- SelectParent(value);
- }
- }
-
- public List ThreadStackParents { get; set; }
-
- public List ThreadStackChildren { get; set; }
-
- public List ThreadIds {
- get { return threadIds; }
- }
-
- public ObservableCollection ItemCollection {
- get { return itemCollection; }
- set {
- itemCollection = value;
- this.datagrid.ItemsSource = itemCollection;
- }
- }
-
- #endregion
-
- #region Public Methods
-
- public void UpdateThreadIds(bool isTask, params uint[] threadIds)
- {
- var list = new List();
- foreach (uint id in threadIds) {
- if (!this.threadIds.Contains(id)) {
- list.Add(id);
- }
- }
- this.threadIds.AddRange(list);
-
- if (this.threadIds.Count > 1) {
- string suffix = isTask ? " Tasks" : " Threads";
- this.HeaderText.Text = this.threadIds.Count.ToString() + suffix;
- }
- else {
- this.HeaderText.Text = isTask ? "1 Task" : "1 Thread";
- }
- }
-
- public void ClearImages()
- {
- foreach (ParallelStackFrameModel item in itemCollection) {
- if (!item.IsRunningStackFrame)
- item.Image = null;
- }
- }
-
- #endregion
-
- #region Private Methods
-
- private void SelectParent(bool isSelected)
- {
- if (this.ThreadStackParents == null || this.ThreadStackParents.Count == 0)
- return;
-
- foreach (var ts in this.ThreadStackParents)
- if (ts != null)
- ts.IsSelected = isSelected;
- }
-
- void datagrid_PreviewMouseMove(object sender, MouseEventArgs e)
- {
- var result = VisualTreeHelper.HitTest(this, e.GetPosition(this));
- if (result != null)
- {
- var row = TryFindParent(result.VisualHit);
- if (row != null)
- {
- datagrid.SelectedItem = row.DataContext;
- e.Handled = true;
- }
- }
- }
-
- private void Datagrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
- {
- if (Process.IsRunning) return;
-
- ParallelStackFrameModel selectedItem = datagrid.SelectedItem as ParallelStackFrameModel;
- if (selectedItem != null) {
- if (ThreadIds.Count > 1) {
- datagrid.ContextMenu = CreateContextMenu(selectedItem);
- datagrid.ContextMenu.IsOpen = true;
- }
- else
- {
- SelectFrame(ThreadIds[0], selectedItem);
- }
- }
- }
-
- private void SelectFrame(uint threadId, ParallelStackFrameModel selectedItem)
- {
- if (selectedItem == null)
- return;
-
- var thread = Process.Threads.Find(t => t.ID == threadId);
- if (thread == null)
- return;
-
- if (StackSelected != null)
- StackSelected(this, EventArgs.Empty);
-
- this.IsSelected = true;
-
- foreach(var frame in thread.Callstack)
- {
- if (frame.GetMethodName() == selectedItem.MethodName)
- {
- if (!selectedItem.IsRunningStackFrame)
- selectedItem.Image = PresentationResourceService.GetImage("Icons.48x48.CurrentFrame").Source;
-
- SourcecodeSegment nextStatement = frame.NextStatement;
- if (nextStatement != null) {
- var location = new Location(nextStatement.StartColumn, nextStatement.StartLine);
- FileService.JumpToFilePosition(
- nextStatement.Filename, location.Line, location.Column);
-
- if (FrameSelected != null)
- FrameSelected(this, new FrameSelectedEventArgs(frame, location));
- }
-
- break;
- }
- }
- }
-
- private void Datagrid_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
- {
- if (Process.IsRunning) return;
-
- ParallelStackFrameModel selectedItem = datagrid.SelectedItem as ParallelStackFrameModel;
- if (selectedItem == null)
- return;
-
- datagrid.ContextMenu = CreateContextMenu(selectedItem);
- datagrid.ContextMenu.IsOpen = true;
- }
-
- ContextMenu CreateContextMenu(ParallelStackFrameModel item)
- {
- var menu = new ContextMenu();
-
- foreach (var id in ThreadIds) {
- MenuItem m = new MenuItem();
- m.IsCheckable = true;
- m.IsChecked = id == Process.SelectedThread.ID;
- m.Click += delegate(object sender, RoutedEventArgs e) {
- var menuItem = e.OriginalSource as MenuItem;
- SelectFrame((uint)menuItem.Tag, item);
- };
- m.Tag = id;
- m.Header = id.ToString() + ":" + item.MethodName;
-
- menu.Items.Add(m);
- }
-
- return menu;
- }
-
- private void OnToolTipOpening(object sender, ToolTipEventArgs e)
- {
- if (Process.IsRunning)
- return;
-
- StackPanel panel = new StackPanel();
-
- ParallelStackFrameModel selectedItem = datagrid.SelectedItem as ParallelStackFrameModel;
- if (selectedItem == null) {
- panel.Children.Add(new TextBlock { Text = "No item selected" });
- this.toolTip.Content = panel;
- return;
- }
-
- foreach(var thread in Process.Threads)
- {
- if (ThreadIds.Contains(thread.ID))
- {
- foreach (var frame in thread.Callstack)
- {
- if (selectedItem.MethodName == frame.GetMethodName())
- {
- TextBlock tb = new TextBlock();
- tb.Text = thread.ID + ": " + CallStackPadContent.GetFullName(frame);
- panel.Children.Add(tb);
- }
- }
- }
- }
-
- this.toolTip.Content = panel;
- }
-
- #endregion
-
- #region Static Methods
-
- private static T TryFindParent(DependencyObject child) where T : DependencyObject
- {
- if (child is T) return child as T;
-
- DependencyObject parentObject = GetParentObject(child);
- if (parentObject == null) return null;
-
- var parent = parentObject as T;
- if (parent != null && parent is T)
- {
- return parent;
- }
- else
- {
- return TryFindParent(parentObject);
- }
- }
-
- private static DependencyObject GetParentObject(DependencyObject child)
- {
- if (child == null) return null;
-
- ContentElement contentElement = child as ContentElement;
- if (contentElement != null)
- {
- DependencyObject parent = ContentOperations.GetParent(contentElement);
- if (parent != null) return parent;
-
- FrameworkContentElement fce = contentElement as FrameworkContentElement;
- return fce != null ? fce.Parent : null;
- }
-
- FrameworkElement frameworkElement = child as FrameworkElement;
- if (frameworkElement != null)
- {
- DependencyObject parent = frameworkElement.Parent;
- if (parent != null) return parent;
- }
-
- return VisualTreeHelper.GetParent(child);
- }
-
- #endregion
- }
+// 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.Dynamic;
+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;
+
+namespace Debugger.AddIn.Pads.ParallelPad
+{
+ public class FrameSelectedEventArgs : EventArgs
+ {
+ public StackFrame Item {
+ get;
+ private set;
+ }
+
+ public Location Location {
+ get;
+ private set;
+ }
+
+ public FrameSelectedEventArgs(StackFrame item, Location location)
+ {
+ Item = item;
+ Location = location;
+ }
+ }
+
+ public partial class ThreadStack : UserControl
+ {
+ public static SolidColorBrush SelectedBrush = new SolidColorBrush(Color.FromRgb(84, 169, 255));
+
+ public static readonly DependencyProperty IsSelectedProperty =
+ DependencyProperty.Register("IsSelected", typeof(bool), typeof(ThreadStack),
+ new FrameworkPropertyMetadata());
+
+ public event EventHandler StackSelected;
+
+ public event EventHandler FrameSelected;
+
+ ObservableCollection itemCollection = new ObservableCollection();
+
+ ToolTip toolTip = new ToolTip();
+ List threadIds = new List();
+
+ public ThreadStack()
+ {
+ InitializeComponent();
+ datagrid.ToolTip = toolTip;
+ datagrid.ToolTipOpening += OnToolTipOpening;
+ datagrid.PreviewMouseMove += new MouseEventHandler(datagrid_PreviewMouseMove);
+ datagrid.MouseLeave += delegate { toolTip.IsOpen = false; };
+ }
+
+ #region Public Properties
+
+ public Process Process { get; set; }
+
+ public int Level { get; set; }
+
+ public bool IsSelected {
+ get { return (bool)GetValue(IsSelectedProperty); }
+ set {
+ if (value) {
+ BorderParent.BorderBrush = SelectedBrush;
+ BorderParent.BorderThickness = new Thickness(5);
+ }
+ else {
+ BorderParent.BorderBrush = Brushes.Black;
+ BorderParent.BorderThickness = new Thickness(3);
+ }
+
+ SetValue(IsSelectedProperty, value);
+
+ SelectParent(value);
+ }
+ }
+
+ public List ThreadStackParents { get; set; }
+
+ public List ThreadStackChildren { get; set; }
+
+ public List ThreadIds {
+ get { return threadIds; }
+ }
+
+ public ObservableCollection ItemCollection {
+ get { return itemCollection; }
+ set {
+ itemCollection = value;
+ this.datagrid.ItemsSource = itemCollection;
+ }
+ }
+
+ #endregion
+
+ #region Public Methods
+
+ public void UpdateThreadIds(bool isTask, params uint[] threadIds)
+ {
+ var list = new List();
+ foreach (uint id in threadIds) {
+ if (!this.threadIds.Contains(id)) {
+ list.Add(id);
+ }
+ }
+ this.threadIds.AddRange(list);
+
+ if (this.threadIds.Count > 1) {
+ string suffix = isTask ? " Tasks" : " Threads";
+ this.HeaderText.Text = this.threadIds.Count.ToString() + suffix;
+ }
+ else {
+ this.HeaderText.Text = isTask ? "1 Task" : "1 Thread";
+ }
+ }
+
+ public void ClearImages()
+ {
+ foreach (ParallelStackFrameModel item in itemCollection) {
+ if (!item.IsRunningStackFrame)
+ item.Image = null;
+ }
+ }
+
+ #endregion
+
+ #region Private Methods
+
+ private void SelectParent(bool isSelected)
+ {
+ if (this.ThreadStackParents == null || this.ThreadStackParents.Count == 0)
+ return;
+
+ foreach (var ts in this.ThreadStackParents)
+ if (ts != null)
+ ts.IsSelected = isSelected;
+ }
+
+ void datagrid_PreviewMouseMove(object sender, MouseEventArgs e)
+ {
+ var result = VisualTreeHelper.HitTest(this, e.GetPosition(this));
+ if (result != null)
+ {
+ var row = TryFindParent(result.VisualHit);
+ if (row != null)
+ {
+ datagrid.SelectedItem = row.DataContext;
+ e.Handled = true;
+ }
+ }
+ }
+
+ private void Datagrid_MouseDoubleClick(object sender, MouseButtonEventArgs e)
+ {
+ if (Process.IsRunning) return;
+
+ ParallelStackFrameModel selectedItem = datagrid.SelectedItem as ParallelStackFrameModel;
+ if (selectedItem != null) {
+ if (ThreadIds.Count > 1) {
+ datagrid.ContextMenu = CreateContextMenu(selectedItem);
+ datagrid.ContextMenu.IsOpen = true;
+ }
+ else
+ {
+ SelectFrame(ThreadIds[0], selectedItem);
+ }
+ }
+ }
+
+ private void SelectFrame(uint threadId, ParallelStackFrameModel selectedItem)
+ {
+ if (selectedItem == null)
+ return;
+
+ var thread = Process.Threads.Find(t => t.ID == threadId);
+ if (thread == null)
+ return;
+
+ if (StackSelected != null)
+ StackSelected(this, EventArgs.Empty);
+
+ this.IsSelected = true;
+
+ foreach(var frame in thread.Callstack)
+ {
+ if (frame.GetMethodName() == selectedItem.MethodName)
+ {
+ if (!selectedItem.IsRunningStackFrame)
+ selectedItem.Image = PresentationResourceService.GetImage("Icons.48x48.CurrentFrame").Source;
+
+ SourcecodeSegment nextStatement = frame.NextStatement;
+ if (nextStatement != null) {
+ var location = new Location(nextStatement.StartColumn, nextStatement.StartLine);
+ FileService.JumpToFilePosition(
+ nextStatement.Filename, location.Line, location.Column);
+
+ if (FrameSelected != null)
+ FrameSelected(this, new FrameSelectedEventArgs(frame, location));
+ }
+
+ break;
+ }
+ }
+ }
+
+ private void Datagrid_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
+ {
+ if (Process.IsRunning) return;
+
+ ParallelStackFrameModel selectedItem = datagrid.SelectedItem as ParallelStackFrameModel;
+ if (selectedItem == null)
+ return;
+
+ datagrid.ContextMenu = CreateContextMenu(selectedItem);
+ datagrid.ContextMenu.IsOpen = true;
+ }
+
+ ContextMenu CreateContextMenu(ParallelStackFrameModel item)
+ {
+ var menu = new ContextMenu();
+
+ foreach (var id in ThreadIds) {
+ MenuItem m = new MenuItem();
+ m.IsCheckable = true;
+ m.IsChecked = id == Process.SelectedThread.ID;
+ m.Click += delegate(object sender, RoutedEventArgs e) {
+ var menuItem = e.OriginalSource as MenuItem;
+ SelectFrame((uint)menuItem.Tag, item);
+ };
+ m.Tag = id;
+ m.Header = id.ToString() + ":" + item.MethodName;
+
+ menu.Items.Add(m);
+ }
+
+ return menu;
+ }
+
+ private void OnToolTipOpening(object sender, ToolTipEventArgs e)
+ {
+ if (Process.IsRunning)
+ return;
+
+ StackPanel panel = new StackPanel();
+
+ ParallelStackFrameModel selectedItem = datagrid.SelectedItem as ParallelStackFrameModel;
+ if (selectedItem == null) {
+ panel.Children.Add(new TextBlock { Text = "No item selected" });
+ this.toolTip.Content = panel;
+ return;
+ }
+
+ foreach(var thread in Process.Threads)
+ {
+ if (ThreadIds.Contains(thread.ID))
+ {
+ foreach (var frame in thread.Callstack)
+ {
+ if (selectedItem.MethodName == frame.GetMethodName())
+ {
+ TextBlock tb = new TextBlock();
+ tb.Text = thread.ID + ": " + CallStackPadContent.GetFullName(frame);
+ panel.Children.Add(tb);
+ }
+ }
+ }
+ }
+
+ this.toolTip.Content = panel;
+ }
+
+ #endregion
+
+ #region Static Methods
+
+ private static T TryFindParent(DependencyObject child) where T : DependencyObject
+ {
+ if (child is T) return child as T;
+
+ DependencyObject parentObject = GetParentObject(child);
+ if (parentObject == null) return null;
+
+ var parent = parentObject as T;
+ if (parent != null && parent is T)
+ {
+ return parent;
+ }
+ else
+ {
+ return TryFindParent(parentObject);
+ }
+ }
+
+ private static DependencyObject GetParentObject(DependencyObject child)
+ {
+ if (child == null) return null;
+
+ ContentElement contentElement = child as ContentElement;
+ if (contentElement != null)
+ {
+ DependencyObject parent = ContentOperations.GetParent(contentElement);
+ if (parent != null) return parent;
+
+ FrameworkContentElement fce = contentElement as FrameworkContentElement;
+ return fce != null ? fce.Parent : null;
+ }
+
+ FrameworkElement frameworkElement = child as FrameworkElement;
+ if (frameworkElement != null)
+ {
+ DependencyObject parent = frameworkElement.Parent;
+ if (parent != null) return parent;
+ }
+
+ return VisualTreeHelper.GetParent(child);
+ }
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs b/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs
index e498cfc91d..c575fb84cf 100644
--- a/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs
+++ b/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs
@@ -1,995 +1,995 @@
-// 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.Diagnostics;
-using System.Drawing;
-using System.IO;
-using System.Linq;
-using System.Runtime.InteropServices;
-using System.Security.Cryptography;
-using System.Text;
-using System.Windows.Forms;
-
-using Debugger;
-using Debugger.AddIn.Tooltips;
-using Debugger.AddIn.TreeModel;
-using Debugger.Interop.CorPublish;
-using Debugger.MetaData;
-using ICSharpCode.Core;
-using ICSharpCode.Core.WinForms;
-using ICSharpCode.NRefactory;
-using ICSharpCode.NRefactory.Ast;
-using ICSharpCode.NRefactory.Visitors;
-using ICSharpCode.SharpDevelop.Bookmarks;
-using ICSharpCode.SharpDevelop.Debugging;
-using ICSharpCode.SharpDevelop.Gui;
-using ICSharpCode.SharpDevelop.Gui.OptionPanels;
-using ICSharpCode.SharpDevelop.Project;
-using Mono.Cecil;
-using Process = Debugger.Process;
-
-namespace ICSharpCode.SharpDevelop.Services
-{
- public class WindowsDebugger : IDebugger
- {
- enum StopAttachedProcessDialogResult {
- Detach = 0,
- Terminate = 1,
- Cancel = 2
- }
-
- bool useRemotingForThreadInterop = false;
- bool attached;
-
- NDebugger debugger;
-
- ICorPublish corPublish;
-
- Process debuggedProcess;
-
- internal IDebuggerDecompilerService debuggerDecompilerService;
-
- //DynamicTreeDebuggerRow currentTooltipRow;
- //Expression currentTooltipExpression;
-
- public event EventHandler ProcessSelected;
-
- public NDebugger DebuggerCore {
- get {
- return debugger;
- }
- }
-
- public Process DebuggedProcess {
- get {
- return debuggedProcess;
- }
- }
-
- public static Process CurrentProcess {
- get {
- WindowsDebugger dbgr = DebuggerService.CurrentDebugger as WindowsDebugger;
- if (dbgr != null && dbgr.DebuggedProcess != null) {
- return dbgr.DebuggedProcess;
- } else {
- return null;
- }
- }
- }
-
- ///
- public bool BreakAtBeginning {
- get;
- set;
- }
-
- protected virtual void OnProcessSelected(ProcessEventArgs e)
- {
- if (ProcessSelected != null) {
- ProcessSelected(this, e);
- }
- }
-
- public bool ServiceInitialized {
- get {
- return debugger != null;
- }
- }
-
- public WindowsDebugger()
- {
-
- }
-
- #region IDebugger Members
-
- string errorDebugging = "${res:XML.MainMenu.DebugMenu.Error.Debugging}";
- string errorNotDebugging = "${res:XML.MainMenu.DebugMenu.Error.NotDebugging}";
- string errorProcessRunning = "${res:XML.MainMenu.DebugMenu.Error.ProcessRunning}";
- string errorProcessPaused = "${res:XML.MainMenu.DebugMenu.Error.ProcessPaused}";
- string errorCannotStepNoActiveFunction = "${res:MainWindow.Windows.Debug.Threads.CannotStepNoActiveFunction}";
-
- public bool IsDebugging {
- get {
- return ServiceInitialized && debuggedProcess != null;
- }
- }
-
- public bool IsAttached {
- get {
- return ServiceInitialized && attached;
- }
- }
-
- public bool IsProcessRunning {
- get {
- return IsDebugging && debuggedProcess.IsRunning;
- }
- }
-
- public bool CanDebug(IProject project)
- {
- return true;
- }
-
- public void Start(ProcessStartInfo processStartInfo)
- {
- if (IsDebugging) {
- MessageService.ShowMessage(errorDebugging);
- return;
- }
- if (!ServiceInitialized) {
- InitializeService();
- }
-
- string version = debugger.GetProgramVersion(processStartInfo.FileName);
-
- if (version.StartsWith("v1.0")) {
- MessageService.ShowMessage("${res:XML.MainMenu.DebugMenu.Error.Net10NotSupported}");
- } else if (version.StartsWith("v1.1")) {
- MessageService.ShowMessage(StringParser.Parse("${res:XML.MainMenu.DebugMenu.Error.Net10NotSupported}").Replace("1.0", "1.1"));
-// } else if (string.IsNullOrEmpty(version)) {
-// // Not a managed assembly
-// MessageService.ShowMessage("${res:XML.MainMenu.DebugMenu.Error.BadAssembly}");
- } else if (debugger.IsKernelDebuggerEnabled) {
- MessageService.ShowMessage("${res:XML.MainMenu.DebugMenu.Error.KernelDebuggerEnabled}");
- } else {
- attached = false;
- if (DebugStarting != null)
- DebugStarting(this, EventArgs.Empty);
-
- try {
- // set the JIT flag for evaluating optimized code
- Process.DebugMode = DebugModeFlag.Debug;
- Process process = debugger.Start(processStartInfo.FileName,
- processStartInfo.WorkingDirectory,
- processStartInfo.Arguments);
- SelectProcess(process);
- } catch (System.Exception e) {
- // COMException: The request is not supported. (Exception from HRESULT: 0x80070032)
- // COMException: The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log for more detail. (Exception from HRESULT: 0x800736B1)
- // COMException: The requested operation requires elevation. (Exception from HRESULT: 0x800702E4)
- // COMException: The directory name is invalid. (Exception from HRESULT: 0x8007010B)
- // BadImageFormatException: is not a valid Win32 application. (Exception from HRESULT: 0x800700C1)
- // UnauthorizedAccessException: Отказано в доступе. (Исключение из HRESULT: 0x80070005 (E_ACCESSDENIED))
- if (e is COMException || e is BadImageFormatException || e is UnauthorizedAccessException) {
- string msg = StringParser.Parse("${res:XML.MainMenu.DebugMenu.Error.CannotStartProcess}");
- msg += " " + e.Message;
- // TODO: Remove
- if (e is COMException && ((uint)((COMException)e).ErrorCode == 0x80070032)) {
- msg += Environment.NewLine + Environment.NewLine;
- msg += "64-bit debugging is not supported. Please set Project -> Project Options... -> Compiling -> Target CPU to 32bit.";
- }
- MessageService.ShowMessage(msg);
-
- if (DebugStopped != null)
- DebugStopped(this, EventArgs.Empty);
- } else {
- throw;
- }
- }
- }
- }
-
- public void ShowAttachDialog()
- {
- using (AttachToProcessForm attachForm = new AttachToProcessForm()) {
- if (attachForm.ShowDialog(WorkbenchSingleton.MainWin32Window) == DialogResult.OK) {
- Attach(attachForm.Process);
- }
- }
- }
-
- public void Attach(System.Diagnostics.Process existingProcess)
- {
- if (existingProcess == null)
- return;
-
- if (IsDebugging) {
- MessageService.ShowMessage(errorDebugging);
- return;
- }
- if (!ServiceInitialized) {
- InitializeService();
- }
-
- string version = debugger.GetProgramVersion(existingProcess.MainModule.FileName);
- if (version.StartsWith("v1.0")) {
- MessageService.ShowMessage("${res:XML.MainMenu.DebugMenu.Error.Net10NotSupported}");
- } else {
- if (DebugStarting != null)
- DebugStarting(this, EventArgs.Empty);
-
- try {
- // set the JIT flag for evaluating optimized code
- Process.DebugMode = DebugModeFlag.Debug;
- Process process = debugger.Attach(existingProcess);
- attached = true;
- SelectProcess(process);
-
- process.Modules.Added += process_Modules_Added;
- } catch (System.Exception e) {
- // CORDBG_E_DEBUGGER_ALREADY_ATTACHED
- if (e is COMException || e is UnauthorizedAccessException) {
- string msg = StringParser.Parse("${res:XML.MainMenu.DebugMenu.Error.CannotAttachToProcess}");
- MessageService.ShowMessage(msg + " " + e.Message);
-
- if (DebugStopped != null)
- DebugStopped(this, EventArgs.Empty);
- } else {
- throw;
- }
- }
- }
- }
-
- public void Detach()
- {
- debugger.Detach();
- }
-
- public void StartWithoutDebugging(ProcessStartInfo processStartInfo)
- {
- System.Diagnostics.Process.Start(processStartInfo);
- }
-
- public void Stop()
- {
- if (!IsDebugging) {
- MessageService.ShowMessage(errorNotDebugging, "${res:XML.MainMenu.DebugMenu.Stop}");
- return;
- }
- if (IsAttached) {
- StopAttachedProcessDialogResult result = ShowStopAttachedProcessDialog();
- switch (result) {
- case StopAttachedProcessDialogResult.Terminate:
- debuggedProcess.Terminate();
- attached = false;
- break;
- case StopAttachedProcessDialogResult.Detach:
- Detach();
- attached = false;
- break;
- }
- } else {
- debuggedProcess.Terminate();
- }
- }
-
- // ExecutionControl:
-
- public void Break()
- {
- if (!IsDebugging) {
- MessageService.ShowMessage(errorNotDebugging, "${res:XML.MainMenu.DebugMenu.Break}");
- return;
- }
- if (!IsProcessRunning) {
- MessageService.ShowMessage(errorProcessPaused, "${res:XML.MainMenu.DebugMenu.Break}");
- return;
- }
- debuggedProcess.Break();
- }
-
- public void Continue()
- {
- if (!IsDebugging) {
- MessageService.ShowMessage(errorNotDebugging, "${res:XML.MainMenu.DebugMenu.Continue}");
- return;
- }
- if (IsProcessRunning) {
- MessageService.ShowMessage(errorProcessRunning, "${res:XML.MainMenu.DebugMenu.Continue}");
- return;
- }
- debuggedProcess.AsyncContinue();
- }
-
- // Stepping:
- Debugger.StackFrame GetStackFrame()
- {
- bool isMatch = false;
- int line = -1;
- int[] ilRange = null;
-
- var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
- int typeToken = frame.MethodInfo.DeclaringType.MetadataToken;
- int methodToken = frame.MethodInfo.MetadataToken;
-
- // get the mapped instruction from the current line marker or the next one
- if (!debuggerDecompilerService.GetILAndLineNumber(typeToken, methodToken, frame.IP, out ilRange, out line, out isMatch)){
- frame.SourceCodeLine = 0;
- frame.ILRanges = new [] { 0, 1 };
- } else {
- frame.SourceCodeLine = line;
- frame.ILRanges = ilRange;
- }
-
- return frame;
- }
-
- public void StepInto()
- {
- if (!IsDebugging) {
- MessageService.ShowMessage(errorNotDebugging, "${res:XML.MainMenu.DebugMenu.StepInto}");
- return;
- }
-
- if (debuggedProcess.IsRunning) {
- MessageService.ShowMessage(errorProcessRunning, "${res:XML.MainMenu.DebugMenu.StepInto}");
- return;
- }
-
- var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
- if (frame == null) {
- MessageService.ShowMessage(errorCannotStepNoActiveFunction, "${res:XML.MainMenu.DebugMenu.StepInto}");
- } else {
- if (!frame.HasSymbols) {
- // get frame info from external code mappings
- frame = GetStackFrame();
- }
-
- frame.AsyncStepInto();
- }
- }
-
- public void StepOver()
- {
- if (!IsDebugging) {
- MessageService.ShowMessage(errorNotDebugging, "${res:XML.MainMenu.DebugMenu.StepOver}");
- return;
- }
-
- if (debuggedProcess.IsRunning) {
- MessageService.ShowMessage(errorProcessRunning, "${res:XML.MainMenu.DebugMenu.StepOver}");
- return;
- }
-
- var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
- if (frame == null) {
- MessageService.ShowMessage(errorCannotStepNoActiveFunction, "${res:XML.MainMenu.DebugMenu.StepOver}");
- } else {
- if (!frame.HasSymbols) {
- // get frame info from external code mappings
- frame = GetStackFrame();
- }
-
- frame.AsyncStepOver();
- }
- }
-
- public void StepOut()
- {
- if (!IsDebugging) {
- MessageService.ShowMessage(errorNotDebugging, "${res:XML.MainMenu.DebugMenu.StepOut}");
- return;
- }
-
- if (debuggedProcess.IsRunning) {
- MessageService.ShowMessage(errorProcessRunning, "${res:XML.MainMenu.DebugMenu.StepOut}");
- return;
- }
-
- var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
- if (frame == null) {
- MessageService.ShowMessage(errorCannotStepNoActiveFunction, "${res:XML.MainMenu.DebugMenu.StepInto}");
- } else {
- if (!frame.HasSymbols) {
- // get frame info from external code mappings
- frame = GetStackFrame();
- }
-
- frame.AsyncStepOut();
- }
- }
-
- public event EventHandler DebugStarting;
- public event EventHandler DebugStarted;
- public event EventHandler DebugStopped;
- public event EventHandler IsProcessRunningChanged;
-
- protected virtual void OnIsProcessRunningChanged(EventArgs e)
- {
- if (IsProcessRunningChanged != null) {
- IsProcessRunningChanged(this, e);
- }
- }
-
- ///
- /// Gets variable of given name.
- /// Returns null if unsuccessful. Can throw GetValueException.
- /// Thrown when evaluation fails. Exception message explains reason.
- ///
- public Value GetValueFromName(string variableName)
- {
- if (!CanEvaluate) {
- return null;
- }
-
- var frame = debuggedProcess.GetCurrentExecutingFrame();
- if (frame == null)
- return null;
- object data = debuggerDecompilerService.GetLocalVariableIndex(frame.MethodInfo.DeclaringType.MetadataToken,
- frame.MethodInfo.MetadataToken,
- variableName);
- // evaluate expression
- return ExpressionEvaluator.Evaluate(variableName, SupportedLanguage.CSharp, frame, data);
- }
-
- ///
- /// Gets Expression for given variable. Can throw GetValueException.
- /// Thrown when getting expression fails. Exception message explains reason.
- ///
- public Expression GetExpression(string variableName)
- {
- if (!CanEvaluate) {
- throw new GetValueException("Cannot evaluate now - debugged process is either null or running or has no selected stack frame");
- }
- return ExpressionEvaluator.ParseExpression(variableName, SupportedLanguage.CSharp);
- }
-
- public bool IsManaged(int processId)
- {
- corPublish = new CorpubPublishClass();
- Debugger.Interop.TrackedComObjects.Track(corPublish);
-
- ICorPublishProcess process = corPublish.GetProcess((uint)processId);
- if (process != null) {
- return process.IsManaged() != 0;
- }
- return false;
- }
-
- ///
- /// Gets the current value of the variable as string that can be displayed in tooltips.
- /// Returns null if unsuccessful.
- ///
- public string GetValueAsString(string variableName)
- {
- try {
- Value val = GetValueFromName(variableName);
- if (val == null) return null;
- return val.AsString();
- } catch (GetValueException) {
- return null;
- }
- }
-
- bool CanEvaluate
- {
- get {
- return debuggedProcess != null && !debuggedProcess.IsRunning &&
- (debuggedProcess.SelectedStackFrame != null || debuggedProcess.SelectedThread.MostRecentStackFrame != null);
- }
- }
-
- ///
- /// Gets the tooltip control that shows the value of given variable.
- /// Return null if no tooltip is available.
- ///
- public object GetTooltipControl(Location logicalPosition, string variableName)
- {
- try {
- var tooltipExpression = GetExpression(variableName);
- string imageName;
- var image = ExpressionNode.GetImageForLocalVariable(out imageName);
- ExpressionNode expressionNode = new ExpressionNode(null, image, variableName, tooltipExpression);
- expressionNode.ImageName = imageName;
- return new DebuggerTooltipControl(logicalPosition, expressionNode) { ShowPins = debuggedProcess.GetCurrentExecutingFrame().HasSymbols };
- } catch (System.Exception ex) {
- LoggingService.Error("Error on GetTooltipControl: " + ex.Message);
- return null;
- }
- }
-
- public ITreeNode GetNode(string variable, string currentImageName = null)
- {
- try {
- var expression = GetExpression(variable);
- string imageName;
- IImage image;
- if (string.IsNullOrEmpty(currentImageName)) {
- image = ExpressionNode.GetImageForLocalVariable(out imageName);
- }
- else {
- image = new ResourceServiceImage(currentImageName);
- imageName = currentImageName;
- }
- ExpressionNode expressionNode = new ExpressionNode(null, image, variable, expression);
- expressionNode.ImageName = imageName;
- return expressionNode;
- } catch (GetValueException) {
- return null;
- }
- }
-
- public bool CanSetInstructionPointer(string filename, int line, int column)
- {
- if (debuggedProcess != null && debuggedProcess.IsPaused && debuggedProcess.SelectedStackFrame != null) {
- SourcecodeSegment seg = debuggedProcess.SelectedStackFrame.CanSetIP(filename, line, column);
- return seg != null;
- } else {
- return false;
- }
- }
-
- public bool SetInstructionPointer(string filename, int line, int column)
- {
- if (CanSetInstructionPointer(filename, line, column)) {
- SourcecodeSegment seg = debuggedProcess.SelectedStackFrame.SetIP(filename, line, column);
- return seg != null;
- } else {
- return false;
- }
- }
-
- public void Dispose()
- {
- Stop();
- }
-
- #endregion
-
- public event EventHandler Initialize;
-
- public void InitializeService()
- {
- if (useRemotingForThreadInterop) {
- // This needs to be called before instance of NDebugger is created
- string path = RemotingConfigurationHelpper.GetLoadedAssemblyPath("Debugger.Core.dll");
- new RemotingConfigurationHelpper(path).Configure();
- }
-
- // get decompiler service
- var items = AddInTree.BuildItems("/SharpDevelop/Services/DebuggerDecompilerService", null, false);
- if (items.Count > 0)
- debuggerDecompilerService = items[0];
-
- // init NDebugger
- debugger = new NDebugger();
- debugger.Options = DebuggingOptions.Instance;
- debugger.DebuggerTraceMessage += debugger_TraceMessage;
- debugger.Processes.Added += debugger_ProcessStarted;
- debugger.Processes.Removed += debugger_ProcessExited;
-
- DebuggerService.BreakPointAdded += delegate (object sender, BreakpointBookmarkEventArgs e) {
- AddBreakpoint(e.BreakpointBookmark);
- };
-
- foreach (BreakpointBookmark b in DebuggerService.Breakpoints) {
- AddBreakpoint(b);
- }
-
- if (Initialize != null) {
- Initialize(this, null);
- }
- }
-
- bool Compare(byte[] a, byte[] b)
- {
- if (a.Length != b.Length) return false;
- for(int i = 0; i < a.Length; i++) {
- if (a[i] != b[i]) return false;
- }
- return true;
- }
-
- void AddBreakpoint(BreakpointBookmark bookmark)
- {
- Breakpoint breakpoint = null;
-
- if (bookmark is DecompiledBreakpointBookmark) {
- try {
- if (debuggerDecompilerService == null) {
- LoggingService.Warn("No IDebuggerDecompilerService found!");
- return;
- }
- var dbb = (DecompiledBreakpointBookmark)bookmark;
- MemberReference memberReference = null;
-
- string assemblyFile, typeName;
- if (DecompiledBreakpointBookmark.GetAssemblyAndType(dbb.FileName, out assemblyFile, out typeName)) {
- memberReference = dbb.GetMemberReference(debuggerDecompilerService.GetAssemblyResolver(assemblyFile));
- }
-
- int token = memberReference.MetadataToken.ToInt32();
- if (!debuggerDecompilerService.CheckMappings(token))
- debuggerDecompilerService.DecompileOnDemand(memberReference as TypeDefinition);
-
- int[] ilRanges;
- int methodToken;
- if (debuggerDecompilerService.GetILAndTokenByLineNumber(token, dbb.LineNumber, out ilRanges, out methodToken)) {
- // create BP
- breakpoint = new ILBreakpoint(
- debugger,
- memberReference.FullName,
- dbb.LineNumber,
- memberReference.MetadataToken.ToInt32(),
- methodToken,
- ilRanges[0],
- dbb.IsEnabled);
-
- debugger.Breakpoints.Add(breakpoint);
- }
- } catch (System.Exception ex) {
- LoggingService.Error("Error on DecompiledBreakpointBookmark: " + ex.Message);
- }
- } else {
- breakpoint = debugger.Breakpoints.Add(bookmark.FileName, null, bookmark.LineNumber, 0, bookmark.IsEnabled);
- }
-
- if (breakpoint == null) {
- LoggingService.Warn(string.Format("unable to create breakpoint: {0}", bookmark.ToString()));
- return;
- }
-
- MethodInvoker setBookmarkColor = delegate {
- if (debugger.Processes.Count == 0) {
- bookmark.IsHealthy = true;
- bookmark.Tooltip = null;
- } else if (!breakpoint.IsSet) {
- bookmark.IsHealthy = false;
- bookmark.Tooltip = "Breakpoint was not found in any loaded modules";
- } else if (breakpoint.OriginalLocation == null || breakpoint.OriginalLocation.CheckSum == null) {
- bookmark.IsHealthy = true;
- bookmark.Tooltip = null;
- } else {
- if (!File.Exists(bookmark.FileName))
- return;
-
- byte[] fileMD5;
- IEditable file = FileService.GetOpenFile(bookmark.FileName) as IEditable;
- if (file != null) {
- byte[] fileContent = Encoding.UTF8.GetBytesWithPreamble(file.Text);
- fileMD5 = new MD5CryptoServiceProvider().ComputeHash(fileContent);
- } else {
- fileMD5 = new MD5CryptoServiceProvider().ComputeHash(File.ReadAllBytes(bookmark.FileName));
- }
- if (Compare(fileMD5, breakpoint.OriginalLocation.CheckSum)) {
- bookmark.IsHealthy = true;
- bookmark.Tooltip = null;
- } else {
- bookmark.IsHealthy = false;
- bookmark.Tooltip = "Check sum or file does not match to the original";
- }
- }
- };
-
- // event handlers on bookmark and breakpoint don't need deregistration
- bookmark.IsEnabledChanged += delegate {
- breakpoint.Enabled = bookmark.IsEnabled;
- };
- breakpoint.Set += delegate { setBookmarkColor(); };
-
- setBookmarkColor();
-
- EventHandler> bp_debugger_ProcessStarted = (sender, e) => {
- setBookmarkColor();
- // User can change line number by inserting or deleting lines
- breakpoint.Line = bookmark.LineNumber;
- };
- EventHandler> bp_debugger_ProcessExited = (sender, e) => {
- setBookmarkColor();
- };
-
- EventHandler bp_debugger_BreakpointHit =
- new EventHandler(
- delegate(object sender, BreakpointEventArgs e)
- {
- LoggingService.Debug(bookmark.Action + " " + bookmark.ScriptLanguage + " " + bookmark.Condition);
-
- switch (bookmark.Action) {
- case BreakpointAction.Break:
- break;
- case BreakpointAction.Condition:
- if (Evaluate(bookmark.Condition, bookmark.ScriptLanguage))
- DebuggerService.PrintDebugMessage(string.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.Conditional.Breakpoints.BreakpointHitAtBecause}") + "\n", bookmark.LineNumber, bookmark.FileName, bookmark.Condition));
- else
- this.debuggedProcess.AsyncContinue();
- break;
- case BreakpointAction.Trace:
- DebuggerService.PrintDebugMessage(string.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.Conditional.Breakpoints.BreakpointHitAt}") + "\n", bookmark.LineNumber, bookmark.FileName));
- break;
- }
- });
-
- BookmarkEventHandler bp_bookmarkManager_Removed = null;
- bp_bookmarkManager_Removed = (sender, e) => {
- if (bookmark == e.Bookmark) {
- debugger.Breakpoints.Remove(breakpoint);
-
- // unregister the events
- debugger.Processes.Added -= bp_debugger_ProcessStarted;
- debugger.Processes.Removed -= bp_debugger_ProcessExited;
- breakpoint.Hit -= bp_debugger_BreakpointHit;
- BookmarkManager.Removed -= bp_bookmarkManager_Removed;
- }
- };
- // register the events
- debugger.Processes.Added += bp_debugger_ProcessStarted;
- debugger.Processes.Removed += bp_debugger_ProcessExited;
- breakpoint.Hit += bp_debugger_BreakpointHit;
- BookmarkManager.Removed += bp_bookmarkManager_Removed;
- }
-
- bool Evaluate(string code, string language)
- {
- try {
- SupportedLanguage supportedLanguage = (SupportedLanguage)Enum.Parse(typeof(SupportedLanguage), language, true);
- Value val = ExpressionEvaluator.Evaluate(code, supportedLanguage, debuggedProcess.SelectedStackFrame);
-
- if (val != null && val.Type.IsPrimitive && val.PrimitiveValue is bool)
- return (bool)val.PrimitiveValue;
- else
- return false;
- } catch (GetValueException e) {
- string errorMessage = "Error while evaluating breakpoint condition " + code + ":\n" + e.Message + "\n";
- DebuggerService.PrintDebugMessage(errorMessage);
- WorkbenchSingleton.SafeThreadAsyncCall(MessageService.ShowWarning, errorMessage);
- return true;
- }
- }
-
- void LogMessage(object sender, MessageEventArgs e)
- {
- DebuggerService.PrintDebugMessage(e.Message);
- }
-
- void debugger_TraceMessage(object sender, MessageEventArgs e)
- {
- LoggingService.Debug("Debugger: " + e.Message);
- }
-
- void debugger_ProcessStarted(object sender, CollectionItemEventArgs e)
- {
- if (debugger.Processes.Count == 1) {
- if (DebugStarted != null) {
- DebugStarted(this, EventArgs.Empty);
- }
- }
- e.Item.LogMessage += LogMessage;
- }
-
- void debugger_ProcessExited(object sender, CollectionItemEventArgs e)
- {
- if (debugger.Processes.Count == 0) {
- if (DebugStopped != null) {
- DebugStopped(this, e);
- }
- SelectProcess(null);
- } else {
- SelectProcess(debugger.Processes[0]);
- }
- }
-
- public void SelectProcess(Process process)
- {
- if (debuggedProcess != null) {
- debuggedProcess.Paused -= debuggedProcess_DebuggingPaused;
- debuggedProcess.ExceptionThrown -= debuggedProcess_ExceptionThrown;
- debuggedProcess.Resumed -= debuggedProcess_DebuggingResumed;
- debuggedProcess.ModulesAdded -= debuggedProcess_ModulesAdded;
- }
- debuggedProcess = process;
- if (debuggedProcess != null) {
- debuggedProcess.Paused += debuggedProcess_DebuggingPaused;
- debuggedProcess.ExceptionThrown += debuggedProcess_ExceptionThrown;
- debuggedProcess.Resumed += debuggedProcess_DebuggingResumed;
- debuggedProcess.ModulesAdded += debuggedProcess_ModulesAdded;
-
- debuggedProcess.BreakAtBeginning = BreakAtBeginning;
- }
- // reset
- BreakAtBeginning = false;
-
- JumpToCurrentLine();
- OnProcessSelected(new ProcessEventArgs(process));
- }
-
- void debuggedProcess_ModulesAdded(object sender, ModuleEventArgs e)
- {
- var currentModuleTypes = e.Module.GetNamesOfDefinedTypes();
- foreach (var bookmark in DebuggerService.Breakpoints.OfType()) {
- var breakpoint = debugger.Breakpoints.FirstOrDefault(
- b => b is ILBreakpoint && b.Line == bookmark.LineNumber &&
- ((ILBreakpoint)b).MetadataToken == bookmark.MemberReference.MetadataToken.ToInt32());
- if (breakpoint == null)
- continue;
- // set the breakpoint only if the module contains the type
- if (!currentModuleTypes.Contains(breakpoint.TypeName))
- continue;
-
- breakpoint.SetBreakpoint(e.Module);
- }
- }
-
- void debuggedProcess_DebuggingPaused(object sender, ProcessEventArgs e)
- {
- OnIsProcessRunningChanged(EventArgs.Empty);
-
- using(new PrintTimes("Jump to current line")) {
- JumpToCurrentLine();
- }
- // TODO update tooltip
- /*if (currentTooltipRow != null && currentTooltipRow.IsShown) {
- using(new PrintTimes("Update tooltip")) {
- try {
- Utils.DoEvents(debuggedProcess);
- AbstractNode updatedNode = ValueNode.Create(currentTooltipExpression);
- currentTooltipRow.SetContentRecursive(updatedNode);
- } catch (AbortedBecauseDebuggeeResumedException) {
- }
- }
- }*/
- }
-
- void debuggedProcess_DebuggingResumed(object sender, ProcessEventArgs e)
- {
- OnIsProcessRunningChanged(EventArgs.Empty);
- DebuggerService.RemoveCurrentLineMarker();
- }
-
- void debuggedProcess_ExceptionThrown(object sender, ExceptionEventArgs e)
- {
- JumpToCurrentLine();
-
- StringBuilder stacktraceBuilder = new StringBuilder();
-
- if (e.IsUnhandled) {
- // Need to intercept now so that we can evaluate properties
- if (e.Process.SelectedThread.InterceptException(e.Exception)) {
- stacktraceBuilder.AppendLine(e.Exception.ToString());
- string stackTrace;
- try {
- stackTrace = e.Exception.GetStackTrace(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.EndOfInnerException}"));
- } catch (GetValueException) {
- stackTrace = e.Process.SelectedThread.GetStackTrace(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.Symbols}"), StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.NoSymbols}"));
- }
- stacktraceBuilder.Append(stackTrace);
- } else {
- // For example, happens on stack overflow
- stacktraceBuilder.AppendLine(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Error.CannotInterceptException}"));
- stacktraceBuilder.AppendLine(e.Exception.ToString());
- stacktraceBuilder.Append(e.Process.SelectedThread.GetStackTrace(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.Symbols}"), StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.NoSymbols}")));
- }
- } else {
- stacktraceBuilder.AppendLine(e.Exception.ToString());
- stacktraceBuilder.Append(e.Process.SelectedThread.GetStackTrace(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.Symbols}"), StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.NoSymbols}")));
- }
-
- string title = e.IsUnhandled ? StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Title.Unhandled}") : StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Title.Handled}");
- string message = string.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Message}"), e.Exception.Type);
- Bitmap icon = WinFormsResourceService.GetBitmap(e.IsUnhandled ? "Icons.32x32.Error" : "Icons.32x32.Warning");
-
- DebuggeeExceptionForm.Show(debuggedProcess, title, message, stacktraceBuilder.ToString(), icon, e.IsUnhandled, e.Exception);
- }
-
- public bool BreakAndInterceptHandledException(Debugger.Exception exception)
- {
- if (!debuggedProcess.SelectedThread.InterceptException(exception)) {
- MessageService.ShowError("${res:MainWindow.Windows.Debug.ExceptionForm.Error.CannotInterceptHandledException}");
- return false;
- }
- JumpToCurrentLine();
- return true;
- }
-
- public void JumpToCurrentLine()
- {
- if (debuggedProcess == null || debuggedProcess.SelectedThread == null)
- return;
-
- WorkbenchSingleton.MainWindow.Activate();
-
- if (debuggedProcess.IsSelectedFrameForced()) {
- if (debuggedProcess.SelectedStackFrame != null && debuggedProcess.SelectedStackFrame.HasSymbols) {
- JumpToSourceCode();
- } else {
- JumpToDecompiledCode(debuggedProcess.SelectedStackFrame);
- }
- } else {
- var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
- // other pause reasons
- if (frame != null && frame.HasSymbols) {
- JumpToSourceCode();
- } else {
- // use most recent stack frame because we don't have the symbols
- JumpToDecompiledCode(debuggedProcess.SelectedThread.MostRecentStackFrame);
- }
- }
- }
-
- void JumpToSourceCode()
- {
- if (debuggedProcess == null || debuggedProcess.SelectedThread == null)
- return;
-
- SourcecodeSegment nextStatement = debuggedProcess.NextStatement;
- if (nextStatement != null) {
- DebuggerService.RemoveCurrentLineMarker();
- DebuggerService.JumpToCurrentLine(nextStatement.Filename, nextStatement.StartLine, nextStatement.StartColumn, nextStatement.EndLine, nextStatement.EndColumn);
- }
- }
-
- void JumpToDecompiledCode(Debugger.StackFrame frame)
- {
- if (frame == null) {
- LoggingService.Error("No stack frame!");
- return;
- }
-
- if (debuggerDecompilerService == null) {
- LoggingService.Warn("No IDebuggerDecompilerService found!");
- return;
- }
-
- // check for options - if these options are enabled, debugging decompiled code should not continue
- if (!debuggedProcess.Options.DecompileCodeWithoutSymbols) {
- LoggingService.Info("Decompiled code debugging is disabled!");
- return;
- }
- DebuggerService.RemoveCurrentLineMarker();
- // get external data
- int typeToken = frame.MethodInfo.DeclaringType.MetadataToken;
- int methodToken = frame.MethodInfo.MetadataToken;
- int ilOffset = frame.IP;
- int[] ilRanges = null;
- int line = -1;
- bool isMatch = false;
- var debugType = (DebugType)frame.MethodInfo.DeclaringType;
- debuggerDecompilerService.DebugStepInformation = Tuple.Create(methodToken, ilOffset);
-
- if (debuggerDecompilerService.GetILAndLineNumber(typeToken, methodToken, ilOffset, out ilRanges, out line, out isMatch)) {
- // update marker & navigate to line
- NavigationService.NavigateTo(debugType.DebugModule.FullPath,
- debugType.FullNameWithoutGenericArguments,
- IDStringProvider.GetIDString(frame.MethodInfo),
- line);
- } else {
- // no line => do decompilation
- NavigationService.NavigateTo(debugType.DebugModule.FullPath,
- debugType.FullNameWithoutGenericArguments,
- IDStringProvider.GetIDString(frame.MethodInfo));
-
- }
- }
-
- StopAttachedProcessDialogResult ShowStopAttachedProcessDialog()
- {
- string caption = StringParser.Parse("${res:XML.MainMenu.DebugMenu.Stop}");
- string message = StringParser.Parse("${res:MainWindow.Windows.Debug.StopProcessDialog.Message}");
- string[] buttonLabels = new string[] { StringParser.Parse("${res:XML.MainMenu.DebugMenu.Detach}"), StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Terminate}"), StringParser.Parse("${res:Global.CancelButtonText}") };
- return (StopAttachedProcessDialogResult)MessageService.ShowCustomDialog(caption, message, (int)StopAttachedProcessDialogResult.Detach, (int)StopAttachedProcessDialogResult.Cancel, buttonLabels);
- }
-
- void process_Modules_Added(object sender, CollectionItemEventArgs e)
- {
- if (ProjectService.OpenSolution == null)
- return;
-
- ProjectService.OpenSolution.Projects
- .Where(p => e.Item.Name.IndexOf(p.Name) >= 0)
- .ForEach(p => e.Item.LoadSymbolsFromDisk(new []{ Path.GetDirectoryName(p.OutputAssemblyFullPath) }));
- }
- }
-}
+// 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.Diagnostics;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Security.Cryptography;
+using System.Text;
+using System.Windows.Forms;
+
+using Debugger;
+using Debugger.AddIn.Tooltips;
+using Debugger.AddIn.TreeModel;
+using Debugger.Interop.CorPublish;
+using Debugger.MetaData;
+using ICSharpCode.Core;
+using ICSharpCode.Core.WinForms;
+using ICSharpCode.NRefactory;
+using ICSharpCode.NRefactory.Ast;
+using ICSharpCode.NRefactory.Visitors;
+using ICSharpCode.SharpDevelop.Bookmarks;
+using ICSharpCode.SharpDevelop.Debugging;
+using ICSharpCode.SharpDevelop.Gui;
+using ICSharpCode.SharpDevelop.Gui.OptionPanels;
+using ICSharpCode.SharpDevelop.Project;
+using Mono.Cecil;
+using Process = Debugger.Process;
+
+namespace ICSharpCode.SharpDevelop.Services
+{
+ public class WindowsDebugger : IDebugger
+ {
+ enum StopAttachedProcessDialogResult {
+ Detach = 0,
+ Terminate = 1,
+ Cancel = 2
+ }
+
+ bool useRemotingForThreadInterop = false;
+ bool attached;
+
+ NDebugger debugger;
+
+ ICorPublish corPublish;
+
+ Process debuggedProcess;
+
+ internal IDebuggerDecompilerService debuggerDecompilerService;
+
+ //DynamicTreeDebuggerRow currentTooltipRow;
+ //Expression currentTooltipExpression;
+
+ public event EventHandler ProcessSelected;
+
+ public NDebugger DebuggerCore {
+ get {
+ return debugger;
+ }
+ }
+
+ public Process DebuggedProcess {
+ get {
+ return debuggedProcess;
+ }
+ }
+
+ public static Process CurrentProcess {
+ get {
+ WindowsDebugger dbgr = DebuggerService.CurrentDebugger as WindowsDebugger;
+ if (dbgr != null && dbgr.DebuggedProcess != null) {
+ return dbgr.DebuggedProcess;
+ } else {
+ return null;
+ }
+ }
+ }
+
+ ///
+ public bool BreakAtBeginning {
+ get;
+ set;
+ }
+
+ protected virtual void OnProcessSelected(ProcessEventArgs e)
+ {
+ if (ProcessSelected != null) {
+ ProcessSelected(this, e);
+ }
+ }
+
+ public bool ServiceInitialized {
+ get {
+ return debugger != null;
+ }
+ }
+
+ public WindowsDebugger()
+ {
+
+ }
+
+ #region IDebugger Members
+
+ string errorDebugging = "${res:XML.MainMenu.DebugMenu.Error.Debugging}";
+ string errorNotDebugging = "${res:XML.MainMenu.DebugMenu.Error.NotDebugging}";
+ string errorProcessRunning = "${res:XML.MainMenu.DebugMenu.Error.ProcessRunning}";
+ string errorProcessPaused = "${res:XML.MainMenu.DebugMenu.Error.ProcessPaused}";
+ string errorCannotStepNoActiveFunction = "${res:MainWindow.Windows.Debug.Threads.CannotStepNoActiveFunction}";
+
+ public bool IsDebugging {
+ get {
+ return ServiceInitialized && debuggedProcess != null;
+ }
+ }
+
+ public bool IsAttached {
+ get {
+ return ServiceInitialized && attached;
+ }
+ }
+
+ public bool IsProcessRunning {
+ get {
+ return IsDebugging && debuggedProcess.IsRunning;
+ }
+ }
+
+ public bool CanDebug(IProject project)
+ {
+ return true;
+ }
+
+ public void Start(ProcessStartInfo processStartInfo)
+ {
+ if (IsDebugging) {
+ MessageService.ShowMessage(errorDebugging);
+ return;
+ }
+ if (!ServiceInitialized) {
+ InitializeService();
+ }
+
+ string version = debugger.GetProgramVersion(processStartInfo.FileName);
+
+ if (version.StartsWith("v1.0")) {
+ MessageService.ShowMessage("${res:XML.MainMenu.DebugMenu.Error.Net10NotSupported}");
+ } else if (version.StartsWith("v1.1")) {
+ MessageService.ShowMessage(StringParser.Parse("${res:XML.MainMenu.DebugMenu.Error.Net10NotSupported}").Replace("1.0", "1.1"));
+// } else if (string.IsNullOrEmpty(version)) {
+// // Not a managed assembly
+// MessageService.ShowMessage("${res:XML.MainMenu.DebugMenu.Error.BadAssembly}");
+ } else if (debugger.IsKernelDebuggerEnabled) {
+ MessageService.ShowMessage("${res:XML.MainMenu.DebugMenu.Error.KernelDebuggerEnabled}");
+ } else {
+ attached = false;
+ if (DebugStarting != null)
+ DebugStarting(this, EventArgs.Empty);
+
+ try {
+ // set the JIT flag for evaluating optimized code
+ Process.DebugMode = DebugModeFlag.Debug;
+ Process process = debugger.Start(processStartInfo.FileName,
+ processStartInfo.WorkingDirectory,
+ processStartInfo.Arguments);
+ SelectProcess(process);
+ } catch (System.Exception e) {
+ // COMException: The request is not supported. (Exception from HRESULT: 0x80070032)
+ // COMException: The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log for more detail. (Exception from HRESULT: 0x800736B1)
+ // COMException: The requested operation requires elevation. (Exception from HRESULT: 0x800702E4)
+ // COMException: The directory name is invalid. (Exception from HRESULT: 0x8007010B)
+ // BadImageFormatException: is not a valid Win32 application. (Exception from HRESULT: 0x800700C1)
+ // UnauthorizedAccessException: Отказано в доступе. (Исключение из HRESULT: 0x80070005 (E_ACCESSDENIED))
+ if (e is COMException || e is BadImageFormatException || e is UnauthorizedAccessException) {
+ string msg = StringParser.Parse("${res:XML.MainMenu.DebugMenu.Error.CannotStartProcess}");
+ msg += " " + e.Message;
+ // TODO: Remove
+ if (e is COMException && ((uint)((COMException)e).ErrorCode == 0x80070032)) {
+ msg += Environment.NewLine + Environment.NewLine;
+ msg += "64-bit debugging is not supported. Please set Project -> Project Options... -> Compiling -> Target CPU to 32bit.";
+ }
+ MessageService.ShowMessage(msg);
+
+ if (DebugStopped != null)
+ DebugStopped(this, EventArgs.Empty);
+ } else {
+ throw;
+ }
+ }
+ }
+ }
+
+ public void ShowAttachDialog()
+ {
+ using (AttachToProcessForm attachForm = new AttachToProcessForm()) {
+ if (attachForm.ShowDialog(WorkbenchSingleton.MainWin32Window) == DialogResult.OK) {
+ Attach(attachForm.Process);
+ }
+ }
+ }
+
+ public void Attach(System.Diagnostics.Process existingProcess)
+ {
+ if (existingProcess == null)
+ return;
+
+ if (IsDebugging) {
+ MessageService.ShowMessage(errorDebugging);
+ return;
+ }
+ if (!ServiceInitialized) {
+ InitializeService();
+ }
+
+ string version = debugger.GetProgramVersion(existingProcess.MainModule.FileName);
+ if (version.StartsWith("v1.0")) {
+ MessageService.ShowMessage("${res:XML.MainMenu.DebugMenu.Error.Net10NotSupported}");
+ } else {
+ if (DebugStarting != null)
+ DebugStarting(this, EventArgs.Empty);
+
+ try {
+ // set the JIT flag for evaluating optimized code
+ Process.DebugMode = DebugModeFlag.Debug;
+ Process process = debugger.Attach(existingProcess);
+ attached = true;
+ SelectProcess(process);
+
+ process.Modules.Added += process_Modules_Added;
+ } catch (System.Exception e) {
+ // CORDBG_E_DEBUGGER_ALREADY_ATTACHED
+ if (e is COMException || e is UnauthorizedAccessException) {
+ string msg = StringParser.Parse("${res:XML.MainMenu.DebugMenu.Error.CannotAttachToProcess}");
+ MessageService.ShowMessage(msg + " " + e.Message);
+
+ if (DebugStopped != null)
+ DebugStopped(this, EventArgs.Empty);
+ } else {
+ throw;
+ }
+ }
+ }
+ }
+
+ public void Detach()
+ {
+ debugger.Detach();
+ }
+
+ public void StartWithoutDebugging(ProcessStartInfo processStartInfo)
+ {
+ System.Diagnostics.Process.Start(processStartInfo);
+ }
+
+ public void Stop()
+ {
+ if (!IsDebugging) {
+ MessageService.ShowMessage(errorNotDebugging, "${res:XML.MainMenu.DebugMenu.Stop}");
+ return;
+ }
+ if (IsAttached) {
+ StopAttachedProcessDialogResult result = ShowStopAttachedProcessDialog();
+ switch (result) {
+ case StopAttachedProcessDialogResult.Terminate:
+ debuggedProcess.Terminate();
+ attached = false;
+ break;
+ case StopAttachedProcessDialogResult.Detach:
+ Detach();
+ attached = false;
+ break;
+ }
+ } else {
+ debuggedProcess.Terminate();
+ }
+ }
+
+ // ExecutionControl:
+
+ public void Break()
+ {
+ if (!IsDebugging) {
+ MessageService.ShowMessage(errorNotDebugging, "${res:XML.MainMenu.DebugMenu.Break}");
+ return;
+ }
+ if (!IsProcessRunning) {
+ MessageService.ShowMessage(errorProcessPaused, "${res:XML.MainMenu.DebugMenu.Break}");
+ return;
+ }
+ debuggedProcess.Break();
+ }
+
+ public void Continue()
+ {
+ if (!IsDebugging) {
+ MessageService.ShowMessage(errorNotDebugging, "${res:XML.MainMenu.DebugMenu.Continue}");
+ return;
+ }
+ if (IsProcessRunning) {
+ MessageService.ShowMessage(errorProcessRunning, "${res:XML.MainMenu.DebugMenu.Continue}");
+ return;
+ }
+ debuggedProcess.AsyncContinue();
+ }
+
+ // Stepping:
+ Debugger.StackFrame GetStackFrame()
+ {
+ bool isMatch = false;
+ int line = -1;
+ int[] ilRange = null;
+
+ var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
+ int typeToken = frame.MethodInfo.DeclaringType.MetadataToken;
+ int methodToken = frame.MethodInfo.MetadataToken;
+
+ // get the mapped instruction from the current line marker or the next one
+ if (!debuggerDecompilerService.GetILAndLineNumber(typeToken, methodToken, frame.IP, out ilRange, out line, out isMatch)){
+ frame.SourceCodeLine = 0;
+ frame.ILRanges = new [] { 0, 1 };
+ } else {
+ frame.SourceCodeLine = line;
+ frame.ILRanges = ilRange;
+ }
+
+ return frame;
+ }
+
+ public void StepInto()
+ {
+ if (!IsDebugging) {
+ MessageService.ShowMessage(errorNotDebugging, "${res:XML.MainMenu.DebugMenu.StepInto}");
+ return;
+ }
+
+ if (debuggedProcess.IsRunning) {
+ MessageService.ShowMessage(errorProcessRunning, "${res:XML.MainMenu.DebugMenu.StepInto}");
+ return;
+ }
+
+ var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
+ if (frame == null) {
+ MessageService.ShowMessage(errorCannotStepNoActiveFunction, "${res:XML.MainMenu.DebugMenu.StepInto}");
+ } else {
+ if (!frame.HasSymbols) {
+ // get frame info from external code mappings
+ frame = GetStackFrame();
+ }
+
+ frame.AsyncStepInto();
+ }
+ }
+
+ public void StepOver()
+ {
+ if (!IsDebugging) {
+ MessageService.ShowMessage(errorNotDebugging, "${res:XML.MainMenu.DebugMenu.StepOver}");
+ return;
+ }
+
+ if (debuggedProcess.IsRunning) {
+ MessageService.ShowMessage(errorProcessRunning, "${res:XML.MainMenu.DebugMenu.StepOver}");
+ return;
+ }
+
+ var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
+ if (frame == null) {
+ MessageService.ShowMessage(errorCannotStepNoActiveFunction, "${res:XML.MainMenu.DebugMenu.StepOver}");
+ } else {
+ if (!frame.HasSymbols) {
+ // get frame info from external code mappings
+ frame = GetStackFrame();
+ }
+
+ frame.AsyncStepOver();
+ }
+ }
+
+ public void StepOut()
+ {
+ if (!IsDebugging) {
+ MessageService.ShowMessage(errorNotDebugging, "${res:XML.MainMenu.DebugMenu.StepOut}");
+ return;
+ }
+
+ if (debuggedProcess.IsRunning) {
+ MessageService.ShowMessage(errorProcessRunning, "${res:XML.MainMenu.DebugMenu.StepOut}");
+ return;
+ }
+
+ var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
+ if (frame == null) {
+ MessageService.ShowMessage(errorCannotStepNoActiveFunction, "${res:XML.MainMenu.DebugMenu.StepInto}");
+ } else {
+ if (!frame.HasSymbols) {
+ // get frame info from external code mappings
+ frame = GetStackFrame();
+ }
+
+ frame.AsyncStepOut();
+ }
+ }
+
+ public event EventHandler DebugStarting;
+ public event EventHandler DebugStarted;
+ public event EventHandler DebugStopped;
+ public event EventHandler IsProcessRunningChanged;
+
+ protected virtual void OnIsProcessRunningChanged(EventArgs e)
+ {
+ if (IsProcessRunningChanged != null) {
+ IsProcessRunningChanged(this, e);
+ }
+ }
+
+ ///
+ /// Gets variable of given name.
+ /// Returns null if unsuccessful. Can throw GetValueException.
+ /// Thrown when evaluation fails. Exception message explains reason.
+ ///
+ public Value GetValueFromName(string variableName)
+ {
+ if (!CanEvaluate) {
+ return null;
+ }
+
+ var frame = debuggedProcess.GetCurrentExecutingFrame();
+ if (frame == null)
+ return null;
+ object data = debuggerDecompilerService.GetLocalVariableIndex(frame.MethodInfo.DeclaringType.MetadataToken,
+ frame.MethodInfo.MetadataToken,
+ variableName);
+ // evaluate expression
+ return ExpressionEvaluator.Evaluate(variableName, SupportedLanguage.CSharp, frame, data);
+ }
+
+ ///
+ /// Gets Expression for given variable. Can throw GetValueException.
+ /// Thrown when getting expression fails. Exception message explains reason.
+ ///
+ public Expression GetExpression(string variableName)
+ {
+ if (!CanEvaluate) {
+ throw new GetValueException("Cannot evaluate now - debugged process is either null or running or has no selected stack frame");
+ }
+ return ExpressionEvaluator.ParseExpression(variableName, SupportedLanguage.CSharp);
+ }
+
+ public bool IsManaged(int processId)
+ {
+ corPublish = new CorpubPublishClass();
+ Debugger.Interop.TrackedComObjects.Track(corPublish);
+
+ ICorPublishProcess process = corPublish.GetProcess((uint)processId);
+ if (process != null) {
+ return process.IsManaged() != 0;
+ }
+ return false;
+ }
+
+ ///
+ /// Gets the current value of the variable as string that can be displayed in tooltips.
+ /// Returns null if unsuccessful.
+ ///
+ public string GetValueAsString(string variableName)
+ {
+ try {
+ Value val = GetValueFromName(variableName);
+ if (val == null) return null;
+ return val.AsString();
+ } catch (GetValueException) {
+ return null;
+ }
+ }
+
+ bool CanEvaluate
+ {
+ get {
+ return debuggedProcess != null && !debuggedProcess.IsRunning &&
+ (debuggedProcess.SelectedStackFrame != null || debuggedProcess.SelectedThread.MostRecentStackFrame != null);
+ }
+ }
+
+ ///
+ /// Gets the tooltip control that shows the value of given variable.
+ /// Return null if no tooltip is available.
+ ///
+ public object GetTooltipControl(Location logicalPosition, string variableName)
+ {
+ try {
+ var tooltipExpression = GetExpression(variableName);
+ string imageName;
+ var image = ExpressionNode.GetImageForLocalVariable(out imageName);
+ ExpressionNode expressionNode = new ExpressionNode(null, image, variableName, tooltipExpression);
+ expressionNode.ImageName = imageName;
+ return new DebuggerTooltipControl(logicalPosition, expressionNode) { ShowPins = debuggedProcess.GetCurrentExecutingFrame().HasSymbols };
+ } catch (System.Exception ex) {
+ LoggingService.Error("Error on GetTooltipControl: " + ex.Message);
+ return null;
+ }
+ }
+
+ public ITreeNode GetNode(string variable, string currentImageName = null)
+ {
+ try {
+ var expression = GetExpression(variable);
+ string imageName;
+ IImage image;
+ if (string.IsNullOrEmpty(currentImageName)) {
+ image = ExpressionNode.GetImageForLocalVariable(out imageName);
+ }
+ else {
+ image = new ResourceServiceImage(currentImageName);
+ imageName = currentImageName;
+ }
+ ExpressionNode expressionNode = new ExpressionNode(null, image, variable, expression);
+ expressionNode.ImageName = imageName;
+ return expressionNode;
+ } catch (GetValueException) {
+ return null;
+ }
+ }
+
+ public bool CanSetInstructionPointer(string filename, int line, int column)
+ {
+ if (debuggedProcess != null && debuggedProcess.IsPaused && debuggedProcess.SelectedStackFrame != null) {
+ SourcecodeSegment seg = debuggedProcess.SelectedStackFrame.CanSetIP(filename, line, column);
+ return seg != null;
+ } else {
+ return false;
+ }
+ }
+
+ public bool SetInstructionPointer(string filename, int line, int column)
+ {
+ if (CanSetInstructionPointer(filename, line, column)) {
+ SourcecodeSegment seg = debuggedProcess.SelectedStackFrame.SetIP(filename, line, column);
+ return seg != null;
+ } else {
+ return false;
+ }
+ }
+
+ public void Dispose()
+ {
+ Stop();
+ }
+
+ #endregion
+
+ public event EventHandler Initialize;
+
+ public void InitializeService()
+ {
+ if (useRemotingForThreadInterop) {
+ // This needs to be called before instance of NDebugger is created
+ string path = RemotingConfigurationHelpper.GetLoadedAssemblyPath("Debugger.Core.dll");
+ new RemotingConfigurationHelpper(path).Configure();
+ }
+
+ // get decompiler service
+ var items = AddInTree.BuildItems("/SharpDevelop/Services/DebuggerDecompilerService", null, false);
+ if (items.Count > 0)
+ debuggerDecompilerService = items[0];
+
+ // init NDebugger
+ debugger = new NDebugger();
+ debugger.Options = DebuggingOptions.Instance;
+ debugger.DebuggerTraceMessage += debugger_TraceMessage;
+ debugger.Processes.Added += debugger_ProcessStarted;
+ debugger.Processes.Removed += debugger_ProcessExited;
+
+ DebuggerService.BreakPointAdded += delegate (object sender, BreakpointBookmarkEventArgs e) {
+ AddBreakpoint(e.BreakpointBookmark);
+ };
+
+ foreach (BreakpointBookmark b in DebuggerService.Breakpoints) {
+ AddBreakpoint(b);
+ }
+
+ if (Initialize != null) {
+ Initialize(this, null);
+ }
+ }
+
+ bool Compare(byte[] a, byte[] b)
+ {
+ if (a.Length != b.Length) return false;
+ for(int i = 0; i < a.Length; i++) {
+ if (a[i] != b[i]) return false;
+ }
+ return true;
+ }
+
+ void AddBreakpoint(BreakpointBookmark bookmark)
+ {
+ Breakpoint breakpoint = null;
+
+ if (bookmark is DecompiledBreakpointBookmark) {
+ try {
+ if (debuggerDecompilerService == null) {
+ LoggingService.Warn("No IDebuggerDecompilerService found!");
+ return;
+ }
+ var dbb = (DecompiledBreakpointBookmark)bookmark;
+ MemberReference memberReference = null;
+
+ string assemblyFile, typeName;
+ if (DecompiledBreakpointBookmark.GetAssemblyAndType(dbb.FileName, out assemblyFile, out typeName)) {
+ memberReference = dbb.GetMemberReference(debuggerDecompilerService.GetAssemblyResolver(assemblyFile));
+ }
+
+ int token = memberReference.MetadataToken.ToInt32();
+ if (!debuggerDecompilerService.CheckMappings(token))
+ debuggerDecompilerService.DecompileOnDemand(memberReference as TypeDefinition);
+
+ int[] ilRanges;
+ int methodToken;
+ if (debuggerDecompilerService.GetILAndTokenByLineNumber(token, dbb.LineNumber, out ilRanges, out methodToken)) {
+ // create BP
+ breakpoint = new ILBreakpoint(
+ debugger,
+ memberReference.FullName,
+ dbb.LineNumber,
+ memberReference.MetadataToken.ToInt32(),
+ methodToken,
+ ilRanges[0],
+ dbb.IsEnabled);
+
+ debugger.Breakpoints.Add(breakpoint);
+ }
+ } catch (System.Exception ex) {
+ LoggingService.Error("Error on DecompiledBreakpointBookmark: " + ex.Message);
+ }
+ } else {
+ breakpoint = debugger.Breakpoints.Add(bookmark.FileName, null, bookmark.LineNumber, 0, bookmark.IsEnabled);
+ }
+
+ if (breakpoint == null) {
+ LoggingService.Warn(string.Format("unable to create breakpoint: {0}", bookmark.ToString()));
+ return;
+ }
+
+ MethodInvoker setBookmarkColor = delegate {
+ if (debugger.Processes.Count == 0) {
+ bookmark.IsHealthy = true;
+ bookmark.Tooltip = null;
+ } else if (!breakpoint.IsSet) {
+ bookmark.IsHealthy = false;
+ bookmark.Tooltip = "Breakpoint was not found in any loaded modules";
+ } else if (breakpoint.OriginalLocation == null || breakpoint.OriginalLocation.CheckSum == null) {
+ bookmark.IsHealthy = true;
+ bookmark.Tooltip = null;
+ } else {
+ if (!File.Exists(bookmark.FileName))
+ return;
+
+ byte[] fileMD5;
+ IEditable file = FileService.GetOpenFile(bookmark.FileName) as IEditable;
+ if (file != null) {
+ byte[] fileContent = Encoding.UTF8.GetBytesWithPreamble(file.Text);
+ fileMD5 = new MD5CryptoServiceProvider().ComputeHash(fileContent);
+ } else {
+ fileMD5 = new MD5CryptoServiceProvider().ComputeHash(File.ReadAllBytes(bookmark.FileName));
+ }
+ if (Compare(fileMD5, breakpoint.OriginalLocation.CheckSum)) {
+ bookmark.IsHealthy = true;
+ bookmark.Tooltip = null;
+ } else {
+ bookmark.IsHealthy = false;
+ bookmark.Tooltip = "Check sum or file does not match to the original";
+ }
+ }
+ };
+
+ // event handlers on bookmark and breakpoint don't need deregistration
+ bookmark.IsEnabledChanged += delegate {
+ breakpoint.Enabled = bookmark.IsEnabled;
+ };
+ breakpoint.Set += delegate { setBookmarkColor(); };
+
+ setBookmarkColor();
+
+ EventHandler> bp_debugger_ProcessStarted = (sender, e) => {
+ setBookmarkColor();
+ // User can change line number by inserting or deleting lines
+ breakpoint.Line = bookmark.LineNumber;
+ };
+ EventHandler> bp_debugger_ProcessExited = (sender, e) => {
+ setBookmarkColor();
+ };
+
+ EventHandler bp_debugger_BreakpointHit =
+ new EventHandler(
+ delegate(object sender, BreakpointEventArgs e)
+ {
+ LoggingService.Debug(bookmark.Action + " " + bookmark.ScriptLanguage + " " + bookmark.Condition);
+
+ switch (bookmark.Action) {
+ case BreakpointAction.Break:
+ break;
+ case BreakpointAction.Condition:
+ if (Evaluate(bookmark.Condition, bookmark.ScriptLanguage))
+ DebuggerService.PrintDebugMessage(string.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.Conditional.Breakpoints.BreakpointHitAtBecause}") + "\n", bookmark.LineNumber, bookmark.FileName, bookmark.Condition));
+ else
+ this.debuggedProcess.AsyncContinue();
+ break;
+ case BreakpointAction.Trace:
+ DebuggerService.PrintDebugMessage(string.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.Conditional.Breakpoints.BreakpointHitAt}") + "\n", bookmark.LineNumber, bookmark.FileName));
+ break;
+ }
+ });
+
+ BookmarkEventHandler bp_bookmarkManager_Removed = null;
+ bp_bookmarkManager_Removed = (sender, e) => {
+ if (bookmark == e.Bookmark) {
+ debugger.Breakpoints.Remove(breakpoint);
+
+ // unregister the events
+ debugger.Processes.Added -= bp_debugger_ProcessStarted;
+ debugger.Processes.Removed -= bp_debugger_ProcessExited;
+ breakpoint.Hit -= bp_debugger_BreakpointHit;
+ BookmarkManager.Removed -= bp_bookmarkManager_Removed;
+ }
+ };
+ // register the events
+ debugger.Processes.Added += bp_debugger_ProcessStarted;
+ debugger.Processes.Removed += bp_debugger_ProcessExited;
+ breakpoint.Hit += bp_debugger_BreakpointHit;
+ BookmarkManager.Removed += bp_bookmarkManager_Removed;
+ }
+
+ bool Evaluate(string code, string language)
+ {
+ try {
+ SupportedLanguage supportedLanguage = (SupportedLanguage)Enum.Parse(typeof(SupportedLanguage), language, true);
+ Value val = ExpressionEvaluator.Evaluate(code, supportedLanguage, debuggedProcess.SelectedStackFrame);
+
+ if (val != null && val.Type.IsPrimitive && val.PrimitiveValue is bool)
+ return (bool)val.PrimitiveValue;
+ else
+ return false;
+ } catch (GetValueException e) {
+ string errorMessage = "Error while evaluating breakpoint condition " + code + ":\n" + e.Message + "\n";
+ DebuggerService.PrintDebugMessage(errorMessage);
+ WorkbenchSingleton.SafeThreadAsyncCall(MessageService.ShowWarning, errorMessage);
+ return true;
+ }
+ }
+
+ void LogMessage(object sender, MessageEventArgs e)
+ {
+ DebuggerService.PrintDebugMessage(e.Message);
+ }
+
+ void debugger_TraceMessage(object sender, MessageEventArgs e)
+ {
+ LoggingService.Debug("Debugger: " + e.Message);
+ }
+
+ void debugger_ProcessStarted(object sender, CollectionItemEventArgs e)
+ {
+ if (debugger.Processes.Count == 1) {
+ if (DebugStarted != null) {
+ DebugStarted(this, EventArgs.Empty);
+ }
+ }
+ e.Item.LogMessage += LogMessage;
+ }
+
+ void debugger_ProcessExited(object sender, CollectionItemEventArgs e)
+ {
+ if (debugger.Processes.Count == 0) {
+ if (DebugStopped != null) {
+ DebugStopped(this, e);
+ }
+ SelectProcess(null);
+ } else {
+ SelectProcess(debugger.Processes[0]);
+ }
+ }
+
+ public void SelectProcess(Process process)
+ {
+ if (debuggedProcess != null) {
+ debuggedProcess.Paused -= debuggedProcess_DebuggingPaused;
+ debuggedProcess.ExceptionThrown -= debuggedProcess_ExceptionThrown;
+ debuggedProcess.Resumed -= debuggedProcess_DebuggingResumed;
+ debuggedProcess.ModulesAdded -= debuggedProcess_ModulesAdded;
+ }
+ debuggedProcess = process;
+ if (debuggedProcess != null) {
+ debuggedProcess.Paused += debuggedProcess_DebuggingPaused;
+ debuggedProcess.ExceptionThrown += debuggedProcess_ExceptionThrown;
+ debuggedProcess.Resumed += debuggedProcess_DebuggingResumed;
+ debuggedProcess.ModulesAdded += debuggedProcess_ModulesAdded;
+
+ debuggedProcess.BreakAtBeginning = BreakAtBeginning;
+ }
+ // reset
+ BreakAtBeginning = false;
+
+ JumpToCurrentLine();
+ OnProcessSelected(new ProcessEventArgs(process));
+ }
+
+ void debuggedProcess_ModulesAdded(object sender, ModuleEventArgs e)
+ {
+ var currentModuleTypes = e.Module.GetNamesOfDefinedTypes();
+ foreach (var bookmark in DebuggerService.Breakpoints.OfType()) {
+ var breakpoint = debugger.Breakpoints.FirstOrDefault(
+ b => b is ILBreakpoint && b.Line == bookmark.LineNumber &&
+ ((ILBreakpoint)b).MetadataToken == bookmark.MemberReference.MetadataToken.ToInt32());
+ if (breakpoint == null)
+ continue;
+ // set the breakpoint only if the module contains the type
+ if (!currentModuleTypes.Contains(breakpoint.TypeName))
+ continue;
+
+ breakpoint.SetBreakpoint(e.Module);
+ }
+ }
+
+ void debuggedProcess_DebuggingPaused(object sender, ProcessEventArgs e)
+ {
+ OnIsProcessRunningChanged(EventArgs.Empty);
+
+ using(new PrintTimes("Jump to current line")) {
+ JumpToCurrentLine();
+ }
+ // TODO update tooltip
+ /*if (currentTooltipRow != null && currentTooltipRow.IsShown) {
+ using(new PrintTimes("Update tooltip")) {
+ try {
+ Utils.DoEvents(debuggedProcess);
+ AbstractNode updatedNode = ValueNode.Create(currentTooltipExpression);
+ currentTooltipRow.SetContentRecursive(updatedNode);
+ } catch (AbortedBecauseDebuggeeResumedException) {
+ }
+ }
+ }*/
+ }
+
+ void debuggedProcess_DebuggingResumed(object sender, ProcessEventArgs e)
+ {
+ OnIsProcessRunningChanged(EventArgs.Empty);
+ DebuggerService.RemoveCurrentLineMarker();
+ }
+
+ void debuggedProcess_ExceptionThrown(object sender, ExceptionEventArgs e)
+ {
+ JumpToCurrentLine();
+
+ StringBuilder stacktraceBuilder = new StringBuilder();
+
+ if (e.IsUnhandled) {
+ // Need to intercept now so that we can evaluate properties
+ if (e.Process.SelectedThread.InterceptException(e.Exception)) {
+ stacktraceBuilder.AppendLine(e.Exception.ToString());
+ string stackTrace;
+ try {
+ stackTrace = e.Exception.GetStackTrace(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.EndOfInnerException}"));
+ } catch (GetValueException) {
+ stackTrace = e.Process.SelectedThread.GetStackTrace(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.Symbols}"), StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.NoSymbols}"));
+ }
+ stacktraceBuilder.Append(stackTrace);
+ } else {
+ // For example, happens on stack overflow
+ stacktraceBuilder.AppendLine(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Error.CannotInterceptException}"));
+ stacktraceBuilder.AppendLine(e.Exception.ToString());
+ stacktraceBuilder.Append(e.Process.SelectedThread.GetStackTrace(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.Symbols}"), StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.NoSymbols}")));
+ }
+ } else {
+ stacktraceBuilder.AppendLine(e.Exception.ToString());
+ stacktraceBuilder.Append(e.Process.SelectedThread.GetStackTrace(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.Symbols}"), StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.NoSymbols}")));
+ }
+
+ string title = e.IsUnhandled ? StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Title.Unhandled}") : StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Title.Handled}");
+ string message = string.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Message}"), e.Exception.Type);
+ Bitmap icon = WinFormsResourceService.GetBitmap(e.IsUnhandled ? "Icons.32x32.Error" : "Icons.32x32.Warning");
+
+ DebuggeeExceptionForm.Show(debuggedProcess, title, message, stacktraceBuilder.ToString(), icon, e.IsUnhandled, e.Exception);
+ }
+
+ public bool BreakAndInterceptHandledException(Debugger.Exception exception)
+ {
+ if (!debuggedProcess.SelectedThread.InterceptException(exception)) {
+ MessageService.ShowError("${res:MainWindow.Windows.Debug.ExceptionForm.Error.CannotInterceptHandledException}");
+ return false;
+ }
+ JumpToCurrentLine();
+ return true;
+ }
+
+ public void JumpToCurrentLine()
+ {
+ if (debuggedProcess == null || debuggedProcess.SelectedThread == null)
+ return;
+
+ WorkbenchSingleton.MainWindow.Activate();
+
+ if (debuggedProcess.IsSelectedFrameForced()) {
+ if (debuggedProcess.SelectedStackFrame != null && debuggedProcess.SelectedStackFrame.HasSymbols) {
+ JumpToSourceCode();
+ } else {
+ JumpToDecompiledCode(debuggedProcess.SelectedStackFrame);
+ }
+ } else {
+ var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
+ // other pause reasons
+ if (frame != null && frame.HasSymbols) {
+ JumpToSourceCode();
+ } else {
+ // use most recent stack frame because we don't have the symbols
+ JumpToDecompiledCode(debuggedProcess.SelectedThread.MostRecentStackFrame);
+ }
+ }
+ }
+
+ void JumpToSourceCode()
+ {
+ if (debuggedProcess == null || debuggedProcess.SelectedThread == null)
+ return;
+
+ SourcecodeSegment nextStatement = debuggedProcess.NextStatement;
+ if (nextStatement != null) {
+ DebuggerService.RemoveCurrentLineMarker();
+ DebuggerService.JumpToCurrentLine(nextStatement.Filename, nextStatement.StartLine, nextStatement.StartColumn, nextStatement.EndLine, nextStatement.EndColumn);
+ }
+ }
+
+ void JumpToDecompiledCode(Debugger.StackFrame frame)
+ {
+ if (frame == null) {
+ LoggingService.Error("No stack frame!");
+ return;
+ }
+
+ if (debuggerDecompilerService == null) {
+ LoggingService.Warn("No IDebuggerDecompilerService found!");
+ return;
+ }
+
+ // check for options - if these options are enabled, debugging decompiled code should not continue
+ if (!debuggedProcess.Options.DecompileCodeWithoutSymbols) {
+ LoggingService.Info("Decompiled code debugging is disabled!");
+ return;
+ }
+ DebuggerService.RemoveCurrentLineMarker();
+ // get external data
+ int typeToken = frame.MethodInfo.DeclaringType.MetadataToken;
+ int methodToken = frame.MethodInfo.MetadataToken;
+ int ilOffset = frame.IP;
+ int[] ilRanges = null;
+ int line = -1;
+ bool isMatch = false;
+ var debugType = (DebugType)frame.MethodInfo.DeclaringType;
+ debuggerDecompilerService.DebugStepInformation = Tuple.Create(methodToken, ilOffset);
+
+ if (debuggerDecompilerService.GetILAndLineNumber(typeToken, methodToken, ilOffset, out ilRanges, out line, out isMatch)) {
+ // update marker & navigate to line
+ NavigationService.NavigateTo(debugType.DebugModule.FullPath,
+ debugType.FullNameWithoutGenericArguments,
+ IDStringProvider.GetIDString(frame.MethodInfo),
+ line);
+ } else {
+ // no line => do decompilation
+ NavigationService.NavigateTo(debugType.DebugModule.FullPath,
+ debugType.FullNameWithoutGenericArguments,
+ IDStringProvider.GetIDString(frame.MethodInfo));
+
+ }
+ }
+
+ StopAttachedProcessDialogResult ShowStopAttachedProcessDialog()
+ {
+ string caption = StringParser.Parse("${res:XML.MainMenu.DebugMenu.Stop}");
+ string message = StringParser.Parse("${res:MainWindow.Windows.Debug.StopProcessDialog.Message}");
+ string[] buttonLabels = new string[] { StringParser.Parse("${res:XML.MainMenu.DebugMenu.Detach}"), StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Terminate}"), StringParser.Parse("${res:Global.CancelButtonText}") };
+ return (StopAttachedProcessDialogResult)MessageService.ShowCustomDialog(caption, message, (int)StopAttachedProcessDialogResult.Detach, (int)StopAttachedProcessDialogResult.Cancel, buttonLabels);
+ }
+
+ void process_Modules_Added(object sender, CollectionItemEventArgs e)
+ {
+ if (ProjectService.OpenSolution == null)
+ return;
+
+ ProjectService.OpenSolution.Projects
+ .Where(p => e.Item.Name.IndexOf(p.Name) >= 0)
+ .ForEach(p => e.Item.LoadSymbolsFromDisk(new []{ Path.GetDirectoryName(p.OutputAssemblyFullPath) }));
+ }
+ }
+}
diff --git a/src/AddIns/Debugger/Debugger.Core/Breakpoint.cs b/src/AddIns/Debugger/Debugger.Core/Breakpoint.cs
index bca887514f..30fc6fa15b 100644
--- a/src/AddIns/Debugger/Debugger.Core/Breakpoint.cs
+++ b/src/AddIns/Debugger/Debugger.Core/Breakpoint.cs
@@ -1,228 +1,228 @@
-// 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.Runtime.InteropServices;
-
-using Debugger.Interop.CorDebug;
-
-namespace Debugger
-{
- public class Breakpoint: DebuggerObject
- {
- NDebugger debugger;
-
- string fileName;
- byte[] checkSum;
- int line;
- int column;
- bool enabled;
-
- SourcecodeSegment originalLocation;
-
- 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 int Column {
- get { return column; }
- }
-
- public bool Enabled {
- get { return enabled; }
- set {
- enabled = value;
- foreach(ICorDebugFunctionBreakpoint corBreakpoint in corBreakpoints) {
- corBreakpoint.Activate(enabled ? 1 : 0);
- }
- }
- }
-
- 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);
- }
- }
-
- public Breakpoint() { }
-
- public Breakpoint(NDebugger debugger, ICorDebugFunctionBreakpoint corBreakpoint)
- {
- 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.enabled = enabled;
- }
-
- internal bool IsOwnerOf(ICorDebugBreakpoint breakpoint)
- {
- foreach(ICorDebugFunctionBreakpoint corFunBreakpoint in corBreakpoints) {
- if (((ICorDebugBreakpoint)corFunBreakpoint).Equals(breakpoint)) return true;
- }
- 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()
- {
- corBreakpoints.Clear();
- }
-
- public virtual bool SetBreakpoint(Module module)
- {
- if (this.fileName == null)
- return false;
-
- SourcecodeSegment segment = SourcecodeSegment.Resolve(module, FileName, CheckSum, Line, Column);
- if (segment == null) return false;
-
- 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)
- {
- this.Debugger = debugger;
- this.Line = line;
- this.TypeName = typeName;
- this.MetadataToken = metadataToken;
- this.MemberMetadataToken = memberToken;
- this.ILOffset = offset;
- this.Enabled = enabled;
- }
-
- public int MetadataToken { get; private set; }
-
- public int MemberMetadataToken { get; private set; }
-
- public int ILOffset { get; private set; }
-
- public override bool SetBreakpoint(Module module)
- {
- 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);
- corBreakpoints.Add(corBreakpoint);
-
- OnSet(new BreakpointEventArgs(this));
- return true;
- } catch
- #if DEBUG
- (System.Exception)
- #endif
- {
- return false;
- }
- }
- }
-
- [Serializable]
- public class BreakpointEventArgs : DebuggerEventArgs
- {
- public Breakpoint Breakpoint {
- get; private set;
- }
-
- public BreakpointEventArgs(Breakpoint breakpoint): base(breakpoint.Debugger)
- {
- this.Breakpoint = breakpoint;
- }
- }
-}
+// 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.Runtime.InteropServices;
+
+using Debugger.Interop.CorDebug;
+
+namespace Debugger
+{
+ public class Breakpoint: DebuggerObject
+ {
+ NDebugger debugger;
+
+ string fileName;
+ byte[] checkSum;
+ int line;
+ int column;
+ bool enabled;
+
+ SourcecodeSegment originalLocation;
+
+ 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 int Column {
+ get { return column; }
+ }
+
+ public bool Enabled {
+ get { return enabled; }
+ set {
+ enabled = value;
+ foreach(ICorDebugFunctionBreakpoint corBreakpoint in corBreakpoints) {
+ corBreakpoint.Activate(enabled ? 1 : 0);
+ }
+ }
+ }
+
+ 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);
+ }
+ }
+
+ public Breakpoint() { }
+
+ public Breakpoint(NDebugger debugger, ICorDebugFunctionBreakpoint corBreakpoint)
+ {
+ 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.enabled = enabled;
+ }
+
+ internal bool IsOwnerOf(ICorDebugBreakpoint breakpoint)
+ {
+ foreach(ICorDebugFunctionBreakpoint corFunBreakpoint in corBreakpoints) {
+ if (((ICorDebugBreakpoint)corFunBreakpoint).Equals(breakpoint)) return true;
+ }
+ 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()
+ {
+ corBreakpoints.Clear();
+ }
+
+ public virtual bool SetBreakpoint(Module module)
+ {
+ if (this.fileName == null)
+ return false;
+
+ SourcecodeSegment segment = SourcecodeSegment.Resolve(module, FileName, CheckSum, Line, Column);
+ if (segment == null) return false;
+
+ 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)
+ {
+ this.Debugger = debugger;
+ this.Line = line;
+ this.TypeName = typeName;
+ this.MetadataToken = metadataToken;
+ this.MemberMetadataToken = memberToken;
+ this.ILOffset = offset;
+ this.Enabled = enabled;
+ }
+
+ public int MetadataToken { get; private set; }
+
+ public int MemberMetadataToken { get; private set; }
+
+ public int ILOffset { get; private set; }
+
+ public override bool SetBreakpoint(Module module)
+ {
+ 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);
+ corBreakpoints.Add(corBreakpoint);
+
+ OnSet(new BreakpointEventArgs(this));
+ return true;
+ } catch
+ #if DEBUG
+ (System.Exception)
+ #endif
+ {
+ 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/Interop/MetaData.cs b/src/AddIns/Debugger/Debugger.Core/Interop/MetaData.cs
index b0900b29c1..f424b99f55 100644
--- a/src/AddIns/Debugger/Debugger.Core/Interop/MetaData.cs
+++ b/src/AddIns/Debugger/Debugger.Core/Interop/MetaData.cs
@@ -1,6 +1,6 @@
-// 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)
-
+// 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)
+
#pragma warning disable 108, 1591
using System;
@@ -14,7 +14,7 @@ namespace Debugger.Interop.MetaData
{
public uint ridOfField;
public uint ulOffset;
- }
+ }
[System.Flags()]
public enum ClassFieldAttribute: uint
{
@@ -46,7 +46,7 @@ namespace Debugger.Interop.MetaData
fdHasFieldMarshal = 0x1000, // Field has marshalling information.
fdHasDefault = 0x8000, // Field has default.
fdHasFieldRVA = 0x0100, // Field has RVA.
- }
+ }
public enum CorCallingConvention: uint
{
IMAGE_CEE_CS_CALLCONV_DEFAULT = 0x0,
@@ -63,7 +63,7 @@ namespace Debugger.Interop.MetaData
IMAGE_CEE_CS_CALLCONV_MASK = 0x0f, // Calling convention is bottom 4 bits
IMAGE_CEE_CS_CALLCONV_HASTHIS = 0x20, // Top bit indicates a 'this' parameter
IMAGE_CEE_CS_CALLCONV_EXPLICITTHIS = 0x40, // This parameter is explicitly in the signature
- }
+ }
public enum CorMethodAttr: uint
{
// member access mask - Use this mask to retrieve accessibility information.
@@ -104,7 +104,7 @@ namespace Debugger.Interop.MetaData
mdHasSecurity = 0x4000, // Method has security associate with it.
mdRequireSecObject = 0x8000, // Method calls another method containing security code.
- }
+ }
public enum CorTokenType: uint
{
Module = 0x00000000, //
@@ -275,4 +275,4 @@ namespace Debugger.Interop.MetaData
}
}
-#pragma warning restore 108, 1591
+#pragma warning restore 108, 1591
diff --git a/src/AddIns/Debugger/Debugger.Core/Process.cs b/src/AddIns/Debugger/Debugger.Core/Process.cs
index 268bd63f3f..7d2f245410 100644
--- a/src/AddIns/Debugger/Debugger.Core/Process.cs
+++ b/src/AddIns/Debugger/Debugger.Core/Process.cs
@@ -1,754 +1,754 @@
-// 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.Runtime.InteropServices;
-
-using Debugger.Interop.CorDebug;
-using Debugger.Interop.CorSym;
-using ICSharpCode.NRefactory.Ast;
-using ICSharpCode.NRefactory.Visitors;
-
-namespace Debugger
-{
- internal enum DebuggeeStateAction { Keep, Clear }
-
- ///
- /// Debug Mode Flags.
- ///
- public enum DebugModeFlag
- {
- ///
- /// Run in the same mode as without debugger.
- ///
- Default,
- ///
- /// Run in forced optimized mode.
- ///
- Optimized,
- ///
- /// Run in debug mode (easy inspection) but slower.
- ///
- Debug,
- ///
- /// Run in ENC mode (ENC possible) but even slower than debug
- ///
- Enc
- }
-
- public class Process: DebuggerObject
- {
- NDebugger debugger;
-
- ICorDebugProcess corProcess;
- ManagedCallback callbackInterface;
-
- EvalCollection activeEvals;
- ModuleCollection modules;
- ThreadCollection threads;
- AppDomainCollection appDomains;
-
- string workingDirectory;
-
-
- public NDebugger Debugger {
- get { return debugger; }
- }
-
- internal ICorDebugProcess CorProcess {
- get { return corProcess; }
- }
-
- public Options Options {
- get { return debugger.Options; }
- }
-
- public string DebuggeeVersion {
- get { return debugger.DebuggeeVersion; }
- }
-
- internal ManagedCallback CallbackInterface {
- 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 SourcecodeSegment NextStatement {
- get {
- if (SelectedStackFrame == null || IsRunning) {
- return null;
- } else {
- return SelectedStackFrame.NextStatement;
- }
- }
- }
-
- public bool BreakAtBeginning {
- get;
- set;
- }
-
- public AppDomainCollection AppDomains {
- get { return appDomains; }
- }
-
- List steppers = new List();
-
- internal List Steppers {
- get { return steppers; }
- }
-
- public string WorkingDirectory {
- get { return workingDirectory; }
- }
-
- public static DebugModeFlag DebugMode { get; set; }
-
- internal Process(NDebugger debugger, ICorDebugProcess corProcess, string workingDirectory)
- {
- this.debugger = debugger;
- this.corProcess = corProcess;
- 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)
- {
- debugger.TraceMessage("Executing " + filename + " " + arguments);
-
- uint[] processStartupInfo = new uint[17];
- processStartupInfo[0] = sizeof(uint) * 17;
- uint[] processInfo = new uint[4];
-
- ICorDebugProcess outProcess;
-
- if (workingDirectory == null || workingDirectory == "") {
- workingDirectory = System.IO.Path.GetDirectoryName(filename);
- }
-
- _SECURITY_ATTRIBUTES secAttr = new _SECURITY_ATTRIBUTES();
- secAttr.bInheritHandle = 0;
- secAttr.lpSecurityDescriptor = IntPtr.Zero;
- secAttr.nLength = (uint)sizeof(_SECURITY_ATTRIBUTES);
-
- fixed (uint* pprocessStartupInfo = processStartupInfo)
- fixed (uint* pprocessInfo = processInfo)
- outProcess =
- debugger.CorDebug.CreateProcess(
- filename, // lpApplicationName
- // If we do not prepend " ", the first argument migh just get lost
- " " + arguments, // lpCommandLine
- ref secAttr, // lpProcessAttributes
- ref secAttr, // lpThreadAttributes
- 1,//TRUE // bInheritHandles
- 0x00000010 /*CREATE_NEW_CONSOLE*/, // dwCreationFlags
- IntPtr.Zero, // lpEnvironment
- workingDirectory, // lpCurrentDirectory
- (uint)pprocessStartupInfo, // lpStartupInfo
- (uint)pprocessInfo, // lpProcessInformation,
- CorDebugCreateProcessFlags.DEBUG_NO_SPECIAL_OPTIONS // debuggingFlags
- );
-
- 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)
- {
- TraceMessage ("Debugger event: OnLogMessage");
- if (LogMessage != null) {
- LogMessage(this, arg);
- }
- }
-
- public void TraceMessage(string message, params object[] args)
- {
- if (args.Length > 0)
- message = string.Format(message, args);
- System.Diagnostics.Debug.WriteLine("Debugger:" + message);
- debugger.OnDebuggerTraceMessage(new MessageEventArgs(this, message));
- }
-
- /// Read the specified amount of memory at the given memory address
- /// The content of the memory. The amount of the read memory may be less then requested.
- public unsafe byte[] ReadMemory(ulong address, int size)
- {
- byte[] buffer = new byte[size];
- int readCount;
- fixed(byte* pBuffer = buffer) {
- readCount = (int)corProcess.ReadMemory(address, (uint)size, new IntPtr(pBuffer));
- }
- if (readCount != size) Array.Resize(ref buffer, readCount);
- return buffer;
- }
-
- /// Writes the given buffer at the specified memory address
- /// The number of bytes written
- public unsafe int WriteMemory(ulong address, byte[] buffer)
- {
- if (buffer.Length == 0) return 0;
- int written;
- fixed(byte* pBuffer = buffer) {
- written = (int)corProcess.WriteMemory(address, (uint)buffer.Length, new IntPtr(pBuffer));
- }
- 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()
- {
- AssertPaused();
- // No real purpose - just additional check
- if (callbackInterface.IsInCallback) throw new DebuggerException("Can not raise event within callback.");
- TraceMessage ("Debugger event: OnPaused()");
- if (Paused != null) {
- foreach(Delegate d in Paused.GetInvocationList()) {
- if (IsRunning) {
- TraceMessage ("Skipping OnPaused delegate because process has resumed");
- break;
- }
- if (this.TerminateCommandIssued || this.HasExited) {
- TraceMessage ("Skipping OnPaused delegate because process has exited");
- break;
- }
- d.DynamicInvoke(this, new ProcessEventArgs(this));
- }
- }
- }
-
- protected virtual 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));
- }
- }
-
- #endregion
-
- #region PauseSession & DebugeeState
-
- PauseSession pauseSession;
- DebuggeeState debuggeeState;
-
- ///
- /// Indentification of the current debugger session. This value changes whenever debugger is continued
- ///
- public PauseSession 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 {
- get { return debuggeeState; }
- }
-
- /// Puts the process into a paused state
- internal void NotifyPaused(PausedReason pauseReason)
- {
- AssertRunning();
- pauseSession = new PauseSession(this, pauseReason);
- if (debuggeeState == null) {
- debuggeeState = new DebuggeeState(this);
- }
- }
-
- /// Puts the process into a resumed state
- internal void NotifyResumed(DebuggeeStateAction action)
- {
- AssertPaused();
- pauseSession = null;
- if (action == DebuggeeStateAction.Clear) {
- if (debuggeeState == null) throw new DebuggerException("Debugee state already cleared");
- debuggeeState = null;
- this.ExpressionsCache.Clear();
- }
- }
-
- /// 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()
- {
- if (IsRunning) {
- throw new DebuggerException("Process is not paused.");
- }
- }
-
- internal void AssertRunning()
- {
- if (IsPaused) {
- throw new DebuggerException("Process is not running.");
- }
- }
-
- public bool IsRunning {
- get { return pauseSession == null; }
- }
-
- public uint Id {
- get { return corProcess.GetID(); }
- }
-
- public bool IsPaused {
- get { return !IsRunning; }
- }
-
- bool hasExited = false;
-
- public event EventHandler Exited;
-
- public bool HasExited {
- get {
- return hasExited;
- }
- }
-
- internal void NotifyHasExited()
- {
- if(!hasExited) {
- hasExited = true;
- if (Exited != null) {
- Exited(this, new ProcessEventArgs(this));
- }
- // Expire pause seesion first
- if (IsPaused) {
- NotifyResumed(DebuggeeStateAction.Clear);
- }
- debugger.Processes.Remove(this);
- }
- }
-
- public void Break()
- {
- AssertRunning();
-
- corProcess.Stop(uint.MaxValue); // Infinite; ignored anyway
-
- NotifyPaused(PausedReason.ForcedBreak);
- RaisePausedEvents();
- }
-
- public void Detach()
- {
- if (IsRunning) {
- corProcess.Stop(uint.MaxValue);
- NotifyPaused(PausedReason.ForcedBreak);
- }
-
- // This is necessary for detach
- foreach(Stepper s in this.Steppers) {
- if (s.CorStepper.IsActive() == 1) {
- s.CorStepper.Deactivate();
- }
- }
- this.Steppers.Clear();
-
- corProcess.Detach();
-
- // modules
- foreach(Module m in this.Modules)
- {
- m.Dispose();
- }
-
- this.modules.Clear();
-
- // threads
- this.threads.Clear();
-
- NotifyHasExited();
- }
-
- public void Continue()
- {
- AsyncContinue();
- WaitForPause();
- }
-
- internal Thread[] UnsuspendedThreads {
- get {
- List unsuspendedThreads = new List(this.Threads.Count);
- foreach(Thread t in this.Threads) {
- if (!t.Suspended)
- unsuspendedThreads.Add(t);
- }
- return unsuspendedThreads.ToArray();
- }
- }
-
- ///
- /// Resume execution and run all threads not marked by the user as susspended.
- ///
- public void AsyncContinue()
- {
- AsyncContinue(DebuggeeStateAction.Clear, this.UnsuspendedThreads, CorDebugThreadState.THREAD_RUN);
- }
-
- internal CorDebugThreadState NewThreadState = CorDebugThreadState.THREAD_RUN;
-
- /// Null to keep current setting
- /// What happens to created threads. Null to keep current setting
- internal void AsyncContinue(DebuggeeStateAction action, Thread[] threadsToRun, CorDebugThreadState? newThreadState)
- {
- AssertPaused();
-
- if (threadsToRun != null) {
-// corProcess.SetAllThreadsDebugState(CorDebugThreadState.THREAD_SUSPEND, null);
-// Note: There is unreported thread, stopping it prevents the debugee from exiting
-// It is not corProcess.GetHelperThreadID
-// ICorDebugThread[] ts = new ICorDebugThread[corProcess.EnumerateThreads().GetCount()];
-// corProcess.EnumerateThreads().Next((uint)ts.Length, ts);
- foreach(Thread t in this.Threads) {
- CorDebugThreadState state = Array.IndexOf(threadsToRun, t) == -1 ? CorDebugThreadState.THREAD_SUSPEND : CorDebugThreadState.THREAD_RUN;
- try {
- t.CorThread.SetDebugState(state);
- } catch (COMException e) {
- // The state of the thread is invalid. (Exception from HRESULT: 0x8013132D)
- // It can happen for example when thread has not started yet
- if ((uint)e.ErrorCode == 0x8013132D) {
- // TraceMessage("Can not suspend thread - The state of the thread is invalid. Thread ID = " + t.CorThread.GetID());
- } else {
- throw;
- }
- }
- }
- }
-
- if (newThreadState != null) {
- this.NewThreadState = newThreadState.Value;
- }
-
- NotifyResumed(action);
- corProcess.Continue(0);
- if (this.Options.Verbose) {
- this.TraceMessage("Continue");
- }
-
- if (action == DebuggeeStateAction.Clear) {
- OnResumed();
- }
- }
-
- /// Terminates the execution of the process
- public void Terminate()
- {
- AsyncTerminate();
- // Wait until ExitProcess callback is received
- WaitForExit();
- }
-
- /// Terminates the execution of the process
- public void AsyncTerminate()
- {
- // Resume stoped tread
- if (this.IsPaused) {
- // We might get more callbacks so we should maintain consistent sate
- //AsyncContinue(); // Continue the process to get remaining callbacks
- }
-
- // Expose race condition - drain callback queue
- System.Threading.Thread.Sleep(0);
-
- // Stop&terminate - both must be called
- corProcess.Stop(uint.MaxValue);
- corProcess.Terminate(0);
- this.TerminateCommandIssued = true;
-
- // Do not mark the process as exited
- // 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) {
- if (stepper.IsCorStepper(corStepper)) {
- return stepper;
- }
- }
- throw new DebuggerException("Stepper is not in collection");
- }
-
- internal void DisableAllSteppers()
- {
- foreach(Thread thread in this.Threads) {
- thread.CurrentStepIn = null;
- }
- foreach(Stepper stepper in this.Steppers) {
- stepper.Ignore = true;
- }
- }
-
- ///
- /// Waits until the debugger pauses unless it is already paused.
- /// Use PausedReason to find out why it paused.
- ///
- public void WaitForPause()
- {
- while(this.IsRunning && !this.HasExited) {
- debugger.MTA2STA.WaitForCall();
- debugger.MTA2STA.PerformAllCalls();
- }
- if (this.HasExited) throw new ProcessExitedException();
- }
-
- public void WaitForPause(TimeSpan timeout)
- {
- System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
- watch.Start();
- while(this.IsRunning && !this.HasExited) {
- TimeSpan timeLeft = timeout - watch.Elapsed;
- if (timeLeft <= TimeSpan.FromMilliseconds(10)) break;
- //this.TraceMessage("Time left: " + timeLeft.TotalMilliseconds);
- debugger.MTA2STA.WaitForCall(timeLeft);
- debugger.MTA2STA.PerformAllCalls();
- }
- if (this.HasExited) throw new ProcessExitedException();
- }
-
- ///
- /// Waits until the precesses exits.
- ///
- public void WaitForExit()
- {
- while(!this.HasExited) {
- debugger.MTA2STA.WaitForCall();
- debugger.MTA2STA.PerformAllCalls();
- }
- }
-
- #region Break at begining
-
- private void OnModulesAdded(object sender, CollectionItemEventArgs e)
- {
- if (BreakAtBeginning) {
- if (e.Item.SymReader == null) return; // No symbols
-
- try {
- // create a BP at entry point
- uint entryPoint = e.Item.SymReader.GetUserEntryPoint();
- if (entryPoint == 0) return; // no EP
- var mainFunction = e.Item.CorModule.GetFunctionFromToken(entryPoint);
- var corBreakpoint = mainFunction.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;
- };
- } catch {
- // the app does not have an entry point - COM exception
- }
- BreakAtBeginning = false;
- }
-
- if (ModulesAdded != null)
- ModulesAdded(this, new ModuleEventArgs(e.Item));
- }
-
- #endregion
-
- public event EventHandler ModulesAdded;
-
- public StackFrame GetCurrentExecutingFrame()
- {
- if (IsRunning || SelectedThread == null)
- return null;
-
- if (IsSelectedFrameForced()) {
- return SelectedStackFrame; // selected from callstack or threads pads
- }
-
- 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;
- }
- }
-
- public bool IsSelectedFrameForced()
- {
- return pauseSession.PausedReason == PausedReason.CurrentFunctionChanged ||
- pauseSession.PausedReason == PausedReason.CurrentThreadChanged ||
- pauseSession.PausedReason == PausedReason.EvalComplete;
- }
- }
-}
+// 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.Runtime.InteropServices;
+
+using Debugger.Interop.CorDebug;
+using Debugger.Interop.CorSym;
+using ICSharpCode.NRefactory.Ast;
+using ICSharpCode.NRefactory.Visitors;
+
+namespace Debugger
+{
+ internal enum DebuggeeStateAction { Keep, Clear }
+
+ ///
+ /// Debug Mode Flags.
+ ///
+ public enum DebugModeFlag
+ {
+ ///
+ /// Run in the same mode as without debugger.
+ ///
+ Default,
+ ///
+ /// Run in forced optimized mode.
+ ///
+ Optimized,
+ ///
+ /// Run in debug mode (easy inspection) but slower.
+ ///
+ Debug,
+ ///
+ /// Run in ENC mode (ENC possible) but even slower than debug
+ ///
+ Enc
+ }
+
+ public class Process: DebuggerObject
+ {
+ NDebugger debugger;
+
+ ICorDebugProcess corProcess;
+ ManagedCallback callbackInterface;
+
+ EvalCollection activeEvals;
+ ModuleCollection modules;
+ ThreadCollection threads;
+ AppDomainCollection appDomains;
+
+ string workingDirectory;
+
+
+ public NDebugger Debugger {
+ get { return debugger; }
+ }
+
+ internal ICorDebugProcess CorProcess {
+ get { return corProcess; }
+ }
+
+ public Options Options {
+ get { return debugger.Options; }
+ }
+
+ public string DebuggeeVersion {
+ get { return debugger.DebuggeeVersion; }
+ }
+
+ internal ManagedCallback CallbackInterface {
+ 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 SourcecodeSegment NextStatement {
+ get {
+ if (SelectedStackFrame == null || IsRunning) {
+ return null;
+ } else {
+ return SelectedStackFrame.NextStatement;
+ }
+ }
+ }
+
+ public bool BreakAtBeginning {
+ get;
+ set;
+ }
+
+ public AppDomainCollection AppDomains {
+ get { return appDomains; }
+ }
+
+ List steppers = new List();
+
+ internal List Steppers {
+ get { return steppers; }
+ }
+
+ public string WorkingDirectory {
+ get { return workingDirectory; }
+ }
+
+ public static DebugModeFlag DebugMode { get; set; }
+
+ internal Process(NDebugger debugger, ICorDebugProcess corProcess, string workingDirectory)
+ {
+ this.debugger = debugger;
+ this.corProcess = corProcess;
+ 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)
+ {
+ debugger.TraceMessage("Executing " + filename + " " + arguments);
+
+ uint[] processStartupInfo = new uint[17];
+ processStartupInfo[0] = sizeof(uint) * 17;
+ uint[] processInfo = new uint[4];
+
+ ICorDebugProcess outProcess;
+
+ if (workingDirectory == null || workingDirectory == "") {
+ workingDirectory = System.IO.Path.GetDirectoryName(filename);
+ }
+
+ _SECURITY_ATTRIBUTES secAttr = new _SECURITY_ATTRIBUTES();
+ secAttr.bInheritHandle = 0;
+ secAttr.lpSecurityDescriptor = IntPtr.Zero;
+ secAttr.nLength = (uint)sizeof(_SECURITY_ATTRIBUTES);
+
+ fixed (uint* pprocessStartupInfo = processStartupInfo)
+ fixed (uint* pprocessInfo = processInfo)
+ outProcess =
+ debugger.CorDebug.CreateProcess(
+ filename, // lpApplicationName
+ // If we do not prepend " ", the first argument migh just get lost
+ " " + arguments, // lpCommandLine
+ ref secAttr, // lpProcessAttributes
+ ref secAttr, // lpThreadAttributes
+ 1,//TRUE // bInheritHandles
+ 0x00000010 /*CREATE_NEW_CONSOLE*/, // dwCreationFlags
+ IntPtr.Zero, // lpEnvironment
+ workingDirectory, // lpCurrentDirectory
+ (uint)pprocessStartupInfo, // lpStartupInfo
+ (uint)pprocessInfo, // lpProcessInformation,
+ CorDebugCreateProcessFlags.DEBUG_NO_SPECIAL_OPTIONS // debuggingFlags
+ );
+
+ 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)
+ {
+ TraceMessage ("Debugger event: OnLogMessage");
+ if (LogMessage != null) {
+ LogMessage(this, arg);
+ }
+ }
+
+ public void TraceMessage(string message, params object[] args)
+ {
+ if (args.Length > 0)
+ message = string.Format(message, args);
+ System.Diagnostics.Debug.WriteLine("Debugger:" + message);
+ debugger.OnDebuggerTraceMessage(new MessageEventArgs(this, message));
+ }
+
+ /// Read the specified amount of memory at the given memory address
+ /// The content of the memory. The amount of the read memory may be less then requested.
+ public unsafe byte[] ReadMemory(ulong address, int size)
+ {
+ byte[] buffer = new byte[size];
+ int readCount;
+ fixed(byte* pBuffer = buffer) {
+ readCount = (int)corProcess.ReadMemory(address, (uint)size, new IntPtr(pBuffer));
+ }
+ if (readCount != size) Array.Resize(ref buffer, readCount);
+ return buffer;
+ }
+
+ /// Writes the given buffer at the specified memory address
+ /// The number of bytes written
+ public unsafe int WriteMemory(ulong address, byte[] buffer)
+ {
+ if (buffer.Length == 0) return 0;
+ int written;
+ fixed(byte* pBuffer = buffer) {
+ written = (int)corProcess.WriteMemory(address, (uint)buffer.Length, new IntPtr(pBuffer));
+ }
+ 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()
+ {
+ AssertPaused();
+ // No real purpose - just additional check
+ if (callbackInterface.IsInCallback) throw new DebuggerException("Can not raise event within callback.");
+ TraceMessage ("Debugger event: OnPaused()");
+ if (Paused != null) {
+ foreach(Delegate d in Paused.GetInvocationList()) {
+ if (IsRunning) {
+ TraceMessage ("Skipping OnPaused delegate because process has resumed");
+ break;
+ }
+ if (this.TerminateCommandIssued || this.HasExited) {
+ TraceMessage ("Skipping OnPaused delegate because process has exited");
+ break;
+ }
+ d.DynamicInvoke(this, new ProcessEventArgs(this));
+ }
+ }
+ }
+
+ protected virtual 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));
+ }
+ }
+
+ #endregion
+
+ #region PauseSession & DebugeeState
+
+ PauseSession pauseSession;
+ DebuggeeState debuggeeState;
+
+ ///
+ /// Indentification of the current debugger session. This value changes whenever debugger is continued
+ ///
+ public PauseSession 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 {
+ get { return debuggeeState; }
+ }
+
+ /// Puts the process into a paused state
+ internal void NotifyPaused(PausedReason pauseReason)
+ {
+ AssertRunning();
+ pauseSession = new PauseSession(this, pauseReason);
+ if (debuggeeState == null) {
+ debuggeeState = new DebuggeeState(this);
+ }
+ }
+
+ /// Puts the process into a resumed state
+ internal void NotifyResumed(DebuggeeStateAction action)
+ {
+ AssertPaused();
+ pauseSession = null;
+ if (action == DebuggeeStateAction.Clear) {
+ if (debuggeeState == null) throw new DebuggerException("Debugee state already cleared");
+ debuggeeState = null;
+ this.ExpressionsCache.Clear();
+ }
+ }
+
+ /// 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()
+ {
+ if (IsRunning) {
+ throw new DebuggerException("Process is not paused.");
+ }
+ }
+
+ internal void AssertRunning()
+ {
+ if (IsPaused) {
+ throw new DebuggerException("Process is not running.");
+ }
+ }
+
+ public bool IsRunning {
+ get { return pauseSession == null; }
+ }
+
+ public uint Id {
+ get { return corProcess.GetID(); }
+ }
+
+ public bool IsPaused {
+ get { return !IsRunning; }
+ }
+
+ bool hasExited = false;
+
+ public event EventHandler Exited;
+
+ public bool HasExited {
+ get {
+ return hasExited;
+ }
+ }
+
+ internal void NotifyHasExited()
+ {
+ if(!hasExited) {
+ hasExited = true;
+ if (Exited != null) {
+ Exited(this, new ProcessEventArgs(this));
+ }
+ // Expire pause seesion first
+ if (IsPaused) {
+ NotifyResumed(DebuggeeStateAction.Clear);
+ }
+ debugger.Processes.Remove(this);
+ }
+ }
+
+ public void Break()
+ {
+ AssertRunning();
+
+ corProcess.Stop(uint.MaxValue); // Infinite; ignored anyway
+
+ NotifyPaused(PausedReason.ForcedBreak);
+ RaisePausedEvents();
+ }
+
+ public void Detach()
+ {
+ if (IsRunning) {
+ corProcess.Stop(uint.MaxValue);
+ NotifyPaused(PausedReason.ForcedBreak);
+ }
+
+ // This is necessary for detach
+ foreach(Stepper s in this.Steppers) {
+ if (s.CorStepper.IsActive() == 1) {
+ s.CorStepper.Deactivate();
+ }
+ }
+ this.Steppers.Clear();
+
+ corProcess.Detach();
+
+ // modules
+ foreach(Module m in this.Modules)
+ {
+ m.Dispose();
+ }
+
+ this.modules.Clear();
+
+ // threads
+ this.threads.Clear();
+
+ NotifyHasExited();
+ }
+
+ public void Continue()
+ {
+ AsyncContinue();
+ WaitForPause();
+ }
+
+ internal Thread[] UnsuspendedThreads {
+ get {
+ List unsuspendedThreads = new List(this.Threads.Count);
+ foreach(Thread t in this.Threads) {
+ if (!t.Suspended)
+ unsuspendedThreads.Add(t);
+ }
+ return unsuspendedThreads.ToArray();
+ }
+ }
+
+ ///
+ /// Resume execution and run all threads not marked by the user as susspended.
+ ///
+ public void AsyncContinue()
+ {
+ AsyncContinue(DebuggeeStateAction.Clear, this.UnsuspendedThreads, CorDebugThreadState.THREAD_RUN);
+ }
+
+ internal CorDebugThreadState NewThreadState = CorDebugThreadState.THREAD_RUN;
+
+ /// Null to keep current setting
+ /// What happens to created threads. Null to keep current setting
+ internal void AsyncContinue(DebuggeeStateAction action, Thread[] threadsToRun, CorDebugThreadState? newThreadState)
+ {
+ AssertPaused();
+
+ if (threadsToRun != null) {
+// corProcess.SetAllThreadsDebugState(CorDebugThreadState.THREAD_SUSPEND, null);
+// Note: There is unreported thread, stopping it prevents the debugee from exiting
+// It is not corProcess.GetHelperThreadID
+// ICorDebugThread[] ts = new ICorDebugThread[corProcess.EnumerateThreads().GetCount()];
+// corProcess.EnumerateThreads().Next((uint)ts.Length, ts);
+ foreach(Thread t in this.Threads) {
+ CorDebugThreadState state = Array.IndexOf(threadsToRun, t) == -1 ? CorDebugThreadState.THREAD_SUSPEND : CorDebugThreadState.THREAD_RUN;
+ try {
+ t.CorThread.SetDebugState(state);
+ } catch (COMException e) {
+ // The state of the thread is invalid. (Exception from HRESULT: 0x8013132D)
+ // It can happen for example when thread has not started yet
+ if ((uint)e.ErrorCode == 0x8013132D) {
+ // TraceMessage("Can not suspend thread - The state of the thread is invalid. Thread ID = " + t.CorThread.GetID());
+ } else {
+ throw;
+ }
+ }
+ }
+ }
+
+ if (newThreadState != null) {
+ this.NewThreadState = newThreadState.Value;
+ }
+
+ NotifyResumed(action);
+ corProcess.Continue(0);
+ if (this.Options.Verbose) {
+ this.TraceMessage("Continue");
+ }
+
+ if (action == DebuggeeStateAction.Clear) {
+ OnResumed();
+ }
+ }
+
+ /// Terminates the execution of the process
+ public void Terminate()
+ {
+ AsyncTerminate();
+ // Wait until ExitProcess callback is received
+ WaitForExit();
+ }
+
+ /// Terminates the execution of the process
+ public void AsyncTerminate()
+ {
+ // Resume stoped tread
+ if (this.IsPaused) {
+ // We might get more callbacks so we should maintain consistent sate
+ //AsyncContinue(); // Continue the process to get remaining callbacks
+ }
+
+ // Expose race condition - drain callback queue
+ System.Threading.Thread.Sleep(0);
+
+ // Stop&terminate - both must be called
+ corProcess.Stop(uint.MaxValue);
+ corProcess.Terminate(0);
+ this.TerminateCommandIssued = true;
+
+ // Do not mark the process as exited
+ // 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) {
+ if (stepper.IsCorStepper(corStepper)) {
+ return stepper;
+ }
+ }
+ throw new DebuggerException("Stepper is not in collection");
+ }
+
+ internal void DisableAllSteppers()
+ {
+ foreach(Thread thread in this.Threads) {
+ thread.CurrentStepIn = null;
+ }
+ foreach(Stepper stepper in this.Steppers) {
+ stepper.Ignore = true;
+ }
+ }
+
+ ///
+ /// Waits until the debugger pauses unless it is already paused.
+ /// Use PausedReason to find out why it paused.
+ ///
+ public void WaitForPause()
+ {
+ while(this.IsRunning && !this.HasExited) {
+ debugger.MTA2STA.WaitForCall();
+ debugger.MTA2STA.PerformAllCalls();
+ }
+ if (this.HasExited) throw new ProcessExitedException();
+ }
+
+ public void WaitForPause(TimeSpan timeout)
+ {
+ System.Diagnostics.Stopwatch watch = new System.Diagnostics.Stopwatch();
+ watch.Start();
+ while(this.IsRunning && !this.HasExited) {
+ TimeSpan timeLeft = timeout - watch.Elapsed;
+ if (timeLeft <= TimeSpan.FromMilliseconds(10)) break;
+ //this.TraceMessage("Time left: " + timeLeft.TotalMilliseconds);
+ debugger.MTA2STA.WaitForCall(timeLeft);
+ debugger.MTA2STA.PerformAllCalls();
+ }
+ if (this.HasExited) throw new ProcessExitedException();
+ }
+
+ ///
+ /// Waits until the precesses exits.
+ ///
+ public void WaitForExit()
+ {
+ while(!this.HasExited) {
+ debugger.MTA2STA.WaitForCall();
+ debugger.MTA2STA.PerformAllCalls();
+ }
+ }
+
+ #region Break at begining
+
+ private void OnModulesAdded(object sender, CollectionItemEventArgs e)
+ {
+ if (BreakAtBeginning) {
+ if (e.Item.SymReader == null) return; // No symbols
+
+ try {
+ // create a BP at entry point
+ uint entryPoint = e.Item.SymReader.GetUserEntryPoint();
+ if (entryPoint == 0) return; // no EP
+ var mainFunction = e.Item.CorModule.GetFunctionFromToken(entryPoint);
+ var corBreakpoint = mainFunction.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;
+ };
+ } catch {
+ // the app does not have an entry point - COM exception
+ }
+ BreakAtBeginning = false;
+ }
+
+ if (ModulesAdded != null)
+ ModulesAdded(this, new ModuleEventArgs(e.Item));
+ }
+
+ #endregion
+
+ public event EventHandler ModulesAdded;
+
+ public StackFrame GetCurrentExecutingFrame()
+ {
+ if (IsRunning || SelectedThread == null)
+ return null;
+
+ if (IsSelectedFrameForced()) {
+ return SelectedStackFrame; // selected from callstack or threads pads
+ }
+
+ 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;
+ }
+ }
+
+ public bool IsSelectedFrameForced()
+ {
+ return pauseSession.PausedReason == PausedReason.CurrentFunctionChanged ||
+ pauseSession.PausedReason == PausedReason.CurrentThreadChanged ||
+ pauseSession.PausedReason == PausedReason.EvalComplete;
+ }
+ }
+}
diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj
index a57f66e918..7253edd3b6 100644
--- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj
+++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/AvalonEdit.AddIn.csproj
@@ -1,250 +1,250 @@
-
-
-
- {0162E499-42D0-409B-AA25-EED21F75336B}
- Debug
- AnyCPU
- Library
- ICSharpCode.AvalonEdit.AddIn
- ICSharpCode.AvalonEdit.AddIn
- v4.0
- C:\Users\Daniel\AppData\Roaming\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis
- ..\..\..\..\AddIns\DisplayBindings\AvalonEdit\
- False
- False
- 4
- false
- False
- -Microsoft.Design#CA1014;-Microsoft.Design#CA2210
- v4.0
-
-
-
-
- true
- Full
- False
- True
- DEBUG;TRACE
-
-
- False
- None
- True
- False
- TRACE
-
-
- False
- Auto
- 4194304
- AnyCPU
- 4096
-
-
-
-
-
- 3.0
-
-
- 3.0
-
-
- 3.0
-
-
-
- 3.5
-
-
-
- 3.0
-
-
-
-
-
- 3.5
-
-
- 3.0
-
-
- 3.0
-
-
-
-
-
-
-
-
- Always
-
-
- Configuration\GlobalAssemblyInfo.cs
-
-
-
-
-
-
-
-
-
-
- ChooseEncodingDialog.xaml
- Code
-
-
-
-
-
-
-
-
- DiffControl.xaml
- Code
-
-
-
-
- HiddenDefinitionControl.xaml
- Code
-
-
-
-
-
-
-
-
-
- SortOptionsDialog.xaml
- Code
-
-
-
-
-
-
-
-
-
-
-
- BehaviorOptions.xaml
- Code
-
-
-
-
- GeneralEditorOptions.xaml
- Code
-
-
-
- HighlightingOptions.xaml
- Code
-
-
-
-
-
- TextViewOptions.xaml
- Code
-
-
-
-
-
-
-
-
-
-
- Code
-
-
-
- Code
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- SharpDevelopCompletionWindow.cs
-
-
-
- {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}
- ICSharpCode.AvalonEdit
- False
-
-
- {D68133BD-1E63-496E-9EDE-4FBDBF77B486}
- Mono.Cecil
- False
-
-
- {3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}
- NRefactory
- False
-
-
- {2748AD25-9C63-4E12-877B-4DCE96FBED54}
- ICSharpCode.SharpDevelop
- False
-
-
- {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}
- ICSharpCode.Core
- False
-
-
- {7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}
- ICSharpCode.Core.Presentation
- False
-
-
- {857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}
- ICSharpCode.Core.WinForms
- False
-
-
- {924EE450-603D-49C1-A8E5-4AFAA31CE6F3}
- ICSharpCode.SharpDevelop.Dom
- False
-
-
-
-
-
-
-
-
- SnippetOptionPanel.cs
-
-
- QuickClassBrowser.cs
-
-
- {8035765F-D51F-4A0C-A746-2FD100E19419}
- ICSharpCode.SharpDevelop.Widgets
- False
-
-
-
-
-
+
+
+
+ {0162E499-42D0-409B-AA25-EED21F75336B}
+ Debug
+ AnyCPU
+ Library
+ ICSharpCode.AvalonEdit.AddIn
+ ICSharpCode.AvalonEdit.AddIn
+ v4.0
+ C:\Users\Daniel\AppData\Roaming\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis
+ ..\..\..\..\AddIns\DisplayBindings\AvalonEdit\
+ False
+ False
+ 4
+ false
+ False
+ -Microsoft.Design#CA1014;-Microsoft.Design#CA2210
+ v4.0
+
+
+
+
+ true
+ Full
+ False
+ True
+ DEBUG;TRACE
+
+
+ False
+ None
+ True
+ False
+ TRACE
+
+
+ False
+ Auto
+ 4194304
+ AnyCPU
+ 4096
+
+
+
+
+
+ 3.0
+
+
+ 3.0
+
+
+ 3.0
+
+
+
+ 3.5
+
+
+
+ 3.0
+
+
+
+
+
+ 3.5
+
+
+ 3.0
+
+
+ 3.0
+
+
+
+
+
+
+
+
+ Always
+
+
+ Configuration\GlobalAssemblyInfo.cs
+
+
+
+
+
+
+
+
+
+
+ ChooseEncodingDialog.xaml
+ Code
+
+
+
+
+
+
+
+
+ DiffControl.xaml
+ Code
+
+
+
+
+ HiddenDefinitionControl.xaml
+ Code
+
+
+
+
+
+
+
+
+
+ SortOptionsDialog.xaml
+ Code
+
+
+
+
+
+
+
+
+
+
+
+ BehaviorOptions.xaml
+ Code
+
+
+
+
+ GeneralEditorOptions.xaml
+ Code
+
+
+
+ HighlightingOptions.xaml
+ Code
+
+
+
+
+
+ TextViewOptions.xaml
+ Code
+
+
+
+
+
+
+
+
+
+
+ Code
+
+
+
+ Code
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SharpDevelopCompletionWindow.cs
+
+
+
+ {6C55B776-26D4-4DB3-A6AB-87E783B2F3D1}
+ ICSharpCode.AvalonEdit
+ False
+
+
+ {D68133BD-1E63-496E-9EDE-4FBDBF77B486}
+ Mono.Cecil
+ False
+
+
+ {3A9AE6AA-BC07-4A2F-972C-581E3AE2F195}
+ NRefactory
+ False
+
+
+ {2748AD25-9C63-4E12-877B-4DCE96FBED54}
+ ICSharpCode.SharpDevelop
+ False
+
+
+ {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}
+ ICSharpCode.Core
+ False
+
+
+ {7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}
+ ICSharpCode.Core.Presentation
+ False
+
+
+ {857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}
+ ICSharpCode.Core.WinForms
+ False
+
+
+ {924EE450-603D-49C1-A8E5-4AFAA31CE6F3}
+ ICSharpCode.SharpDevelop.Dom
+ False
+
+
+
+
+
+
+
+
+ SnippetOptionPanel.cs
+
+
+ QuickClassBrowser.cs
+
+
+ {8035765F-D51F-4A0C-A746-2FD100E19419}
+ ICSharpCode.SharpDevelop.Widgets
+ False
+
+
+
+
+
\ No newline at end of file
diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/HiddenDefinition/HiddenDefinitionControl.xaml.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/HiddenDefinition/HiddenDefinitionControl.xaml.cs
index cfe08d924e..f6c1170016 100644
--- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/HiddenDefinition/HiddenDefinitionControl.xaml.cs
+++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/HiddenDefinition/HiddenDefinitionControl.xaml.cs
@@ -1,27 +1,27 @@
-// 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.Media;
-
-using ICSharpCode.AvalonEdit.AddIn.Options;
-
-namespace ICSharpCode.AvalonEdit.AddIn.HiddenDefinition
-{
- public partial class HiddenDefinitionControl : UserControl
- {
- public HiddenDefinitionControl()
- {
- InitializeComponent();
- DefinitionTextBlock.FontFamily = new FontFamily(CodeEditorOptions.Instance.FontFamily);
- DefinitionTextBlock.FontSize = CodeEditorOptions.Instance.FontSize;
- }
-
- public string DefinitionText {
- get { return this.DefinitionTextBlock.Text; }
- set { this.DefinitionTextBlock.Text = value; }
- }
- }
+// 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.Media;
+
+using ICSharpCode.AvalonEdit.AddIn.Options;
+
+namespace ICSharpCode.AvalonEdit.AddIn.HiddenDefinition
+{
+ public partial class HiddenDefinitionControl : UserControl
+ {
+ public HiddenDefinitionControl()
+ {
+ InitializeComponent();
+ DefinitionTextBlock.FontFamily = new FontFamily(CodeEditorOptions.Instance.FontFamily);
+ DefinitionTextBlock.FontSize = CodeEditorOptions.Instance.FontSize;
+ }
+
+ public string DefinitionText {
+ get { return this.DefinitionTextBlock.Text; }
+ set { this.DefinitionTextBlock.Text = value; }
+ }
+ }
}
\ No newline at end of file
diff --git a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/HiddenDefinition/HiddenDefinitionRenderer.cs b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/HiddenDefinition/HiddenDefinitionRenderer.cs
index 31222afb19..879b7b06fc 100644
--- a/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/HiddenDefinition/HiddenDefinitionRenderer.cs
+++ b/src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/HiddenDefinition/HiddenDefinitionRenderer.cs
@@ -1,102 +1,102 @@
-// 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.Primitives;
-using ICSharpCode.Core.Presentation;
-using ICSharpCode.SharpDevelop.Editor;
-using ICSharpCode.SharpDevelop.Gui;
-
-namespace ICSharpCode.AvalonEdit.AddIn.HiddenDefinition
-{
- public class HiddenDefinitionRenderer : IDisposable
- {
- private CodeEditorView editor;
- private ExtendedPopup popup = new ExtendedPopup();
- private HiddenDefinitionControl control;
-
- public HiddenDefinitionRenderer(CodeEditorView editorView)
- {
- this.editor = editorView;
- control = new HiddenDefinitionControl();
- WorkbenchSingleton.Workbench.ActiveContentChanged += WorkbenchSingleton_Workbench_ActiveContentChanged;
- }
-
- public BracketSearchResult BracketSearchResult { get; set; }
-
- public void Dispose()
- {
- WorkbenchSingleton.Workbench.ActiveContentChanged -= WorkbenchSingleton_Workbench_ActiveContentChanged;
- ClosePopup();
- popup = null;
- }
-
- public void ClosePopup()
- {
- if (popup != null && popup.IsOpen)
- popup.IsOpen = false;
- }
-
- public void Show()
- {
- ClosePopup();
-
- if (BracketSearchResult == null) return;
-
- // verify if we have a open bracket
- if (this.editor.Document.GetCharAt(BracketSearchResult.OpeningBracketOffset) != '{')
- return;
-
- var line = GetLineText(BracketSearchResult.OpeningBracketOffset);
- if(line == null) return;
-
- control.DefinitionText = line;
- popup.Child = control;
- popup.HorizontalOffset = 70;
- popup.Placement = PlacementMode.Relative;
- popup.PlacementTarget = editor.TextArea;
- popup.IsOpen = true;
- }
-
- ///
- /// Gets the line text near the offset.
- ///
- /// Offset.
- ///
- private string GetLineText(int offset)
- {
- if (!editor.TextArea.TextView.VisualLinesValid)
- return null;
-
- // get line
- var documentLine = editor.Document.GetLineByOffset(offset);
- string documentText = editor.Document.Text;
- string lineText = string.Empty;
- int off, length;
-
- do {
- if (documentLine == null || documentLine.IsDeleted) return null;
- off = documentLine.Offset;
- length = documentLine.Length;
- lineText = documentText.Substring(off, length).Trim();
-
- documentLine = documentLine.PreviousLine;
- }
- while (lineText == "{" || string.IsNullOrEmpty(lineText) ||
- lineText.StartsWith("//") || lineText.StartsWith("/*") ||
- lineText.StartsWith("*") || lineText.StartsWith("'"));
-
- // check whether the line is visible
- if (editor.TextArea.TextView.VisualLines[0].StartOffset > off) {
- return this.editor.TextArea.TextView.Document.GetText(off, length);
- }
-
- return null;
- }
-
- private void WorkbenchSingleton_Workbench_ActiveContentChanged(object sender, EventArgs e)
- {
- ClosePopup();
- }
- }
+// 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.Primitives;
+using ICSharpCode.Core.Presentation;
+using ICSharpCode.SharpDevelop.Editor;
+using ICSharpCode.SharpDevelop.Gui;
+
+namespace ICSharpCode.AvalonEdit.AddIn.HiddenDefinition
+{
+ public class HiddenDefinitionRenderer : IDisposable
+ {
+ private CodeEditorView editor;
+ private ExtendedPopup popup = new ExtendedPopup();
+ private HiddenDefinitionControl control;
+
+ public HiddenDefinitionRenderer(CodeEditorView editorView)
+ {
+ this.editor = editorView;
+ control = new HiddenDefinitionControl();
+ WorkbenchSingleton.Workbench.ActiveContentChanged += WorkbenchSingleton_Workbench_ActiveContentChanged;
+ }
+
+ public BracketSearchResult BracketSearchResult { get; set; }
+
+ public void Dispose()
+ {
+ WorkbenchSingleton.Workbench.ActiveContentChanged -= WorkbenchSingleton_Workbench_ActiveContentChanged;
+ ClosePopup();
+ popup = null;
+ }
+
+ public void ClosePopup()
+ {
+ if (popup != null && popup.IsOpen)
+ popup.IsOpen = false;
+ }
+
+ public void Show()
+ {
+ ClosePopup();
+
+ if (BracketSearchResult == null) return;
+
+ // verify if we have a open bracket
+ if (this.editor.Document.GetCharAt(BracketSearchResult.OpeningBracketOffset) != '{')
+ return;
+
+ var line = GetLineText(BracketSearchResult.OpeningBracketOffset);
+ if(line == null) return;
+
+ control.DefinitionText = line;
+ popup.Child = control;
+ popup.HorizontalOffset = 70;
+ popup.Placement = PlacementMode.Relative;
+ popup.PlacementTarget = editor.TextArea;
+ popup.IsOpen = true;
+ }
+
+ ///
+ /// Gets the line text near the offset.
+ ///
+ /// Offset.
+ ///
+ private string GetLineText(int offset)
+ {
+ if (!editor.TextArea.TextView.VisualLinesValid)
+ return null;
+
+ // get line
+ var documentLine = editor.Document.GetLineByOffset(offset);
+ string documentText = editor.Document.Text;
+ string lineText = string.Empty;
+ int off, length;
+
+ do {
+ if (documentLine == null || documentLine.IsDeleted) return null;
+ off = documentLine.Offset;
+ length = documentLine.Length;
+ lineText = documentText.Substring(off, length).Trim();
+
+ documentLine = documentLine.PreviousLine;
+ }
+ while (lineText == "{" || string.IsNullOrEmpty(lineText) ||
+ lineText.StartsWith("//") || lineText.StartsWith("/*") ||
+ lineText.StartsWith("*") || lineText.StartsWith("'"));
+
+ // check whether the line is visible
+ if (editor.TextArea.TextView.VisualLines[0].StartOffset > off) {
+ return this.editor.TextArea.TextView.Document.GetText(off, length);
+ }
+
+ return null;
+ }
+
+ private void WorkbenchSingleton_Workbench_ActiveContentChanged(object sender, EventArgs e)
+ {
+ ClosePopup();
+ }
+ }
}
\ No newline at end of file
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/ThumbnailViewPad.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/ThumbnailViewPad.cs
index 18d2fcbacf..13289e6425 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/ThumbnailViewPad.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/Src/ThumbnailViewPad.cs
@@ -1,55 +1,55 @@
-// 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 ICSharpCode.Core;
-using ICSharpCode.SharpDevelop;
-using ICSharpCode.SharpDevelop.Gui;
-using ICSharpCode.WpfDesign.Designer.ThumbnailView;
-
-namespace ICSharpCode.WpfDesign.AddIn
-{
- public class ThumbnailViewPad : AbstractPadContent
- {
- ContentPresenter contentControl = new ContentPresenter();
-
- ThumbnailView thumbnailView = new ThumbnailView();
-
- TextBlock notAvailableTextBlock = new TextBlock {
- Text = StringParser.Parse("${res:ICSharpCode.SharpDevelop.Gui.OutlinePad.NotAvailable}"),
- TextWrapping = TextWrapping.Wrap
- };
-
- public ThumbnailViewPad()
- {
- WorkbenchSingleton.Workbench.ActiveViewContentChanged += WorkbenchActiveViewContentChanged;
- WorkbenchActiveViewContentChanged(null, null);
- }
-
- void WorkbenchActiveViewContentChanged(object sender, EventArgs e)
- {
- WpfViewContent wpfView = WorkbenchSingleton.Workbench.ActiveViewContent as WpfViewContent;
- if (wpfView != null)
- {
- thumbnailView.DesignSurface = wpfView.DesignSurface;
- contentControl.SetContent(thumbnailView);
- }
- else
- {
- contentControl.SetContent(notAvailableTextBlock);
- }
- }
-
- ///
- /// The representing the pad
- ///
- public override object Control {
- get {
- return contentControl;
- }
- }
- }
-}
+// 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 ICSharpCode.Core;
+using ICSharpCode.SharpDevelop;
+using ICSharpCode.SharpDevelop.Gui;
+using ICSharpCode.WpfDesign.Designer.ThumbnailView;
+
+namespace ICSharpCode.WpfDesign.AddIn
+{
+ public class ThumbnailViewPad : AbstractPadContent
+ {
+ ContentPresenter contentControl = new ContentPresenter();
+
+ ThumbnailView thumbnailView = new ThumbnailView();
+
+ TextBlock notAvailableTextBlock = new TextBlock {
+ Text = StringParser.Parse("${res:ICSharpCode.SharpDevelop.Gui.OutlinePad.NotAvailable}"),
+ TextWrapping = TextWrapping.Wrap
+ };
+
+ public ThumbnailViewPad()
+ {
+ WorkbenchSingleton.Workbench.ActiveViewContentChanged += WorkbenchActiveViewContentChanged;
+ WorkbenchActiveViewContentChanged(null, null);
+ }
+
+ void WorkbenchActiveViewContentChanged(object sender, EventArgs e)
+ {
+ WpfViewContent wpfView = WorkbenchSingleton.Workbench.ActiveViewContent as WpfViewContent;
+ if (wpfView != null)
+ {
+ thumbnailView.DesignSurface = wpfView.DesignSurface;
+ contentControl.SetContent(thumbnailView);
+ }
+ else
+ {
+ contentControl.SetContent(notAvailableTextBlock);
+ }
+ }
+
+ ///
+ /// The representing the pad
+ ///
+ public override object Control {
+ get {
+ return contentControl;
+ }
+ }
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfDesign.AddIn.csproj b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfDesign.AddIn.csproj
index eeaea66008..fa65574b6d 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfDesign.AddIn.csproj
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.AddIn/WpfDesign.AddIn.csproj
@@ -1,158 +1,158 @@
-
-
-
- {9A9D6FD4-6A2E-455D-ACC3-DDA775FE9865}
- Debug
- AnyCPU
- Library
- ICSharpCode.WpfDesign.AddIn
- ICSharpCode.WpfDesign.AddIn
- ..\..\..\..\..\AddIns\DisplayBindings\WpfDesign\
- False
- False
- 4
- false
- v4.0
-
-
-
-
- true
- Full
- True
- DEBUG;TRACE
- False
-
-
- False
- None
- False
- TRACE
-
-
- False
- Auto
- 4194304
- AnyCPU
- 4096
-
-
-
-
-
-
-
- 3.5
-
-
-
-
-
- 4.0
-
-
-
-
-
-
-
- Always
-
-
- Configuration\GlobalAssemblyInfo.cs
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ChooseImageDialog.xaml
- Code
-
-
- ImageSourceEditor.xaml
- Code
-
-
-
- ObjectEditor.xaml
-
-
-
-
-
-
-
- WpfDocumentError.xaml
- Code
-
-
-
-
-
-
-
-
- {2748AD25-9C63-4E12-877B-4DCE96FBED54}
- ICSharpCode.SharpDevelop
- False
-
-
- {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}
- ICSharpCode.Core
- False
-
-
- {7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}
- ICSharpCode.Core.Presentation
- False
-
-
- {857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}
- ICSharpCode.Core.WinForms
- False
-
-
- {924EE450-603D-49C1-A8E5-4AFAA31CE6F3}
- ICSharpCode.SharpDevelop.Dom
- False
-
-
- {8035765F-D51F-4A0C-A746-2FD100E19419}
- ICSharpCode.SharpDevelop.Widgets
- False
-
-
- {7D7E92DF-ACEB-4B69-92C8-8AC7A703CD57}
- FormsDesigner
- False
-
-
- {78CC29AC-CC79-4355-B1F2-97936DF198AC}
- WpfDesign.Designer
- False
-
-
- {88DA149F-21B2-48AB-82C4-28FB6BDFD783}
- WpfDesign.XamlDom
- False
-
-
- {66A378A1-E9F4-4AD5-8946-D0EC06C2902F}
- WpfDesign
- False
-
-
-
-
-
-
+
+
+
+ {9A9D6FD4-6A2E-455D-ACC3-DDA775FE9865}
+ Debug
+ AnyCPU
+ Library
+ ICSharpCode.WpfDesign.AddIn
+ ICSharpCode.WpfDesign.AddIn
+ ..\..\..\..\..\AddIns\DisplayBindings\WpfDesign\
+ False
+ False
+ 4
+ false
+ v4.0
+
+
+
+
+ true
+ Full
+ True
+ DEBUG;TRACE
+ False
+
+
+ False
+ None
+ False
+ TRACE
+
+
+ False
+ Auto
+ 4194304
+ AnyCPU
+ 4096
+
+
+
+
+
+
+
+ 3.5
+
+
+
+
+
+ 4.0
+
+
+
+
+
+
+
+ Always
+
+
+ Configuration\GlobalAssemblyInfo.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ChooseImageDialog.xaml
+ Code
+
+
+ ImageSourceEditor.xaml
+ Code
+
+
+
+ ObjectEditor.xaml
+
+
+
+
+
+
+
+ WpfDocumentError.xaml
+ Code
+
+
+
+
+
+
+
+
+ {2748AD25-9C63-4E12-877B-4DCE96FBED54}
+ ICSharpCode.SharpDevelop
+ False
+
+
+ {35CEF10F-2D4C-45F2-9DD1-161E0FEC583C}
+ ICSharpCode.Core
+ False
+
+
+ {7E4A7172-7FF5-48D0-B719-7CD959DD1AC9}
+ ICSharpCode.Core.Presentation
+ False
+
+
+ {857CA1A3-FC88-4BE0-AB6A-D1EE772AB288}
+ ICSharpCode.Core.WinForms
+ False
+
+
+ {924EE450-603D-49C1-A8E5-4AFAA31CE6F3}
+ ICSharpCode.SharpDevelop.Dom
+ False
+
+
+ {8035765F-D51F-4A0C-A746-2FD100E19419}
+ ICSharpCode.SharpDevelop.Widgets
+ False
+
+
+ {7D7E92DF-ACEB-4B69-92C8-8AC7A703CD57}
+ FormsDesigner
+ False
+
+
+ {78CC29AC-CC79-4355-B1F2-97936DF198AC}
+ WpfDesign.Designer
+ False
+
+
+ {88DA149F-21B2-48AB-82C4-28FB6BDFD783}
+ WpfDesign.XamlDom
+ False
+
+
+ {66A378A1-E9F4-4AD5-8946-D0EC06C2902F}
+ WpfDesign
+ False
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/PropertyGrid.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/PropertyGrid.cs
index ed35981f07..ad077f6373 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/PropertyGrid.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.Designer/Project/PropertyGrid/PropertyGrid.cs
@@ -1,328 +1,328 @@
-// 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.Linq;
-using System.Text;
-using System.ComponentModel;
-using System.Collections.ObjectModel;
-using System.Threading;
-using System.Globalization;
-using ICSharpCode.WpfDesign.PropertyGrid;
-using System.Windows.Threading;
-using System.Diagnostics;
-using System.Windows.Media;
-using System.Windows;
-
-namespace ICSharpCode.WpfDesign.Designer.PropertyGrid
-{
- public class PropertyGrid : INotifyPropertyChanged
- {
- public PropertyGrid()
- {
- Categories = new CategoriesCollection();
- Categories.Add(specialCategory);
- Categories.Add(popularCategory);
- Categories.Add(otherCategory);
- Categories.Add(attachedCategory);
-
- Events = new PropertyNodeCollection();
- }
-
- Category specialCategory = new Category("Special");
- Category popularCategory = new Category("Popular");
- Category otherCategory = new Category("Other");
- Category attachedCategory = new Category("Attached");
-
- Dictionary nodeFromDescriptor = new Dictionary();
-
- public CategoriesCollection Categories { get; private set; }
- public PropertyNodeCollection Events { get; private set; }
-
- private PropertyGridGroupMode _groupMode;
-
- public PropertyGridGroupMode GroupMode
- {
- get { return _groupMode; }
- set
- {
- if (_groupMode != value)
- {
- _groupMode = value;
-
- RaisePropertyChanged("GroupMode");
-
- Reload();
- }
- }
- }
-
- PropertyGridTab currentTab;
-
- public PropertyGridTab CurrentTab {
- get {
- return currentTab;
- }
- set {
- currentTab = value;
- RaisePropertyChanged("CurrentTab");
- RaisePropertyChanged("NameBackground");
- }
- }
-
- string filter;
-
- public string Filter {
- get {
- return filter;
- }
- set {
- filter = value;
- Reload();
- RaisePropertyChanged("Filter");
- }
- }
-
- DesignItem singleItem;
-
- public DesignItem SingleItem {
- get {
- return singleItem;
- }
- private set {
- if (singleItem != null) {
- singleItem.NameChanged -= singleItem_NameChanged;
- }
- singleItem = value;
- if (singleItem != null) {
- singleItem.NameChanged += singleItem_NameChanged;
- }
- RaisePropertyChanged("SingleItem");
- RaisePropertyChanged("Name");
- RaisePropertyChanged("IsNameEnabled");
- IsNameCorrect = true;
- }
- }
-
- void singleItem_NameChanged(object sender, EventArgs e)
- {
- RaisePropertyChanged("Name");
- }
-
- public string OldName {
- get; private set;
- }
-
- public string Name {
- get {
- if (SingleItem != null) {
- return SingleItem.Name;
- }
- return null;
- }
- set {
- if (SingleItem != null) {
- try {
- if (string.IsNullOrEmpty(value)) {
- OldName = null;
- SingleItem.Name = null;
- } else {
- OldName = SingleItem.Name;
- SingleItem.Name = value;
- }
- IsNameCorrect = true;
- } catch {
- IsNameCorrect = false;
- }
- RaisePropertyChanged("Name");
- }
- }
- }
-
- bool isNameCorrect = true;
-
- public bool IsNameCorrect {
- get {
- return isNameCorrect;
- }
- set {
- isNameCorrect = value;
- RaisePropertyChanged("IsNameCorrect");
- }
- }
-
- public bool IsNameEnabled {
- get {
- return SingleItem != null;
- }
- }
-
- IEnumerable selectedItems;
-
- public IEnumerable SelectedItems {
- get {
- return selectedItems;
- }
- set {
- selectedItems = value;
- RaisePropertyChanged("SelectedItems");
- Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new Action(
- delegate {
- Reload();
- }));
- }
- }
-
- public void ClearFilter()
- {
- Filter = null;
- }
-
- void Reload()
- {
- Clear();
-
- if (SelectedItems == null || SelectedItems.Count() == 0) return;
- if (SelectedItems.Count() == 1) SingleItem = SelectedItems.First();
-
- foreach (var md in GetDescriptors()) {
- if (PassesFilter(md.Name))
- AddNode(md);
- }
- }
-
- void Clear()
- {
- foreach (var c in Categories) {
- c.IsVisible = false;
- foreach (var p in c.Properties) {
- p.IsVisible = false;
- }
- }
-
- foreach (var e in Events) {
- e.IsVisible = false;
- }
-
- SingleItem = null;
- }
-
- List GetDescriptors()
- {
- List list = new List();
-
- if (SelectedItems.Count() == 1) {
- foreach (MemberDescriptor d in TypeHelper.GetAvailableProperties(SingleItem.Component)) {
- list.Add(d);
- }
- foreach (MemberDescriptor d in TypeHelper.GetAvailableEvents(SingleItem.ComponentType)) {
- list.Add(d);
- }
- } else {
- foreach (MemberDescriptor d in TypeHelper.GetCommonAvailableProperties(SelectedItems.Select(t => t.Component))) {
- list.Add(d);
- }
- }
-
- return list;
- }
-
- bool PassesFilter(string name)
- {
- if (string.IsNullOrEmpty(Filter)) return true;
- for (int i = 0; i < name.Length; i++) {
- if (i == 0 || char.IsUpper(name[i])) {
- if (string.Compare(name, i, Filter, 0, Filter.Length, true) == 0) {
- return true;
- }
- }
- }
- return false;
- }
-
- void AddNode(MemberDescriptor md)
- {
- var designProperties = SelectedItems.Select(item => item.Properties.GetProperty(md)).ToArray();
- if (!Metadata.IsBrowsable(designProperties[0])) return;
-
- PropertyNode node;
- if (nodeFromDescriptor.TryGetValue(md, out node)) {
- node.Load(designProperties);
- } else {
- node = new PropertyNode();
- node.Load(designProperties);
- if (node.IsEvent) {
- Events.AddSorted(node);
- } else {
- var cat = PickCategory(node);
- cat.Properties.AddSorted(node);
- node.Category = cat;
- }
- nodeFromDescriptor[md] = node;
- }
- node.IsVisible = true;
- if (node.Category != null)
- node.Category.IsVisible = true;
- }
-
- Category PickCategory(PropertyNode node)
- {
- if (Metadata.IsPopularProperty(node.FirstProperty)) return popularCategory;
- if (node.FirstProperty.IsAttachedDependencyProperty()) return attachedCategory;
- var typeName = node.FirstProperty.DeclaringType.FullName;
- if (typeName.StartsWith("System.Windows.") || typeName.StartsWith("ICSharpCode.WpfDesign.Designer.Controls."))
- return otherCategory;
- return specialCategory;
- }
-
- #region INotifyPropertyChanged Members
-
- public event PropertyChangedEventHandler PropertyChanged;
-
- void RaisePropertyChanged(string name)
- {
- if (PropertyChanged != null) {
- PropertyChanged(this, new PropertyChangedEventArgs(name));
- }
- }
-
- #endregion
-
- //class CategoryNameComparer : IComparer
- //{
- // public static CategoryNameComparer Instance = new CategoryNameComparer();
-
- // public int Compare(string x, string y)
- // {
- // int i1 = Array.IndexOf(Metadata.CategoryOrder, x);
- // if (i1 == -1) i1 = int.MaxValue;
- // int i2 = Array.IndexOf(Metadata.CategoryOrder, y);
- // if (i2 == -1) i2 = int.MaxValue;
- // if (i1 == i2) return x.CompareTo(y);
- // return i1.CompareTo(i2);
- // }
- //}
- }
-
- public class CategoriesCollection : SortedObservableCollection
- {
- public CategoriesCollection()
- : base(n => n.Name)
- {
- }
- }
-
- public enum PropertyGridGroupMode
- {
- GroupByPopularCategorys,
- GroupByCategorys,
- Ungrouped,
- }
-
- public enum PropertyGridTab
- {
- Properties,
- Events
- }
-}
+// 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.Linq;
+using System.Text;
+using System.ComponentModel;
+using System.Collections.ObjectModel;
+using System.Threading;
+using System.Globalization;
+using ICSharpCode.WpfDesign.PropertyGrid;
+using System.Windows.Threading;
+using System.Diagnostics;
+using System.Windows.Media;
+using System.Windows;
+
+namespace ICSharpCode.WpfDesign.Designer.PropertyGrid
+{
+ public class PropertyGrid : INotifyPropertyChanged
+ {
+ public PropertyGrid()
+ {
+ Categories = new CategoriesCollection();
+ Categories.Add(specialCategory);
+ Categories.Add(popularCategory);
+ Categories.Add(otherCategory);
+ Categories.Add(attachedCategory);
+
+ Events = new PropertyNodeCollection();
+ }
+
+ Category specialCategory = new Category("Special");
+ Category popularCategory = new Category("Popular");
+ Category otherCategory = new Category("Other");
+ Category attachedCategory = new Category("Attached");
+
+ Dictionary nodeFromDescriptor = new Dictionary();
+
+ public CategoriesCollection Categories { get; private set; }
+ public PropertyNodeCollection Events { get; private set; }
+
+ private PropertyGridGroupMode _groupMode;
+
+ public PropertyGridGroupMode GroupMode
+ {
+ get { return _groupMode; }
+ set
+ {
+ if (_groupMode != value)
+ {
+ _groupMode = value;
+
+ RaisePropertyChanged("GroupMode");
+
+ Reload();
+ }
+ }
+ }
+
+ PropertyGridTab currentTab;
+
+ public PropertyGridTab CurrentTab {
+ get {
+ return currentTab;
+ }
+ set {
+ currentTab = value;
+ RaisePropertyChanged("CurrentTab");
+ RaisePropertyChanged("NameBackground");
+ }
+ }
+
+ string filter;
+
+ public string Filter {
+ get {
+ return filter;
+ }
+ set {
+ filter = value;
+ Reload();
+ RaisePropertyChanged("Filter");
+ }
+ }
+
+ DesignItem singleItem;
+
+ public DesignItem SingleItem {
+ get {
+ return singleItem;
+ }
+ private set {
+ if (singleItem != null) {
+ singleItem.NameChanged -= singleItem_NameChanged;
+ }
+ singleItem = value;
+ if (singleItem != null) {
+ singleItem.NameChanged += singleItem_NameChanged;
+ }
+ RaisePropertyChanged("SingleItem");
+ RaisePropertyChanged("Name");
+ RaisePropertyChanged("IsNameEnabled");
+ IsNameCorrect = true;
+ }
+ }
+
+ void singleItem_NameChanged(object sender, EventArgs e)
+ {
+ RaisePropertyChanged("Name");
+ }
+
+ public string OldName {
+ get; private set;
+ }
+
+ public string Name {
+ get {
+ if (SingleItem != null) {
+ return SingleItem.Name;
+ }
+ return null;
+ }
+ set {
+ if (SingleItem != null) {
+ try {
+ if (string.IsNullOrEmpty(value)) {
+ OldName = null;
+ SingleItem.Name = null;
+ } else {
+ OldName = SingleItem.Name;
+ SingleItem.Name = value;
+ }
+ IsNameCorrect = true;
+ } catch {
+ IsNameCorrect = false;
+ }
+ RaisePropertyChanged("Name");
+ }
+ }
+ }
+
+ bool isNameCorrect = true;
+
+ public bool IsNameCorrect {
+ get {
+ return isNameCorrect;
+ }
+ set {
+ isNameCorrect = value;
+ RaisePropertyChanged("IsNameCorrect");
+ }
+ }
+
+ public bool IsNameEnabled {
+ get {
+ return SingleItem != null;
+ }
+ }
+
+ IEnumerable selectedItems;
+
+ public IEnumerable SelectedItems {
+ get {
+ return selectedItems;
+ }
+ set {
+ selectedItems = value;
+ RaisePropertyChanged("SelectedItems");
+ Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new Action(
+ delegate {
+ Reload();
+ }));
+ }
+ }
+
+ public void ClearFilter()
+ {
+ Filter = null;
+ }
+
+ void Reload()
+ {
+ Clear();
+
+ if (SelectedItems == null || SelectedItems.Count() == 0) return;
+ if (SelectedItems.Count() == 1) SingleItem = SelectedItems.First();
+
+ foreach (var md in GetDescriptors()) {
+ if (PassesFilter(md.Name))
+ AddNode(md);
+ }
+ }
+
+ void Clear()
+ {
+ foreach (var c in Categories) {
+ c.IsVisible = false;
+ foreach (var p in c.Properties) {
+ p.IsVisible = false;
+ }
+ }
+
+ foreach (var e in Events) {
+ e.IsVisible = false;
+ }
+
+ SingleItem = null;
+ }
+
+ List GetDescriptors()
+ {
+ List list = new List();
+
+ if (SelectedItems.Count() == 1) {
+ foreach (MemberDescriptor d in TypeHelper.GetAvailableProperties(SingleItem.Component)) {
+ list.Add(d);
+ }
+ foreach (MemberDescriptor d in TypeHelper.GetAvailableEvents(SingleItem.ComponentType)) {
+ list.Add(d);
+ }
+ } else {
+ foreach (MemberDescriptor d in TypeHelper.GetCommonAvailableProperties(SelectedItems.Select(t => t.Component))) {
+ list.Add(d);
+ }
+ }
+
+ return list;
+ }
+
+ bool PassesFilter(string name)
+ {
+ if (string.IsNullOrEmpty(Filter)) return true;
+ for (int i = 0; i < name.Length; i++) {
+ if (i == 0 || char.IsUpper(name[i])) {
+ if (string.Compare(name, i, Filter, 0, Filter.Length, true) == 0) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ void AddNode(MemberDescriptor md)
+ {
+ var designProperties = SelectedItems.Select(item => item.Properties.GetProperty(md)).ToArray();
+ if (!Metadata.IsBrowsable(designProperties[0])) return;
+
+ PropertyNode node;
+ if (nodeFromDescriptor.TryGetValue(md, out node)) {
+ node.Load(designProperties);
+ } else {
+ node = new PropertyNode();
+ node.Load(designProperties);
+ if (node.IsEvent) {
+ Events.AddSorted(node);
+ } else {
+ var cat = PickCategory(node);
+ cat.Properties.AddSorted(node);
+ node.Category = cat;
+ }
+ nodeFromDescriptor[md] = node;
+ }
+ node.IsVisible = true;
+ if (node.Category != null)
+ node.Category.IsVisible = true;
+ }
+
+ Category PickCategory(PropertyNode node)
+ {
+ if (Metadata.IsPopularProperty(node.FirstProperty)) return popularCategory;
+ if (node.FirstProperty.IsAttachedDependencyProperty()) return attachedCategory;
+ var typeName = node.FirstProperty.DeclaringType.FullName;
+ if (typeName.StartsWith("System.Windows.") || typeName.StartsWith("ICSharpCode.WpfDesign.Designer.Controls."))
+ return otherCategory;
+ return specialCategory;
+ }
+
+ #region INotifyPropertyChanged Members
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ void RaisePropertyChanged(string name)
+ {
+ if (PropertyChanged != null) {
+ PropertyChanged(this, new PropertyChangedEventArgs(name));
+ }
+ }
+
+ #endregion
+
+ //class CategoryNameComparer : IComparer
+ //{
+ // public static CategoryNameComparer Instance = new CategoryNameComparer();
+
+ // public int Compare(string x, string y)
+ // {
+ // int i1 = Array.IndexOf(Metadata.CategoryOrder, x);
+ // if (i1 == -1) i1 = int.MaxValue;
+ // int i2 = Array.IndexOf(Metadata.CategoryOrder, y);
+ // if (i2 == -1) i2 = int.MaxValue;
+ // if (i1 == i2) return x.CompareTo(y);
+ // return i1.CompareTo(i2);
+ // }
+ //}
+ }
+
+ public class CategoriesCollection : SortedObservableCollection
+ {
+ public CategoriesCollection()
+ : base(n => n.Name)
+ {
+ }
+ }
+
+ public enum PropertyGridGroupMode
+ {
+ GroupByPopularCategorys,
+ GroupByCategorys,
+ Ungrouped,
+ }
+
+ public enum PropertyGridTab
+ {
+ Properties,
+ Events
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/NameScopeHelper.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/NameScopeHelper.cs
index d77f74961e..990b6079b6 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/NameScopeHelper.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/NameScopeHelper.cs
@@ -1,79 +1,79 @@
-// 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.Diagnostics;
-using System.Windows;
-using System.Windows.Markup;
-
-namespace ICSharpCode.WpfDesign.XamlDom
-{
- ///
- /// Static methods to help with operations on Xaml elements.
- ///
- public static class NameScopeHelper
- {
- ///
- /// Finds the XAML namescope for the specified object and uses it to unregister the old name and then register the new name.
- ///
- /// The object where the name was changed.
- /// The old name.
- /// The new name.
- internal static void NameChanged(XamlObject namedObject, string oldName, string newName)
- {
- var obj = namedObject;
- while (obj != null) {
- var nameScope = GetNameScopeFromObject(obj.Instance);
- if (nameScope != null) {
- if (oldName != null) {
- try {
- nameScope.UnregisterName(oldName);
- } catch (Exception x) {
- Debug.WriteLine(x.Message);
- }
- }
- if (newName != null) {
- nameScope.RegisterName(newName, namedObject.Instance);
-
- try{
- var prp = namedObject.ElementType.GetProperty(namedObject.RuntimeNameProperty);
- if (prp != null)
- prp.SetValue(namedObject.Instance, newName, null);
- } catch (Exception x) {
- Debug.WriteLine(x.Message);
- }
- }
- break;
- }
- obj = obj.ParentObject;
- }
- }
-
- ///
- /// Gets the XAML namescope for the specified object.
- ///
- /// The object to get the XAML namescope for.
- /// A XAML namescope, as an instance.
- public static INameScope GetNameScopeFromObject(object obj)
- {
- var nameScope = obj as INameScope;
- if (nameScope == null) {
- var depObj = obj as DependencyObject;
- if (depObj != null)
- nameScope = NameScope.GetNameScope(depObj);
- }
-
- return nameScope;
- }
-
- ///
- /// Clears the if the object is a .
- ///
- /// The object to clear the on.
- public static void ClearNameScopeProperty(object obj)
- {
- var depObj = obj as DependencyObject;
- if (depObj != null)
- depObj.ClearValue(NameScope.NameScopeProperty);
- }
- }
-}
+// 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.Diagnostics;
+using System.Windows;
+using System.Windows.Markup;
+
+namespace ICSharpCode.WpfDesign.XamlDom
+{
+ ///
+ /// Static methods to help with operations on Xaml elements.
+ ///
+ public static class NameScopeHelper
+ {
+ ///
+ /// Finds the XAML namescope for the specified object and uses it to unregister the old name and then register the new name.
+ ///
+ /// The object where the name was changed.
+ /// The old name.
+ /// The new name.
+ internal static void NameChanged(XamlObject namedObject, string oldName, string newName)
+ {
+ var obj = namedObject;
+ while (obj != null) {
+ var nameScope = GetNameScopeFromObject(obj.Instance);
+ if (nameScope != null) {
+ if (oldName != null) {
+ try {
+ nameScope.UnregisterName(oldName);
+ } catch (Exception x) {
+ Debug.WriteLine(x.Message);
+ }
+ }
+ if (newName != null) {
+ nameScope.RegisterName(newName, namedObject.Instance);
+
+ try{
+ var prp = namedObject.ElementType.GetProperty(namedObject.RuntimeNameProperty);
+ if (prp != null)
+ prp.SetValue(namedObject.Instance, newName, null);
+ } catch (Exception x) {
+ Debug.WriteLine(x.Message);
+ }
+ }
+ break;
+ }
+ obj = obj.ParentObject;
+ }
+ }
+
+ ///
+ /// Gets the XAML namescope for the specified object.
+ ///
+ /// The object to get the XAML namescope for.
+ /// A XAML namescope, as an instance.
+ public static INameScope GetNameScopeFromObject(object obj)
+ {
+ var nameScope = obj as INameScope;
+ if (nameScope == null) {
+ var depObj = obj as DependencyObject;
+ if (depObj != null)
+ nameScope = NameScope.GetNameScope(depObj);
+ }
+
+ return nameScope;
+ }
+
+ ///
+ /// Clears the if the object is a .
+ ///
+ /// The object to clear the on.
+ public static void ClearNameScopeProperty(object obj)
+ {
+ var depObj = obj as DependencyObject;
+ if (depObj != null)
+ depObj.ClearValue(NameScope.NameScopeProperty);
+ }
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs
index bf56fb5ec2..e7daa9f21d 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign.XamlDom/Project/XamlProperty.cs
@@ -1,491 +1,491 @@
-// 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.Diagnostics;
-using System.Linq;
-using System.Text;
-using System.Xml;
-using System.Windows;
-using System.Windows.Markup;
-
-namespace ICSharpCode.WpfDesign.XamlDom
-{
- ///
- /// Describes a property on a .
- ///
- [DebuggerDisplay("XamlProperty: {PropertyName}")]
- public sealed class XamlProperty
- {
- XamlObject parentObject;
- internal readonly XamlPropertyInfo propertyInfo;
- XamlPropertyValue propertyValue;
-
- CollectionElementsCollection collectionElements;
- bool isCollection;
- bool isResources;
-
- static readonly IList emptyCollectionElementsArray = new XamlPropertyValue[0];
-
- // for use by parser only
- internal XamlProperty(XamlObject parentObject, XamlPropertyInfo propertyInfo, XamlPropertyValue propertyValue)
- : this(parentObject, propertyInfo)
- {
- PossiblyNameChanged(null, propertyValue);
-
- this.propertyValue = propertyValue;
- if (propertyValue != null) {
- propertyValue.ParentProperty = this;
- }
-
- UpdateValueOnInstance();
- }
-
- internal XamlProperty(XamlObject parentObject, XamlPropertyInfo propertyInfo)
- {
- this.parentObject = parentObject;
- this.propertyInfo = propertyInfo;
-
- if (propertyInfo.IsCollection) {
- isCollection = true;
- collectionElements = new CollectionElementsCollection(this);
-
- if (propertyInfo.Name.Equals(XamlConstants.ResourcesPropertyName, StringComparison.Ordinal) &&
- propertyInfo.ReturnType == typeof(ResourceDictionary)) {
- isResources = true;
- }
- }
- }
-
- ///
- /// Gets the parent object for which this property was declared.
- ///
- public XamlObject ParentObject {
- get { return parentObject; }
- }
-
- ///
- /// Gets the property name.
- ///
- public string PropertyName {
- get { return propertyInfo.Name; }
- }
-
- ///
- /// Gets the type the property is declared on.
- ///
- public Type PropertyTargetType {
- get { return propertyInfo.TargetType; }
- }
-
- ///
- /// Gets if this property is an attached property.
- ///
- public bool IsAttached {
- get { return propertyInfo.IsAttached; }
- }
-
- ///
- /// Gets if this property is an event.
- ///
- public bool IsEvent {
- get { return propertyInfo.IsEvent; }
- }
-
- ///
- /// Gets the return type of the property.
- ///
- public Type ReturnType {
- get { return propertyInfo.ReturnType; }
- }
-
- ///
- /// Gets the type converter used to convert property values to/from string.
- ///
- public TypeConverter TypeConverter {
- get { return propertyInfo.TypeConverter; }
- }
-
- ///
- /// Gets the category of the property.
- ///
- public string Category {
- get { return propertyInfo.Category; }
- }
-
- ///
- /// Gets the value of the property. Can be null if the property is a collection property.
- ///
- public XamlPropertyValue PropertyValue {
- get { return propertyValue; }
- set { SetPropertyValue(value); }
- }
-
- ///
- /// Gets if the property represents the FrameworkElement.Resources property that holds a locally-defined resource dictionary.
- ///
- public bool IsResources {
- get { return isResources; }
- }
-
- ///
- /// Gets if the property is a collection property.
- ///
- public bool IsCollection {
- get { return isCollection; }
- }
-
- ///
- /// Gets the collection elements of the property. Is empty if the property is not a collection.
- ///
- public IList CollectionElements {
- get { return collectionElements ?? emptyCollectionElementsArray; }
- }
-
- ///
- /// Gets if the property is set.
- ///
- public bool IsSet {
- get { return propertyValue != null ||
- _propertyElement != null; // collection
- }
- }
-
- ///
- /// Occurs when the value of the IsSet property has changed.
- ///
- public event EventHandler IsSetChanged;
-
- ///
- /// Occurs when the value of the property has changed.
- ///
- public event EventHandler ValueChanged;
-
- ///
- /// Occurs when MarkupExtension evaluated PropertyValue dosn't changed but ValueOnInstance does.
- ///
- public event EventHandler ValueOnInstanceChanged;
-
- void SetPropertyValue(XamlPropertyValue value)
- {
- // Binding...
- //if (IsCollection) {
- // throw new InvalidOperationException("Cannot set the value of collection properties.");
- //}
-
- bool wasSet = this.IsSet;
-
- PossiblyNameChanged(propertyValue, value);
-
- //reset expression
- var xamlObject = propertyValue as XamlObject;
- if (xamlObject != null && xamlObject.IsMarkupExtension)
- propertyInfo.ResetValue(parentObject.Instance);
-
- ResetInternal();
-
- propertyValue = value;
- propertyValue.ParentProperty = this;
- propertyValue.AddNodeTo(this);
- UpdateValueOnInstance();
-
- ParentObject.OnPropertyChanged(this);
-
- if (!wasSet) {
- if (IsSetChanged != null) {
- IsSetChanged(this, EventArgs.Empty);
- }
- }
-
- if (ValueChanged != null) {
- ValueChanged(this, EventArgs.Empty);
- }
- }
-
- internal void UpdateValueOnInstance()
- {
- if (PropertyValue != null) {
- try {
- ValueOnInstance = PropertyValue.GetValueFor(propertyInfo);
- }
- catch {
- Debug.WriteLine("UpdateValueOnInstance() failed");
- }
- }
- }
-
- ///
- /// Resets the properties value.
- ///
- public void Reset()
- {
- if (IsSet) {
-
- propertyInfo.ResetValue(parentObject.Instance);
- ResetInternal();
-
- ParentObject.OnPropertyChanged(this);
-
- if (IsSetChanged != null) {
- IsSetChanged(this, EventArgs.Empty);
- }
- if (ValueChanged != null) {
- ValueChanged(this, EventArgs.Empty);
- }
- }
- }
-
- void ResetInternal()
- {
- if (propertyValue != null) {
- propertyValue.RemoveNodeFromParent();
- propertyValue.ParentProperty = null;
- propertyValue = null;
- }
- if (_propertyElement != null) {
- _propertyElement.ParentNode.RemoveChild(_propertyElement);
- _propertyElement = null;
- }
- }
-
- XmlElement _propertyElement;
-
- internal void ParserSetPropertyElement(XmlElement propertyElement)
- {
- XmlElement oldPropertyElement = _propertyElement;
- if (oldPropertyElement == propertyElement) return;
-
- _propertyElement = propertyElement;
-
- if (oldPropertyElement != null && IsCollection) {
- Debug.WriteLine("Property element for " + this.PropertyName + " already exists, merging..");
- foreach (XamlPropertyValue val in this.collectionElements) {
- val.RemoveNodeFromParent();
- val.AddNodeTo(this);
- }
- oldPropertyElement.ParentNode.RemoveChild(oldPropertyElement);
- }
- }
-
- bool IsFirstChildResources(XamlObject obj)
- {
- return obj.XmlElement.FirstChild != null &&
- obj.XmlElement.FirstChild.Name.EndsWith("." + XamlConstants.ResourcesPropertyName) &&
- obj.Properties.Where((prop) => prop.IsResources).FirstOrDefault() != null;
- }
-
- XmlElement CreatePropertyElement()
- {
- string ns = parentObject.OwnerDocument.GetNamespaceFor(parentObject.ElementType);
- return parentObject.OwnerDocument.XmlDocument.CreateElement(
- parentObject.OwnerDocument.GetPrefixForNamespace(ns),
- parentObject.ElementType.Name + "." + this.PropertyName,
- ns
- );
- }
-
- internal void AddChildNodeToProperty(XmlNode newChildNode)
- {
- if (this.IsCollection) {
- // this is the default collection
- InsertNodeInCollection(newChildNode, collectionElements.Count);
- return;
- }
- if (_propertyElement == null) {
- if (PropertyName == parentObject.ContentPropertyName) {
- if (IsFirstChildResources(parentObject)) {
- // Resources element should always be first
- parentObject.XmlElement.InsertAfter(newChildNode, parentObject.XmlElement.FirstChild);
- }
- else
- parentObject.XmlElement.InsertBefore(newChildNode, parentObject.XmlElement.FirstChild);
- return;
- }
- _propertyElement = CreatePropertyElement();
-
- if (IsFirstChildResources(parentObject)) {
- // Resources element should always be first
- parentObject.XmlElement.InsertAfter(_propertyElement, parentObject.XmlElement.FirstChild);
- }
- else
- parentObject.XmlElement.InsertBefore(_propertyElement, parentObject.XmlElement.FirstChild);
- }
- _propertyElement.AppendChild(newChildNode);
- }
-
- internal void InsertNodeInCollection(XmlNode newChildNode, int index)
- {
- Debug.Assert(index >= 0 && index <= collectionElements.Count);
- XmlElement collection = _propertyElement;
- if (collection == null) {
- if (collectionElements.Count == 0 && this.PropertyName != this.ParentObject.ContentPropertyName) {
- // we have to create the collection element
- _propertyElement = CreatePropertyElement();
-
- if (this.IsResources) {
- parentObject.XmlElement.PrependChild(_propertyElement);
- } else {
- parentObject.XmlElement.AppendChild(_propertyElement);
- }
-
- collection = _propertyElement;
- } else {
- // this is the default collection
- collection = parentObject.XmlElement;
- }
- }
- if (collectionElements.Count == 0) {
- // collection is empty -> we may insert anywhere
- collection.AppendChild(newChildNode);
- } else if (index == collectionElements.Count) {
- // insert after last element in collection
- collection.InsertAfter(newChildNode, collectionElements[collectionElements.Count - 1].GetNodeForCollection());
- } else {
- // insert before specified index
- collection.InsertBefore(newChildNode, collectionElements[index].GetNodeForCollection());
- }
- }
-
- internal XmlAttribute SetAttribute(string value)
- {
- string name;
- var element = ParentObject.XmlElement;
-
- if (IsAttached)
- {
- if (PropertyTargetType == typeof (DesignTimeProperties) || PropertyTargetType == typeof (MarkupCompatibilityProperties))
- name = PropertyName;
- else
- name = PropertyTargetType.Name + "." + PropertyName;
-
- string ns = ParentObject.OwnerDocument.GetNamespaceFor(PropertyTargetType);
- string prefix = element.GetPrefixOfNamespace(ns);
-
- if (String.IsNullOrEmpty(prefix)) {
- prefix = ParentObject.OwnerDocument.GetPrefixForNamespace(ns);
- }
-
- if (!string.IsNullOrEmpty(prefix)) {
- element.SetAttribute(name, ns, value);
- return element.GetAttributeNode(name, ns);
- }
- } else {
- name = PropertyName;
- }
-
- element.SetAttribute(name, string.Empty, value);
- return element.GetAttributeNode(name);
- }
-
- internal string GetNameForMarkupExtension()
- {
- if (IsAttached) {
- string name = PropertyTargetType.Name + "." + PropertyName;
-
- var element = ParentObject.XmlElement;
- string ns = ParentObject.OwnerDocument.GetNamespaceFor(PropertyTargetType);
- var prefix = element.GetPrefixOfNamespace(ns);
- if (string.IsNullOrEmpty(prefix))
- return name;
- else
- return prefix + ":" + name;
- } else
- return PropertyName;
- }
-
- ///
- /// used internally by the XamlParser.
- /// Add a collection element that already is part of the XML DOM.
- ///
- internal void ParserAddCollectionElement(XmlElement collectionPropertyElement, XamlPropertyValue val)
- {
- if (collectionPropertyElement != null && _propertyElement == null) {
- ParserSetPropertyElement(collectionPropertyElement);
- }
- collectionElements.AddInternal(val);
- val.ParentProperty = this;
- if (collectionPropertyElement != _propertyElement) {
- val.RemoveNodeFromParent();
- val.AddNodeTo(this);
- }
- }
-
- ///
- /// Gets/Sets the value of the property on the instance without updating the XAML document.
- ///
- public object ValueOnInstance {
- get {
- if (IsEvent) {
- if (propertyValue != null)
- return propertyValue.GetValueFor(null);
- else
- return null;
- } else {
- return propertyInfo.GetValue(parentObject.Instance);
- }
- }
- set {
- propertyInfo.SetValue(parentObject.Instance, value);
- if (ValueOnInstanceChanged != null)
- ValueOnInstanceChanged(this, EventArgs.Empty);
- }
- }
-
- ///
- /// Gets if this property is considered "advanced" and should be hidden by default in a property grid.
- ///
- public bool IsAdvanced {
- get { return propertyInfo.IsAdvanced; }
- }
-
- ///
- /// Gets the dependency property.
- ///
- public DependencyProperty DependencyProperty {
- get {
- return propertyInfo.DependencyProperty;
- }
- }
-
- void PossiblyNameChanged(XamlPropertyValue oldValue, XamlPropertyValue newValue)
- {
- if (ParentObject.RuntimeNameProperty != null && PropertyName == ParentObject.RuntimeNameProperty) {
-
- if (!String.IsNullOrEmpty(ParentObject.GetXamlAttribute("Name"))) {
- throw new XamlLoadException("The property 'Name' is set more than once.");
- }
-
- string oldName = null;
- string newName = null;
-
- var oldTextValue = oldValue as XamlTextValue;
- if (oldTextValue != null) oldName = oldTextValue.Text;
-
- var newTextValue = newValue as XamlTextValue;
- if (newTextValue != null) newName = newTextValue.Text;
-
- NameScopeHelper.NameChanged(ParentObject, oldName, newName);
- }
- }
-
- /*public bool IsAttributeSyntax {
- get {
- return attribute != null;
- }
- }
-
- public bool IsElementSyntax {
- get {
- return element != null;
- }
- }
-
- public bool IsImplicitDefaultProperty {
- get {
- return attribute == null && element == null;
- }
- }*/
- }
-}
+// 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.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Xml;
+using System.Windows;
+using System.Windows.Markup;
+
+namespace ICSharpCode.WpfDesign.XamlDom
+{
+ ///
+ /// Describes a property on a .
+ ///
+ [DebuggerDisplay("XamlProperty: {PropertyName}")]
+ public sealed class XamlProperty
+ {
+ XamlObject parentObject;
+ internal readonly XamlPropertyInfo propertyInfo;
+ XamlPropertyValue propertyValue;
+
+ CollectionElementsCollection collectionElements;
+ bool isCollection;
+ bool isResources;
+
+ static readonly IList emptyCollectionElementsArray = new XamlPropertyValue[0];
+
+ // for use by parser only
+ internal XamlProperty(XamlObject parentObject, XamlPropertyInfo propertyInfo, XamlPropertyValue propertyValue)
+ : this(parentObject, propertyInfo)
+ {
+ PossiblyNameChanged(null, propertyValue);
+
+ this.propertyValue = propertyValue;
+ if (propertyValue != null) {
+ propertyValue.ParentProperty = this;
+ }
+
+ UpdateValueOnInstance();
+ }
+
+ internal XamlProperty(XamlObject parentObject, XamlPropertyInfo propertyInfo)
+ {
+ this.parentObject = parentObject;
+ this.propertyInfo = propertyInfo;
+
+ if (propertyInfo.IsCollection) {
+ isCollection = true;
+ collectionElements = new CollectionElementsCollection(this);
+
+ if (propertyInfo.Name.Equals(XamlConstants.ResourcesPropertyName, StringComparison.Ordinal) &&
+ propertyInfo.ReturnType == typeof(ResourceDictionary)) {
+ isResources = true;
+ }
+ }
+ }
+
+ ///
+ /// Gets the parent object for which this property was declared.
+ ///
+ public XamlObject ParentObject {
+ get { return parentObject; }
+ }
+
+ ///
+ /// Gets the property name.
+ ///
+ public string PropertyName {
+ get { return propertyInfo.Name; }
+ }
+
+ ///
+ /// Gets the type the property is declared on.
+ ///
+ public Type PropertyTargetType {
+ get { return propertyInfo.TargetType; }
+ }
+
+ ///
+ /// Gets if this property is an attached property.
+ ///
+ public bool IsAttached {
+ get { return propertyInfo.IsAttached; }
+ }
+
+ ///
+ /// Gets if this property is an event.
+ ///
+ public bool IsEvent {
+ get { return propertyInfo.IsEvent; }
+ }
+
+ ///
+ /// Gets the return type of the property.
+ ///
+ public Type ReturnType {
+ get { return propertyInfo.ReturnType; }
+ }
+
+ ///
+ /// Gets the type converter used to convert property values to/from string.
+ ///
+ public TypeConverter TypeConverter {
+ get { return propertyInfo.TypeConverter; }
+ }
+
+ ///
+ /// Gets the category of the property.
+ ///
+ public string Category {
+ get { return propertyInfo.Category; }
+ }
+
+ ///
+ /// Gets the value of the property. Can be null if the property is a collection property.
+ ///
+ public XamlPropertyValue PropertyValue {
+ get { return propertyValue; }
+ set { SetPropertyValue(value); }
+ }
+
+ ///
+ /// Gets if the property represents the FrameworkElement.Resources property that holds a locally-defined resource dictionary.
+ ///
+ public bool IsResources {
+ get { return isResources; }
+ }
+
+ ///
+ /// Gets if the property is a collection property.
+ ///
+ public bool IsCollection {
+ get { return isCollection; }
+ }
+
+ ///
+ /// Gets the collection elements of the property. Is empty if the property is not a collection.
+ ///
+ public IList CollectionElements {
+ get { return collectionElements ?? emptyCollectionElementsArray; }
+ }
+
+ ///
+ /// Gets if the property is set.
+ ///
+ public bool IsSet {
+ get { return propertyValue != null ||
+ _propertyElement != null; // collection
+ }
+ }
+
+ ///
+ /// Occurs when the value of the IsSet property has changed.
+ ///
+ public event EventHandler IsSetChanged;
+
+ ///
+ /// Occurs when the value of the property has changed.
+ ///
+ public event EventHandler ValueChanged;
+
+ ///
+ /// Occurs when MarkupExtension evaluated PropertyValue dosn't changed but ValueOnInstance does.
+ ///
+ public event EventHandler ValueOnInstanceChanged;
+
+ void SetPropertyValue(XamlPropertyValue value)
+ {
+ // Binding...
+ //if (IsCollection) {
+ // throw new InvalidOperationException("Cannot set the value of collection properties.");
+ //}
+
+ bool wasSet = this.IsSet;
+
+ PossiblyNameChanged(propertyValue, value);
+
+ //reset expression
+ var xamlObject = propertyValue as XamlObject;
+ if (xamlObject != null && xamlObject.IsMarkupExtension)
+ propertyInfo.ResetValue(parentObject.Instance);
+
+ ResetInternal();
+
+ propertyValue = value;
+ propertyValue.ParentProperty = this;
+ propertyValue.AddNodeTo(this);
+ UpdateValueOnInstance();
+
+ ParentObject.OnPropertyChanged(this);
+
+ if (!wasSet) {
+ if (IsSetChanged != null) {
+ IsSetChanged(this, EventArgs.Empty);
+ }
+ }
+
+ if (ValueChanged != null) {
+ ValueChanged(this, EventArgs.Empty);
+ }
+ }
+
+ internal void UpdateValueOnInstance()
+ {
+ if (PropertyValue != null) {
+ try {
+ ValueOnInstance = PropertyValue.GetValueFor(propertyInfo);
+ }
+ catch {
+ Debug.WriteLine("UpdateValueOnInstance() failed");
+ }
+ }
+ }
+
+ ///
+ /// Resets the properties value.
+ ///
+ public void Reset()
+ {
+ if (IsSet) {
+
+ propertyInfo.ResetValue(parentObject.Instance);
+ ResetInternal();
+
+ ParentObject.OnPropertyChanged(this);
+
+ if (IsSetChanged != null) {
+ IsSetChanged(this, EventArgs.Empty);
+ }
+ if (ValueChanged != null) {
+ ValueChanged(this, EventArgs.Empty);
+ }
+ }
+ }
+
+ void ResetInternal()
+ {
+ if (propertyValue != null) {
+ propertyValue.RemoveNodeFromParent();
+ propertyValue.ParentProperty = null;
+ propertyValue = null;
+ }
+ if (_propertyElement != null) {
+ _propertyElement.ParentNode.RemoveChild(_propertyElement);
+ _propertyElement = null;
+ }
+ }
+
+ XmlElement _propertyElement;
+
+ internal void ParserSetPropertyElement(XmlElement propertyElement)
+ {
+ XmlElement oldPropertyElement = _propertyElement;
+ if (oldPropertyElement == propertyElement) return;
+
+ _propertyElement = propertyElement;
+
+ if (oldPropertyElement != null && IsCollection) {
+ Debug.WriteLine("Property element for " + this.PropertyName + " already exists, merging..");
+ foreach (XamlPropertyValue val in this.collectionElements) {
+ val.RemoveNodeFromParent();
+ val.AddNodeTo(this);
+ }
+ oldPropertyElement.ParentNode.RemoveChild(oldPropertyElement);
+ }
+ }
+
+ bool IsFirstChildResources(XamlObject obj)
+ {
+ return obj.XmlElement.FirstChild != null &&
+ obj.XmlElement.FirstChild.Name.EndsWith("." + XamlConstants.ResourcesPropertyName) &&
+ obj.Properties.Where((prop) => prop.IsResources).FirstOrDefault() != null;
+ }
+
+ XmlElement CreatePropertyElement()
+ {
+ string ns = parentObject.OwnerDocument.GetNamespaceFor(parentObject.ElementType);
+ return parentObject.OwnerDocument.XmlDocument.CreateElement(
+ parentObject.OwnerDocument.GetPrefixForNamespace(ns),
+ parentObject.ElementType.Name + "." + this.PropertyName,
+ ns
+ );
+ }
+
+ internal void AddChildNodeToProperty(XmlNode newChildNode)
+ {
+ if (this.IsCollection) {
+ // this is the default collection
+ InsertNodeInCollection(newChildNode, collectionElements.Count);
+ return;
+ }
+ if (_propertyElement == null) {
+ if (PropertyName == parentObject.ContentPropertyName) {
+ if (IsFirstChildResources(parentObject)) {
+ // Resources element should always be first
+ parentObject.XmlElement.InsertAfter(newChildNode, parentObject.XmlElement.FirstChild);
+ }
+ else
+ parentObject.XmlElement.InsertBefore(newChildNode, parentObject.XmlElement.FirstChild);
+ return;
+ }
+ _propertyElement = CreatePropertyElement();
+
+ if (IsFirstChildResources(parentObject)) {
+ // Resources element should always be first
+ parentObject.XmlElement.InsertAfter(_propertyElement, parentObject.XmlElement.FirstChild);
+ }
+ else
+ parentObject.XmlElement.InsertBefore(_propertyElement, parentObject.XmlElement.FirstChild);
+ }
+ _propertyElement.AppendChild(newChildNode);
+ }
+
+ internal void InsertNodeInCollection(XmlNode newChildNode, int index)
+ {
+ Debug.Assert(index >= 0 && index <= collectionElements.Count);
+ XmlElement collection = _propertyElement;
+ if (collection == null) {
+ if (collectionElements.Count == 0 && this.PropertyName != this.ParentObject.ContentPropertyName) {
+ // we have to create the collection element
+ _propertyElement = CreatePropertyElement();
+
+ if (this.IsResources) {
+ parentObject.XmlElement.PrependChild(_propertyElement);
+ } else {
+ parentObject.XmlElement.AppendChild(_propertyElement);
+ }
+
+ collection = _propertyElement;
+ } else {
+ // this is the default collection
+ collection = parentObject.XmlElement;
+ }
+ }
+ if (collectionElements.Count == 0) {
+ // collection is empty -> we may insert anywhere
+ collection.AppendChild(newChildNode);
+ } else if (index == collectionElements.Count) {
+ // insert after last element in collection
+ collection.InsertAfter(newChildNode, collectionElements[collectionElements.Count - 1].GetNodeForCollection());
+ } else {
+ // insert before specified index
+ collection.InsertBefore(newChildNode, collectionElements[index].GetNodeForCollection());
+ }
+ }
+
+ internal XmlAttribute SetAttribute(string value)
+ {
+ string name;
+ var element = ParentObject.XmlElement;
+
+ if (IsAttached)
+ {
+ if (PropertyTargetType == typeof (DesignTimeProperties) || PropertyTargetType == typeof (MarkupCompatibilityProperties))
+ name = PropertyName;
+ else
+ name = PropertyTargetType.Name + "." + PropertyName;
+
+ string ns = ParentObject.OwnerDocument.GetNamespaceFor(PropertyTargetType);
+ string prefix = element.GetPrefixOfNamespace(ns);
+
+ if (String.IsNullOrEmpty(prefix)) {
+ prefix = ParentObject.OwnerDocument.GetPrefixForNamespace(ns);
+ }
+
+ if (!string.IsNullOrEmpty(prefix)) {
+ element.SetAttribute(name, ns, value);
+ return element.GetAttributeNode(name, ns);
+ }
+ } else {
+ name = PropertyName;
+ }
+
+ element.SetAttribute(name, string.Empty, value);
+ return element.GetAttributeNode(name);
+ }
+
+ internal string GetNameForMarkupExtension()
+ {
+ if (IsAttached) {
+ string name = PropertyTargetType.Name + "." + PropertyName;
+
+ var element = ParentObject.XmlElement;
+ string ns = ParentObject.OwnerDocument.GetNamespaceFor(PropertyTargetType);
+ var prefix = element.GetPrefixOfNamespace(ns);
+ if (string.IsNullOrEmpty(prefix))
+ return name;
+ else
+ return prefix + ":" + name;
+ } else
+ return PropertyName;
+ }
+
+ ///
+ /// used internally by the XamlParser.
+ /// Add a collection element that already is part of the XML DOM.
+ ///
+ internal void ParserAddCollectionElement(XmlElement collectionPropertyElement, XamlPropertyValue val)
+ {
+ if (collectionPropertyElement != null && _propertyElement == null) {
+ ParserSetPropertyElement(collectionPropertyElement);
+ }
+ collectionElements.AddInternal(val);
+ val.ParentProperty = this;
+ if (collectionPropertyElement != _propertyElement) {
+ val.RemoveNodeFromParent();
+ val.AddNodeTo(this);
+ }
+ }
+
+ ///
+ /// Gets/Sets the value of the property on the instance without updating the XAML document.
+ ///
+ public object ValueOnInstance {
+ get {
+ if (IsEvent) {
+ if (propertyValue != null)
+ return propertyValue.GetValueFor(null);
+ else
+ return null;
+ } else {
+ return propertyInfo.GetValue(parentObject.Instance);
+ }
+ }
+ set {
+ propertyInfo.SetValue(parentObject.Instance, value);
+ if (ValueOnInstanceChanged != null)
+ ValueOnInstanceChanged(this, EventArgs.Empty);
+ }
+ }
+
+ ///
+ /// Gets if this property is considered "advanced" and should be hidden by default in a property grid.
+ ///
+ public bool IsAdvanced {
+ get { return propertyInfo.IsAdvanced; }
+ }
+
+ ///
+ /// Gets the dependency property.
+ ///
+ public DependencyProperty DependencyProperty {
+ get {
+ return propertyInfo.DependencyProperty;
+ }
+ }
+
+ void PossiblyNameChanged(XamlPropertyValue oldValue, XamlPropertyValue newValue)
+ {
+ if (ParentObject.RuntimeNameProperty != null && PropertyName == ParentObject.RuntimeNameProperty) {
+
+ if (!String.IsNullOrEmpty(ParentObject.GetXamlAttribute("Name"))) {
+ throw new XamlLoadException("The property 'Name' is set more than once.");
+ }
+
+ string oldName = null;
+ string newName = null;
+
+ var oldTextValue = oldValue as XamlTextValue;
+ if (oldTextValue != null) oldName = oldTextValue.Text;
+
+ var newTextValue = newValue as XamlTextValue;
+ if (newTextValue != null) newName = newTextValue.Text;
+
+ NameScopeHelper.NameChanged(ParentObject, oldName, newName);
+ }
+ }
+
+ /*public bool IsAttributeSyntax {
+ get {
+ return attribute != null;
+ }
+ }
+
+ public bool IsElementSyntax {
+ get {
+ return element != null;
+ }
+ }
+
+ public bool IsImplicitDefaultProperty {
+ get {
+ return attribute == null && element == null;
+ }
+ }*/
+ }
+}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/ExtensionMethods.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/ExtensionMethods.cs
index bd9df3670c..af0549508f 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/ExtensionMethods.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/ExtensionMethods.cs
@@ -1,8 +1,8 @@
// 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.ComponentModel;
+// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
+
+using System;
+using System.ComponentModel;
using System.Windows;
namespace ICSharpCode.WpfDesign
@@ -23,52 +23,52 @@ namespace ICSharpCode.WpfDesign
Math.Round(rect.Width, PlacementInformation.BoundsPrecision),
Math.Round(rect.Height, PlacementInformation.BoundsPrecision)
);
- }
-
- ///
- /// Gets the design item property for the specified member descriptor.
- ///
- public static DesignItemProperty GetProperty(this DesignItemPropertyCollection properties, MemberDescriptor md)
- {
- DesignItemProperty prop = null;
-
- var pd = md as PropertyDescriptor;
- if (pd != null)
- {
- var dpd = DependencyPropertyDescriptor.FromProperty(pd);
- if (dpd != null)
- {
- if (dpd.IsAttached)
- {
- prop = properties.GetAttachedProperty(dpd.DependencyProperty);
- }
- else
- {
- prop = properties.GetProperty(dpd.DependencyProperty);
- }
- }
- }
-
- if (prop == null)
- {
- prop = properties[md.Name];
- }
-
- return prop;
- }
-
- ///
- /// Gets if the specified design item property represents an attached dependency property.
- ///
- public static bool IsAttachedDependencyProperty(this DesignItemProperty property)
- {
- if (property.DependencyProperty != null)
- {
- var dpd = DependencyPropertyDescriptor.FromProperty(property.DependencyProperty, property.DesignItem.ComponentType);
- return dpd.IsAttached;
- }
-
- return false;
+ }
+
+ ///
+ /// Gets the design item property for the specified member descriptor.
+ ///
+ public static DesignItemProperty GetProperty(this DesignItemPropertyCollection properties, MemberDescriptor md)
+ {
+ DesignItemProperty prop = null;
+
+ var pd = md as PropertyDescriptor;
+ if (pd != null)
+ {
+ var dpd = DependencyPropertyDescriptor.FromProperty(pd);
+ if (dpd != null)
+ {
+ if (dpd.IsAttached)
+ {
+ prop = properties.GetAttachedProperty(dpd.DependencyProperty);
+ }
+ else
+ {
+ prop = properties.GetProperty(dpd.DependencyProperty);
+ }
+ }
+ }
+
+ if (prop == null)
+ {
+ prop = properties[md.Name];
+ }
+
+ return prop;
+ }
+
+ ///
+ /// Gets if the specified design item property represents an attached dependency property.
+ ///
+ public static bool IsAttachedDependencyProperty(this DesignItemProperty property)
+ {
+ if (property.DependencyProperty != null)
+ {
+ var dpd = DependencyPropertyDescriptor.FromProperty(property.DependencyProperty, property.DesignItem.ComponentType);
+ return dpd.IsAttached;
+ }
+
+ return false;
}
}
}
diff --git a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyGrid/PropertyNode.cs b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyGrid/PropertyNode.cs
index dd1efb0a43..46dafef069 100644
--- a/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyGrid/PropertyNode.cs
+++ b/src/AddIns/DisplayBindings/WpfDesign/WpfDesign/Project/PropertyGrid/PropertyNode.cs
@@ -1,420 +1,420 @@
-// 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.Linq;
-using System.Text;
-using System.ComponentModel;
-using System.Windows;
-using System.Windows.Controls;
-using System.Collections.ObjectModel;
-using System.Windows.Data;
-using System.Windows.Media;
-using System.Windows.Markup;
-
-namespace ICSharpCode.WpfDesign.PropertyGrid
-{
- ///
- /// View-Model class for the property grid.
- ///
- public class PropertyNode : INotifyPropertyChanged
- {
- static object Unset = new object();
-
- ///
- /// Gets the properties that are presented by this node.
- /// This might be multiple properties if multiple controls are selected.
- ///
- public ReadOnlyCollection Properties { get; private set; }
-
- bool raiseEvents = true;
- bool hasStringConverter;
-
- ///
- /// Gets the name of the property.
- ///
- public string Name
- {
- get
- {
- var dp = FirstProperty.DependencyProperty;
- if (dp != null)
- {
- var dpd = DependencyPropertyDescriptor.FromProperty(dp, FirstProperty.DesignItem.ComponentType);
- if (dpd.IsAttached)
- {
- // Will return the attached property name in the form of .
- return dpd.Name;
- }
- }
-
- return FirstProperty.Name;
- }
- }
-
- ///
- /// Gets if this property node represents an event.
- ///
- public bool IsEvent { get { return FirstProperty.IsEvent; } }
-
- ///
- /// Gets the design context associated with this set of properties.
- ///
- public DesignContext Context { get { return FirstProperty.DesignItem.Context; } }
-
- ///
- /// Gets the service container associated with this set of properties.
- ///
- public ServiceContainer Services { get { return FirstProperty.DesignItem.Services; } }
-
- ///
- /// Gets the editor control that edits this property.
- ///
- public FrameworkElement Editor { get; private set; }
-
- ///
- /// Gets the first property (equivalent to Properties[0])
- ///
- public DesignItemProperty FirstProperty { get { return Properties[0]; } }
-
- ///
- /// For nested property nodes, gets the parent node.
- ///
- public PropertyNode Parent { get; private set; }
-
- ///
- /// For nested property nodes, gets the level of this node.
- ///
- public int Level { get; private set; }
-
- ///
- /// Gets the category of this node.
- ///
- public Category Category { get; set; }
-
- ///
- /// Gets the list of child nodes.
- ///
- public ObservableCollection Children { get; private set; }
-
- ///
- /// Gets the list of advanced child nodes (not visible by default).
- ///
- public ObservableCollection MoreChildren { get; private set; }
-
- bool isExpanded;
-
- ///
- /// Gets whether this property node is currently expanded.
- ///
- public bool IsExpanded {
- get {
- return isExpanded;
- }
- set {
- isExpanded = value;
- UpdateChildren();
- RaisePropertyChanged("IsExpanded");
- }
- }
-
- ///
- /// Gets whether this property node has children.
- ///
- public bool HasChildren {
- get { return Children.Count > 0 || MoreChildren.Count > 0; }
- }
-
- ///
- /// Gets the description object using the IPropertyDescriptionService.
- ///
- public object Description {
- get {
- IPropertyDescriptionService s = Services.GetService();
- if (s != null) {
- return s.GetDescription(FirstProperty);
- }
- return null;
- }
- }
-
- ///
- /// Gets/Sets the value of this property.
- ///
- public object Value {
- get {
- if (IsAmbiguous) return null;
- var result = FirstProperty.ValueOnInstance;
- if (result == DependencyProperty.UnsetValue) return null;
- return result;
- }
- set {
- SetValueCore(value);
- }
- }
-
- ///
- /// Gets/Sets the value of this property in string form
- ///
- public string ValueString {
- get {
- if (ValueItem == null || ValueItem.Component is MarkupExtension) {
- if (Value == null) return null;
- if (hasStringConverter) {
- return FirstProperty.TypeConverter.ConvertToInvariantString(Value);
- }
- return "(" + Value.GetType().Name + ")";
- }
- return "(" + ValueItem.ComponentType.Name + ")";
- }
- set {
- // make sure we only catch specific exceptions
- // and/or show the error message to the user
- //try {
- Value = FirstProperty.TypeConverter.ConvertFromInvariantString(value);
- //} catch {
- // OnValueOnInstanceChanged();
- //}
- }
- }
-
- ///
- /// Gets whether the property node is enabled for editing.
- ///
- public bool IsEnabled {
- get {
- return ValueItem == null && hasStringConverter;
- }
- }
-
- ///
- /// Gets whether this property was set locally.
- ///
- public bool IsSet {
- get {
- foreach (var p in Properties) {
- if (p.IsSet) return true;
- }
- return false;
- }
- }
-
- ///
- /// Gets the color of the name.
- /// Depends on the type of the value (binding/resource/etc.)
- ///
- public Brush NameForeground {
- get {
- if (ValueItem != null) {
- object component = ValueItem.Component;
- if (component is BindingBase)
- return Brushes.DarkGoldenrod;
- if (component is StaticResourceExtension || component is DynamicResourceExtension)
- return Brushes.DarkGreen;
- }
- return SystemColors.WindowTextBrush;
- }
- }
-
- ///
- /// Returns the DesignItem that owns the property (= the DesignItem that is currently selected).
- /// Returns null if multiple DesignItems are selected.
- ///
- public DesignItem ValueItem {
- get {
- if (Properties.Count == 1) {
- return FirstProperty.Value;
- }
- return null;
- }
- }
-
- ///
- /// Gets whether the property value is ambiguous (multiple controls having different values are selected).
- ///
- public bool IsAmbiguous {
- get {
- foreach (var p in Properties) {
- if (!object.Equals(p.ValueOnInstance, FirstProperty.ValueOnInstance)) {
- return true;
- }
- }
- return false;
- }
- }
-
- bool isVisible;
-
- ///
- /// Gets/Sets whether the property is visible.
- ///
- public bool IsVisible {
- get {
- return isVisible;
- }
- set {
- isVisible = value;
- RaisePropertyChanged("IsVisible");
- }
- }
-
- ///
- /// Gets whether resetting the property is possible.
- ///
- public bool CanReset {
- get { return IsSet; }
- }
-
- ///
- /// Resets the property.
- ///
- public void Reset()
- {
- SetValueCore(Unset);
- }
-
- ///
- /// Replaces the value of this node with a new binding.
- ///
- public void CreateBinding()
- {
- Value = new Binding();
- IsExpanded = true;
- }
-
- void SetValueCore(object value)
- {
- raiseEvents = false;
- if (value == Unset) {
- foreach (var p in Properties) {
- p.Reset();
- }
- } else {
- foreach (var p in Properties) {
- p.SetValue(value);
- }
- }
- raiseEvents = true;
- OnValueChanged();
- }
-
- void OnValueChanged()
- {
- RaisePropertyChanged("IsSet");
- RaisePropertyChanged("Value");
- RaisePropertyChanged("ValueString");
- RaisePropertyChanged("IsAmbiguous");
- RaisePropertyChanged("FontWeight");
- RaisePropertyChanged("IsEnabled");
- RaisePropertyChanged("NameForeground");
-
- UpdateChildren();
- }
-
- void OnValueOnInstanceChanged()
- {
- RaisePropertyChanged("Value");
- RaisePropertyChanged("ValueString");
- }
-
- ///
- /// Creates a new PropertyNode instance.
- ///
- public PropertyNode()
- {
- Children = new ObservableCollection();
- MoreChildren = new ObservableCollection();
- }
-
- PropertyNode(DesignItemProperty[] properties, PropertyNode parent) : this()
- {
- this.Parent = parent;
- this.Level = parent == null ? 0 : parent.Level + 1;
- Load(properties);
- }
-
- ///
- /// Initializes this property node with the specified properties.
- ///
- public void Load(DesignItemProperty[] properties)
- {
- if (this.Properties != null) {
- // detach events from old properties
- foreach (var property in this.Properties) {
- property.ValueChanged -= new EventHandler(property_ValueChanged);
- property.ValueOnInstanceChanged -= new EventHandler(property_ValueOnInstanceChanged);
- }
- }
-
- this.Properties = new ReadOnlyCollection(properties);
-
- if (Editor == null)
- Editor = EditorManager.CreateEditor(FirstProperty);
-
- foreach (var property in properties) {
- property.ValueChanged += new EventHandler(property_ValueChanged);
- property.ValueOnInstanceChanged += new EventHandler(property_ValueOnInstanceChanged);
- }
-
- hasStringConverter =
- FirstProperty.TypeConverter.CanConvertFrom(typeof(string)) &&
- FirstProperty.TypeConverter.CanConvertTo(typeof(string));
-
- OnValueChanged();
- }
-
- void property_ValueOnInstanceChanged(object sender, EventArgs e)
- {
- if (raiseEvents) OnValueOnInstanceChanged();
- }
-
- void property_ValueChanged(object sender, EventArgs e)
- {
- if (raiseEvents) OnValueChanged();
- }
-
- void UpdateChildren()
- {
- Children.Clear();
- MoreChildren.Clear();
-
- if (Parent == null || Parent.IsExpanded) {
- if (ValueItem != null) {
- var list = TypeHelper.GetAvailableProperties(ValueItem.Component)
- .OrderBy(d => d.Name)
- .Select(d => new PropertyNode(new[] { ValueItem.Properties.GetProperty(d) }, this));
-
- foreach (var node in list) {
- if (Metadata.IsBrowsable(node.FirstProperty)) {
- node.IsVisible = true;
- if (Metadata.IsPopularProperty(node.FirstProperty)) {
- Children.Add(node);
- } else {
- MoreChildren.Add(node);
- }
- }
- }
- }
- }
-
- RaisePropertyChanged("HasChildren");
- }
-
- #region INotifyPropertyChanged Members
-
- ///
- /// Occurs when a property has changed. Used to support WPF data binding.
- ///
- public event PropertyChangedEventHandler PropertyChanged;
-
- void RaisePropertyChanged(string name)
- {
- if (PropertyChanged != null) {
- PropertyChanged(this, new PropertyChangedEventArgs(name));
- }
- }
-
- #endregion
- }
-}
+// 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.Linq;
+using System.Text;
+using System.ComponentModel;
+using System.Windows;
+using System.Windows.Controls;
+using System.Collections.ObjectModel;
+using System.Windows.Data;
+using System.Windows.Media;
+using System.Windows.Markup;
+
+namespace ICSharpCode.WpfDesign.PropertyGrid
+{
+ ///
+ /// View-Model class for the property grid.
+ ///
+ public class PropertyNode : INotifyPropertyChanged
+ {
+ static object Unset = new object();
+
+ ///
+ /// Gets the properties that are presented by this node.
+ /// This might be multiple properties if multiple controls are selected.
+ ///
+ public ReadOnlyCollection Properties { get; private set; }
+
+ bool raiseEvents = true;
+ bool hasStringConverter;
+
+ ///
+ /// Gets the name of the property.
+ ///
+ public string Name
+ {
+ get
+ {
+ var dp = FirstProperty.DependencyProperty;
+ if (dp != null)
+ {
+ var dpd = DependencyPropertyDescriptor.FromProperty(dp, FirstProperty.DesignItem.ComponentType);
+ if (dpd.IsAttached)
+ {
+ // Will return the attached property name in the form of .
+ return dpd.Name;
+ }
+ }
+
+ return FirstProperty.Name;
+ }
+ }
+
+ ///
+ /// Gets if this property node represents an event.
+ ///
+ public bool IsEvent { get { return FirstProperty.IsEvent; } }
+
+ ///
+ /// Gets the design context associated with this set of properties.
+ ///
+ public DesignContext Context { get { return FirstProperty.DesignItem.Context; } }
+
+ ///
+ /// Gets the service container associated with this set of properties.
+ ///
+ public ServiceContainer Services { get { return FirstProperty.DesignItem.Services; } }
+
+ ///
+ /// Gets the editor control that edits this property.
+ ///
+ public FrameworkElement Editor { get; private set; }
+
+ ///
+ /// Gets the first property (equivalent to Properties[0])
+ ///
+ public DesignItemProperty FirstProperty { get { return Properties[0]; } }
+
+ ///
+ /// For nested property nodes, gets the parent node.
+ ///
+ public PropertyNode Parent { get; private set; }
+
+ ///
+ /// For nested property nodes, gets the level of this node.
+ ///
+ public int Level { get; private set; }
+
+ ///
+ /// Gets the category of this node.
+ ///
+ public Category Category { get; set; }
+
+ ///
+ /// Gets the list of child nodes.
+ ///
+ public ObservableCollection Children { get; private set; }
+
+ ///
+ /// Gets the list of advanced child nodes (not visible by default).
+ ///
+ public ObservableCollection MoreChildren { get; private set; }
+
+ bool isExpanded;
+
+ ///
+ /// Gets whether this property node is currently expanded.
+ ///
+ public bool IsExpanded {
+ get {
+ return isExpanded;
+ }
+ set {
+ isExpanded = value;
+ UpdateChildren();
+ RaisePropertyChanged("IsExpanded");
+ }
+ }
+
+ ///
+ /// Gets whether this property node has children.
+ ///
+ public bool HasChildren {
+ get { return Children.Count > 0 || MoreChildren.Count > 0; }
+ }
+
+ ///
+ /// Gets the description object using the IPropertyDescriptionService.
+ ///
+ public object Description {
+ get {
+ IPropertyDescriptionService s = Services.GetService();
+ if (s != null) {
+ return s.GetDescription(FirstProperty);
+ }
+ return null;
+ }
+ }
+
+ ///
+ /// Gets/Sets the value of this property.
+ ///
+ public object Value {
+ get {
+ if (IsAmbiguous) return null;
+ var result = FirstProperty.ValueOnInstance;
+ if (result == DependencyProperty.UnsetValue) return null;
+ return result;
+ }
+ set {
+ SetValueCore(value);
+ }
+ }
+
+ ///
+ /// Gets/Sets the value of this property in string form
+ ///
+ public string ValueString {
+ get {
+ if (ValueItem == null || ValueItem.Component is MarkupExtension) {
+ if (Value == null) return null;
+ if (hasStringConverter) {
+ return FirstProperty.TypeConverter.ConvertToInvariantString(Value);
+ }
+ return "(" + Value.GetType().Name + ")";
+ }
+ return "(" + ValueItem.ComponentType.Name + ")";
+ }
+ set {
+ // make sure we only catch specific exceptions
+ // and/or show the error message to the user
+ //try {
+ Value = FirstProperty.TypeConverter.ConvertFromInvariantString(value);
+ //} catch {
+ // OnValueOnInstanceChanged();
+ //}
+ }
+ }
+
+ ///
+ /// Gets whether the property node is enabled for editing.
+ ///
+ public bool IsEnabled {
+ get {
+ return ValueItem == null && hasStringConverter;
+ }
+ }
+
+ ///
+ /// Gets whether this property was set locally.
+ ///
+ public bool IsSet {
+ get {
+ foreach (var p in Properties) {
+ if (p.IsSet) return true;
+ }
+ return false;
+ }
+ }
+
+ ///
+ /// Gets the color of the name.
+ /// Depends on the type of the value (binding/resource/etc.)
+ ///
+ public Brush NameForeground {
+ get {
+ if (ValueItem != null) {
+ object component = ValueItem.Component;
+ if (component is BindingBase)
+ return Brushes.DarkGoldenrod;
+ if (component is StaticResourceExtension || component is DynamicResourceExtension)
+ return Brushes.DarkGreen;
+ }
+ return SystemColors.WindowTextBrush;
+ }
+ }
+
+ ///
+ /// Returns the DesignItem that owns the property (= the DesignItem that is currently selected).
+ /// Returns null if multiple DesignItems are selected.
+ ///
+ public DesignItem ValueItem {
+ get {
+ if (Properties.Count == 1) {
+ return FirstProperty.Value;
+ }
+ return null;
+ }
+ }
+
+ ///
+ /// Gets whether the property value is ambiguous (multiple controls having different values are selected).
+ ///
+ public bool IsAmbiguous {
+ get {
+ foreach (var p in Properties) {
+ if (!object.Equals(p.ValueOnInstance, FirstProperty.ValueOnInstance)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ bool isVisible;
+
+ ///
+ /// Gets/Sets whether the property is visible.
+ ///
+ public bool IsVisible {
+ get {
+ return isVisible;
+ }
+ set {
+ isVisible = value;
+ RaisePropertyChanged("IsVisible");
+ }
+ }
+
+ ///
+ /// Gets whether resetting the property is possible.
+ ///
+ public bool CanReset {
+ get { return IsSet; }
+ }
+
+ ///
+ /// Resets the property.
+ ///
+ public void Reset()
+ {
+ SetValueCore(Unset);
+ }
+
+ ///
+ /// Replaces the value of this node with a new binding.
+ ///
+ public void CreateBinding()
+ {
+ Value = new Binding();
+ IsExpanded = true;
+ }
+
+ void SetValueCore(object value)
+ {
+ raiseEvents = false;
+ if (value == Unset) {
+ foreach (var p in Properties) {
+ p.Reset();
+ }
+ } else {
+ foreach (var p in Properties) {
+ p.SetValue(value);
+ }
+ }
+ raiseEvents = true;
+ OnValueChanged();
+ }
+
+ void OnValueChanged()
+ {
+ RaisePropertyChanged("IsSet");
+ RaisePropertyChanged("Value");
+ RaisePropertyChanged("ValueString");
+ RaisePropertyChanged("IsAmbiguous");
+ RaisePropertyChanged("FontWeight");
+ RaisePropertyChanged("IsEnabled");
+ RaisePropertyChanged("NameForeground");
+
+ UpdateChildren();
+ }
+
+ void OnValueOnInstanceChanged()
+ {
+ RaisePropertyChanged("Value");
+ RaisePropertyChanged("ValueString");
+ }
+
+ ///
+ /// Creates a new PropertyNode instance.
+ ///
+ public PropertyNode()
+ {
+ Children = new ObservableCollection();
+ MoreChildren = new ObservableCollection();
+ }
+
+ PropertyNode(DesignItemProperty[] properties, PropertyNode parent) : this()
+ {
+ this.Parent = parent;
+ this.Level = parent == null ? 0 : parent.Level + 1;
+ Load(properties);
+ }
+
+ ///
+ /// Initializes this property node with the specified properties.
+ ///
+ public void Load(DesignItemProperty[] properties)
+ {
+ if (this.Properties != null) {
+ // detach events from old properties
+ foreach (var property in this.Properties) {
+ property.ValueChanged -= new EventHandler(property_ValueChanged);
+ property.ValueOnInstanceChanged -= new EventHandler(property_ValueOnInstanceChanged);
+ }
+ }
+
+ this.Properties = new ReadOnlyCollection(properties);
+
+ if (Editor == null)
+ Editor = EditorManager.CreateEditor(FirstProperty);
+
+ foreach (var property in properties) {
+ property.ValueChanged += new EventHandler(property_ValueChanged);
+ property.ValueOnInstanceChanged += new EventHandler(property_ValueOnInstanceChanged);
+ }
+
+ hasStringConverter =
+ FirstProperty.TypeConverter.CanConvertFrom(typeof(string)) &&
+ FirstProperty.TypeConverter.CanConvertTo(typeof(string));
+
+ OnValueChanged();
+ }
+
+ void property_ValueOnInstanceChanged(object sender, EventArgs e)
+ {
+ if (raiseEvents) OnValueOnInstanceChanged();
+ }
+
+ void property_ValueChanged(object sender, EventArgs e)
+ {
+ if (raiseEvents) OnValueChanged();
+ }
+
+ void UpdateChildren()
+ {
+ Children.Clear();
+ MoreChildren.Clear();
+
+ if (Parent == null || Parent.IsExpanded) {
+ if (ValueItem != null) {
+ var list = TypeHelper.GetAvailableProperties(ValueItem.Component)
+ .OrderBy(d => d.Name)
+ .Select(d => new PropertyNode(new[] { ValueItem.Properties.GetProperty(d) }, this));
+
+ foreach (var node in list) {
+ if (Metadata.IsBrowsable(node.FirstProperty)) {
+ node.IsVisible = true;
+ if (Metadata.IsPopularProperty(node.FirstProperty)) {
+ Children.Add(node);
+ } else {
+ MoreChildren.Add(node);
+ }
+ }
+ }
+ }
+ }
+
+ RaisePropertyChanged("HasChildren");
+ }
+
+ #region INotifyPropertyChanged Members
+
+ ///
+ /// Occurs when a property has changed. Used to support WPF data binding.
+ ///
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ void RaisePropertyChanged(string name)
+ {
+ if (PropertyChanged != null) {
+ PropertyChanged(this, new PropertyChangedEventArgs(name));
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Main/Base/Project/Src/Editor/IBracketSearcher.cs b/src/Main/Base/Project/Src/Editor/IBracketSearcher.cs
index 9e165a4f1e..0d6007ece5 100644
--- a/src/Main/Base/Project/Src/Editor/IBracketSearcher.cs
+++ b/src/Main/Base/Project/Src/Editor/IBracketSearcher.cs
@@ -1,52 +1,52 @@
-// 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 ICSharpCode.SharpDevelop.Editor
-{
- ///
- /// Allows language specific search for matching brackets.
- ///
- public interface IBracketSearcher
- {
- ///
- /// Searches for a matching bracket from the given offset to the start of the document.
- ///
- /// A BracketSearchResult that contains the positions and lengths of the brackets. Return null if there is nothing to highlight.
- BracketSearchResult SearchBracket(IDocument document, int offset);
- }
-
- public class DefaultBracketSearcher : IBracketSearcher
- {
- public static readonly DefaultBracketSearcher DefaultInstance = new DefaultBracketSearcher();
-
- public BracketSearchResult SearchBracket(IDocument document, int offset)
- {
- return null;
- }
- }
-
- ///
- /// Describes a pair of matching brackets found by IBracketSearcher.
- ///
- public class BracketSearchResult
- {
- public int OpeningBracketOffset { get; private set; }
-
- public int OpeningBracketLength { get; private set; }
-
- public int ClosingBracketOffset { get; private set; }
-
- public int ClosingBracketLength { get; private set; }
-
- public BracketSearchResult(int openingBracketOffset, int openingBracketLength,
- int closingBracketOffset, int closingBracketLength)
- {
- this.OpeningBracketOffset = openingBracketOffset;
- this.OpeningBracketLength = openingBracketLength;
- this.ClosingBracketOffset = closingBracketOffset;
- this.ClosingBracketLength = closingBracketLength;
- }
- }
-}
+// 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 ICSharpCode.SharpDevelop.Editor
+{
+ ///
+ /// Allows language specific search for matching brackets.
+ ///
+ public interface IBracketSearcher
+ {
+ ///
+ /// Searches for a matching bracket from the given offset to the start of the document.
+ ///
+ /// A BracketSearchResult that contains the positions and lengths of the brackets. Return null if there is nothing to highlight.
+ BracketSearchResult SearchBracket(IDocument document, int offset);
+ }
+
+ public class DefaultBracketSearcher : IBracketSearcher
+ {
+ public static readonly DefaultBracketSearcher DefaultInstance = new DefaultBracketSearcher();
+
+ public BracketSearchResult SearchBracket(IDocument document, int offset)
+ {
+ return null;
+ }
+ }
+
+ ///
+ /// Describes a pair of matching brackets found by IBracketSearcher.
+ ///
+ public class BracketSearchResult
+ {
+ public int OpeningBracketOffset { get; private set; }
+
+ public int OpeningBracketLength { get; private set; }
+
+ public int ClosingBracketOffset { get; private set; }
+
+ public int ClosingBracketLength { get; private set; }
+
+ public BracketSearchResult(int openingBracketOffset, int openingBracketLength,
+ int closingBracketOffset, int closingBracketLength)
+ {
+ this.OpeningBracketOffset = openingBracketOffset;
+ this.OpeningBracketLength = openingBracketLength;
+ this.ClosingBracketOffset = closingBracketOffset;
+ this.ClosingBracketLength = closingBracketLength;
+ }
+ }
+}