Skip to content

Commit

Permalink
Use MEF for debugger commands.
Browse files Browse the repository at this point in the history
  • Loading branch information
eusebiu committed Mar 5, 2011
1 parent c7de679 commit 33d4843
Show file tree
Hide file tree
Showing 11 changed files with 325 additions and 25 deletions.
24 changes: 12 additions & 12 deletions Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs
Expand Up @@ -57,10 +57,10 @@ protected override void OnRender(DrawingContext drawingContext)
// create a dictionary line number => first bookmark
Dictionary<int, BookmarkBase> bookmarkDict = new Dictionary<int, BookmarkBase>();
foreach (var bm in BookmarkManager.Bookmarks) {
if (DebuggedData.CurrentType == null || bm.Type.FullName != DebuggedData.CurrentType.FullName)
if (DebugData.CurrentType == null || bm.Type.FullName != DebugData.CurrentType.FullName)
continue;
if (bm is BreakpointBookmark &&
((BreakpointBookmark)bm).Language != DebuggedData.Language)
((BreakpointBookmark)bm).Language != DebugData.Language)
continue;

int line = bm.LineNumber;
Expand Down Expand Up @@ -119,8 +119,8 @@ BookmarkBase GetBookmarkFromLine(int line)
BookmarkBase result = null;
foreach (BookmarkBase bm in BookmarkManager.Bookmarks) {
if (bm.LineNumber == line &&
DebuggedData.CurrentType != null &&
bm.Type.FullName == DebuggedData.CurrentType.FullName) {
DebugData.CurrentType != null &&
bm.Type.FullName == DebugData.CurrentType.FullName) {
if (result == null || bm.ZOrder > result.ZOrder)
result = bm;
}
Expand Down Expand Up @@ -189,11 +189,11 @@ protected override void OnMouseMove(MouseEventArgs e)
InvalidateVisual();
}

if (DebuggedData.CurrentType == null)
if (DebugData.CurrentType == null)
return;

BreakpointBookmark bm = BookmarkManager.Bookmarks.Find(
b => b.Type.FullName == DebuggedData.CurrentType.FullName &&
b => b.Type.FullName == DebugData.CurrentType.FullName &&
b.LineNumber == GetLineFromMousePosition(e)
&& b is BreakpointBookmark) as BreakpointBookmark;

