Browse Source

Use MEF for debugger commands.

pull/191/merge
Eusebiu Marcu 16 years ago
parent
commit
33d4843f5d
  1. 24
      Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs
  2. 2
      Debugger/ILSpy.Debugger/AvalonEdit/TextMarkerService.cs
  3. 2
      Debugger/ILSpy.Debugger/DebuggedType.cs
  4. 2
      Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs
  5. 1
      ILSpy/AboutPage.cs
  6. 288
      ILSpy/Commands/DebuggerCommands.cs
  7. 3
      ILSpy/ExportCommandAttribute.cs
  8. 1
      ILSpy/ILSpy.csproj
  9. 17
      ILSpy/MainWindow.xaml.cs
  10. 6
      ILSpy/TextView/DecompilerTextView.cs
  11. 2
      ILSpy/TreeNodes/TypeTreeNode.cs

24
Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs

@ -57,10 +57,10 @@ namespace ILSpy.Debugger.AvalonEdit @@ -57,10 +57,10 @@ namespace ILSpy.Debugger.AvalonEdit
// 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;
@ -119,8 +119,8 @@ namespace ILSpy.Debugger.AvalonEdit @@ -119,8 +119,8 @@ namespace ILSpy.Debugger.AvalonEdit
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;
}
@ -189,11 +189,11 @@ namespace ILSpy.Debugger.AvalonEdit @@ -189,11 +189,11 @@ namespace ILSpy.Debugger.AvalonEdit
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;
@ -226,24 +226,24 @@ namespace ILSpy.Debugger.AvalonEdit @@ -226,24 +226,24 @@ namespace ILSpy.Debugger.AvalonEdit
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();

2
Debugger/ILSpy.Debugger/AvalonEdit/TextMarkerService.cs

@ -45,7 +45,7 @@ namespace ILSpy.Debugger.AvalonEdit @@ -45,7 +45,7 @@ namespace ILSpy.Debugger.AvalonEdit
{
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);

2
Debugger/ILSpy.Debugger/DebuggedType.cs

@ -25,7 +25,7 @@ namespace ILSpy.Debugger @@ -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

2
Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs

@ -49,7 +49,7 @@ namespace ILSpy.Debugger.Services @@ -49,7 +49,7 @@ namespace ILSpy.Debugger.Services
private ConcurrentDictionary<string, List<MethodMapping>> CodeMappingsStorage {
get {
return CodeMappings.GetStorage(DebuggedData.Language);
return CodeMappings.GetStorage(DebugData.Language);
}
}

1
ILSpy/AboutPage.cs

@ -29,6 +29,7 @@ namespace ICSharpCode.ILSpy @@ -29,6 +29,7 @@ namespace ICSharpCode.ILSpy
public override void Execute(object parameter)
{
MainWindow.Instance.UnselectAll();
Display(decompilerTextView);
}

288
ILSpy/Commands/DebuggerCommands.cs

@ -0,0 +1,288 @@ @@ -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));
}
}
}
}
}

3
ILSpy/ExportCommandAttribute.cs

@ -13,7 +13,7 @@ namespace ICSharpCode.ILSpy @@ -13,7 +13,7 @@ namespace ICSharpCode.ILSpy
string ToolbarIcon { get; }
string ToolTip { get; }
string ToolbarCategory { get; }
object Tag { get; }
double ToolbarOrder { get; }
}
@ -30,6 +30,7 @@ namespace ICSharpCode.ILSpy @@ -30,6 +30,7 @@ namespace ICSharpCode.ILSpy
public string ToolbarIcon { get; set; }
public string ToolbarCategory { get; set; }
public double ToolbarOrder { get; set; }
public object Tag { get; set; }
}
#endregion

1
ILSpy/ILSpy.csproj