Expand Down Expand Up @@ -226,24 +226,24 @@ protected override void OnMouseUp(MouseButtonEventArgs e)
return;
}
if (e.ChangedButton == MouseButton.Left) {
if (DebuggedData.CurrentType != null) {
if (DebugData.CurrentType != null) {

// check if the codemappings exists for this line
var storage = CodeMappings.GetStorage(DebuggedData.Language);
var storage = CodeMappings.GetStorage(DebugData.Language);
uint token;
var instruction = storage.GetInstructionByTypeAndLine(DebuggedData.CurrentType.FullName, line, out token);
var instruction = storage.GetInstructionByTypeAndLine(DebugData.CurrentType.FullName, line, out token);

if (instruction == null || instruction.ILInstructionOffset.From == 0) {
MessageBox.Show(string.Format("Missing code mappings for {0} at line {1}", DebuggedData.CurrentType.FullName, line),
MessageBox.Show(string.Format("Missing code mappings for {0} at line {1}", DebugData.CurrentType.FullName, line),
"Code mappings", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}

// no bookmark on the line: create a new breakpoint
DebuggerService.ToggleBreakpointAt(
DebuggedData.CurrentType,
DebugData.CurrentType,
line,
DebuggedData.Language);
DebugData.Language);
}
}
InvalidateVisual();
Expand Down
2 changes: 1 addition & 1 deletion Debugger/ILSpy.Debugger/AvalonEdit/TextMarkerService.cs
Expand Up @@ -45,7 +45,7 @@ void BookmarkManager_Added(object sender, BookmarkEventArgs e)
{
if (e.Bookmark is MarkerBookmark) {
var bm = (MarkerBookmark)e.Bookmark;
if (DebuggedData.CurrentType != null && DebuggedData.CurrentType.FullName.Equals(bm.Type.FullName, StringComparison.OrdinalIgnoreCase)) {
if (DebugData.CurrentType != null && DebugData.CurrentType.FullName.Equals(bm.Type.FullName, StringComparison.OrdinalIgnoreCase)) {
// add bookmark for the current type
DocumentLine line = codeEditor.Document.GetLineByNumber(bm.LineNumber);
bm.Marker = bm.CreateMarker(this, line.Offset, line.Length);
Expand Down
2 changes: 1 addition & 1 deletion Debugger/ILSpy.Debugger/DebuggedType.cs
Expand Up @@ -25,7 +25,7 @@ namespace ILSpy.Debugger
/// <summary>
/// Contains the data important for debugger from the main application.
/// </summary>
public static class DebuggedData
public static class DebugData
{
/// <summary>
/// Gets or sets the current debugged type
Expand Down
Expand Up @@ -49,7 +49,7 @@ enum StopAttachedProcessDialogResult {

private ConcurrentDictionary<string, List<MethodMapping>> CodeMappingsStorage {
get {
return CodeMappings.GetStorage(DebuggedData.Language);
return CodeMappings.GetStorage(DebugData.Language);
}
}

Expand Down
1 change: 1 addition & 0 deletions ILSpy/AboutPage.cs
Expand Up @@ -29,6 +29,7 @@ sealed class AboutPage : SimpleCommand

public override void Execute(object parameter)
{
MainWindow.Instance.UnselectAll();
Display(decompilerTextView);
}

Expand Down
288 changes: 288 additions & 0 deletions ILSpy/Commands/DebuggerCommands.cs
@@ -0,0 +1,288 @@
// 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.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;

using ILSpy.Debugger;
using ILSpy.Debugger.Bookmarks;
using ILSpy.Debugger.Services;
using ILSpy.Debugger.UI;
using Microsoft.Win32;

namespace ICSharpCode.ILSpy.Commands
{
internal abstract class DebuggerCommands : SimpleCommand
{
public DebuggerCommands()
{
MainWindow.Instance.KeyUp += OnKeyUp;
}

void OnKeyUp(object sender, KeyEventArgs e)
{
switch (e.Key) {
case Key.F5:
if (this is ContinueDebuggingCommand) {
((ContinueDebuggingCommand)this).Execute(null);
e.Handled = true;
}
break;
case Key.System:
if (this is StepOverCommand) {
((StepOverCommand)this).Execute(null);
e.Handled = true;
}
break;
case Key.F11:
if (this is StepIntoCommand) {
((StepIntoCommand)this).Execute(null);
e.Handled = true;
}
break;
default:
// do nothing
break;
}
}

#region Static members
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern bool SetWindowPos(
IntPtr hWnd,
IntPtr hWndInsertAfter,
int X,
int Y,
int cx,
int cy,
uint uFlags);

const UInt32 SWP_NOSIZE = 0x0001;
const UInt32 SWP_NOMOVE = 0x0002;

static readonly IntPtr HWND_BOTTOM = new IntPtr(1);
static readonly IntPtr HWND_TOP = new IntPtr(0);

static void SendWpfWindowPos(Window window, IntPtr place)
{
var hWnd = new WindowInteropHelper(window).Handle;
SetWindowPos(hWnd, place, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
}
#endregion

protected static IDebugger CurrentDebugger {
get {
return DebuggerService.CurrentDebugger;
}
}

protected void StartDebugging(Process process)
{
CurrentDebugger.Attach(process);
EnableDebuggerUI(false);
CurrentDebugger.DebugStopped += OnDebugStopped;
CurrentDebugger.IsProcessRunningChanged += CurrentDebugger_IsProcessRunningChanged;
}

protected void OnDebugStopped(object sender, EventArgs e)
{
EnableDebuggerUI(true);
CurrentDebugger.DebugStopped -= OnDebugStopped;
CurrentDebugger.IsProcessRunningChanged -= CurrentDebugger_IsProcessRunningChanged;
}

protected void EnableDebuggerUI(bool enable)
{
var menuItems = MainWindow.Instance.mainMenu.Items;
var toolbarItems = MainWindow.Instance.toolBar.Items;

// menu
var items = menuItems.OfType<MenuItem>().Where(m => (m.Header as string) == "_Debugger");
foreach (var item in items.First().Items.OfType<MenuItem>()) {
string header = (string)item.Header;
if (header.StartsWith("Attach") || header.StartsWith("Debug"))
item.IsEnabled = enable;
else
item.IsEnabled = !enable;
}

//toolbar
var buttons = toolbarItems.OfType<Button>().Where(b => (b.Tag as string) == "Debugger");
foreach (var item in buttons) {
item.IsEnabled = enable;
}
}

void CurrentDebugger_IsProcessRunningChanged(object sender, EventArgs e)
{
if (CurrentDebugger.IsProcessRunning) {
//SendWpfWindowPos(this, HWND_BOTTOM);
return;
}

// breakpoint was hit => bring to front the main window
SendWpfWindowPos(MainWindow.Instance, HWND_TOP);
MainWindow.Instance.Activate();

// jump to type & expand folding
if (CurrentLineBookmark.Instance != null) {
if (CurrentLineBookmark.Instance.Type != DebugData.CurrentType)
MainWindow.Instance.JumpToReference(CurrentLineBookmark.Instance.Type);

MainWindow.Instance.TextView.UnfoldAndScroll(CurrentLineBookmark.Instance.LineNumber);
}
}
}

[ExportToolbarCommand(ToolTip = "Attach to running application",
ToolbarIcon = "ILSpy.Debugger;component/Images/bug.png",
ToolbarCategory = "Debugger",
Tag = "Debugger",
ToolbarOrder = 0)]
[ExportMainMenuCommand(Menu = "_Debugger",
MenuIcon = "ILSpy.Debugger;component/Images/bug.png",
MenuCategory = "Debugger1",
Header = "Attach to _running application",
MenuOrder = 0)]
internal sealed class AttachCommand : DebuggerCommands
{
public override void Execute(object parameter)
{
if (!CurrentDebugger.IsDebugging) {
var window = new AttachToProcessWindow { Owner = MainWindow.Instance };
if (window.ShowDialog() == true) {
StartDebugging(window.SelectedProcess);
}
}
}
}

[ExportMainMenuCommand(Menu = "_Debugger",
MenuIcon = "ILSpy.Debugger;component/Images/ContinueDebugging.png",
MenuCategory = "Debugger1",
Header = "Continue debugging",
MenuOrder = 1)]
internal sealed class ContinueDebuggingCommand : DebuggerCommands
{
public override void Execute(object parameter)
{
if (CurrentDebugger.IsDebugging && !CurrentDebugger.IsProcessRunning)
CurrentDebugger.Continue();
}
}

[ExportMainMenuCommand(Menu = "_Debugger",
MenuIcon = "ILSpy.Debugger;component/Images/StepInto.png",
MenuCategory = "Debugger1",
Header = "Step into",
MenuOrder = 2)]
internal sealed class StepIntoCommand : DebuggerCommands
{
public override void Execute(object parameter)
{
if (CurrentDebugger.IsDebugging && !CurrentDebugger.IsProcessRunning)
CurrentDebugger.StepInto();
}
}

[ExportMainMenuCommand(Menu = "_Debugger",
MenuIcon = "ILSpy.Debugger;component/Images/StepOver.png",
MenuCategory = "Debugger1",
Header = "Step over",
MenuOrder = 3)]
internal sealed class StepOverCommand : DebuggerCommands
{
public override void Execute(object parameter)
{
if (CurrentDebugger.IsDebugging && !CurrentDebugger.IsProcessRunning)
CurrentDebugger.StepOver();
}
}

[ExportMainMenuCommand(Menu = "_Debugger",
MenuIcon = "ILSpy.Debugger;component/Images/StepOut.png",
MenuCategory = "Debugger1",
Header = "Step out",
MenuOrder = 4)]
internal sealed class StepOutCommand : DebuggerCommands
{
public override void Execute(object parameter)
{
if (CurrentDebugger.IsDebugging && !CurrentDebugger.IsProcessRunning)
CurrentDebugger.StepOut();
}
}

[ExportMainMenuCommand(Menu = "_Debugger",
MenuCategory = "Debugger1",
Header = "_Detach from running application",
MenuOrder = 5)]
internal sealed class DetachCommand : DebuggerCommands
{
public override void Execute(object parameter)
{
if (CurrentDebugger.IsDebugging){
CurrentDebugger.Detach();

EnableDebuggerUI(true);
CurrentDebugger.DebugStopped -= OnDebugStopped;
}
}
}

[ExportMainMenuCommand(Menu = "_Debugger",
MenuIcon = "ILSpy.Debugger;component/Images/DeleteAllBreakpoints.png",
MenuCategory = "Debugger2",
Header = "Remove all _breakpoints",
MenuOrder = 6)]
internal sealed class RemoveBreakpointsCommand : DebuggerCommands
{
public override void Execute(object parameter)
{
for (int i = BookmarkManager.Bookmarks.Count - 1; i >= 0; --i) {
var bookmark = BookmarkManager.Bookmarks[i];
if (bookmark is BreakpointBookmark) {
BookmarkManager.RemoveMark(bookmark);
}
}
}
}

[ExportToolbarCommand(ToolTip = "Debug an executable",
ToolbarIcon = "ILSpy.Debugger;component/Images/application-x-executable.png",
ToolbarCategory = "Debugger",
Tag = "Debugger",
ToolbarOrder = 0)]
[ExportMainMenuCommand(Menu = "_Debugger",
MenuIcon = "ILSpy.Debugger;component/Images/application-x-executable.png",
MenuCategory = "Debugger3",
Header = "Debug an _executable",
MenuOrder = 7)]
internal sealed class DebugExecutableCommand : DebuggerCommands
{
public override void Execute(object parameter)
{
OpenFileDialog dialog = new OpenFileDialog() {
Filter = ".NET Executable (*.exe) | *.exe",
RestoreDirectory = true,
DefaultExt = "exe"
};

if (dialog.ShowDialog() == true) {
string fileName = dialog.FileName;

// add it to references
MainWindow.Instance.OpenFiles(new [] { fileName }, false);

if (!CurrentDebugger.IsDebugging) {
// execute the process
this.StartDebugging(Process.Start(fileName));
}
}
}
}
}

0 comments on commit 33d4843

Please sign in to comment.