@ -90,6 +90,7 @@ @@ -90,6 +90,7 @@
<Compile Include="AssemblyListManager.cs" />
<Compile Include="BamlDecompiler.cs" />
<Compile Include="Commands.cs" />
<Compile Include="Commands\DebuggerCommands.cs" />
<Compile Include="Controls\SearchBox.cs" />
<Compile Include="Controls\SortableGridViewColumn.cs" />
<Compile Include="CSharpLanguage.cs" />

17
ILSpy/MainWindow.xaml.cs

@ -138,6 +138,7 @@ namespace ICSharpCode.ILSpy @@ -138,6 +138,7 @@ namespace ICSharpCode.ILSpy
return new Button {
Command = CommandWrapper.Unwrap(command.Value),
ToolTip = command.Metadata.ToolTip,
Tag = command.Metadata.Tag,
Content = new Image {
Width = 16,
Height = 16,
@ -395,22 +396,25 @@ namespace ICSharpCode.ILSpy @@ -395,22 +396,25 @@ namespace ICSharpCode.ILSpy
}
}
public void OpenFiles(string[] fileNames)
public void OpenFiles(string[] fileNames, bool focusNode = true)
{
if (fileNames == null)
throw new ArgumentNullException("fileNames");
if (focusNode)
treeView.UnselectAll();
SharpTreeNode lastNode = null;
foreach (string file in fileNames) {
var asm = assemblyList.OpenAssembly(file);
if (asm != null) {
var node = assemblyListTreeNode.FindAssemblyNode(asm);
if (node != null) {
if (node != null && focusNode) {
treeView.SelectedItems.Add(node);
lastNode = node;
}
}
if (lastNode != null)
if (lastNode != null && focusNode)
treeView.FocusNode(lastNode);
}
}
@ -539,7 +543,12 @@ namespace ICSharpCode.ILSpy @@ -539,7 +543,12 @@ namespace ICSharpCode.ILSpy
void LanguageComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
DebuggedData.Language = sessionSettings.FilterSettings.Language.Name.StartsWith("IL") ? DecompiledLanguages.IL : DecompiledLanguages.CSharp;
DebugData.Language = sessionSettings.FilterSettings.Language.Name.StartsWith("IL") ? DecompiledLanguages.IL : DecompiledLanguages.CSharp;
}
public void UnselectAll()
{
treeView.UnselectAll();
}
}
}

6
ILSpy/TextView/DecompilerTextView.cs

@ -332,7 +332,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -332,7 +332,7 @@ namespace ICSharpCode.ILSpy.TextView
/// </summary>
public void Decompile(ILSpy.Language language, IEnumerable<ILSpyTreeNode> treeNodes, DecompilationOptions options)
{
DebuggedData.CurrentType = null;
DebugData.CurrentType = null;
// Some actions like loading an assembly list cause several selection changes in the tree view,
// and each of those will start a decompilation action.
bool isDecompilationScheduled = this.nextDecompilationRun != null;
@ -396,8 +396,8 @@ namespace ICSharpCode.ILSpy.TextView @@ -396,8 +396,8 @@ namespace ICSharpCode.ILSpy.TextView
// show the currentline marker
var bm = CurrentLineBookmark.Instance;
if (bm != null && DebuggedData.CurrentType != null) {
if (DebuggedData.CurrentType.FullName.Equals(bm.Type.FullName, StringComparison.OrdinalIgnoreCase)) {
if (bm != null && DebugData.CurrentType != null) {
if (DebugData.CurrentType.FullName.Equals(bm.Type.FullName, StringComparison.OrdinalIgnoreCase)) {
DocumentLine line = textEditor.Document.GetLineByNumber(bm.LineNumber);
bm.Marker = bm.CreateMarker(textMarkerService, line.Offset, line.Length);
UnfoldAndScroll(bm.LineNumber);

2
ILSpy/TreeNodes/TypeTreeNode.cs

@ -129,7 +129,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -129,7 +129,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
DebuggedData.CurrentType = type;
DebugData.CurrentType = type;
language.DecompileType(type, output, options);
}

Loading…
Cancel
Save