Browse Source

Fix IL Code mappings;

Unfold and scroll when hitting a BP.
Jump to the type that has a BP when the BP is hit.
pull/191/merge
Eusebiu Marcu 14 years ago
parent
commit
572c79f097
  1. 24
      Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs
  2. 7
      Debugger/ILSpy.Debugger/AvalonEdit/TextMarkerService.cs
  3. 7
      Debugger/ILSpy.Debugger/Bookmarks/BookmarkBase.cs
  4. 4
      Debugger/ILSpy.Debugger/Bookmarks/BookmarkManager.cs
  5. 3
      Debugger/ILSpy.Debugger/Bookmarks/BreakpointBookmark.cs
  6. 7
      Debugger/ILSpy.Debugger/Bookmarks/CurrentLineBookmark.cs
  7. 3
      Debugger/ILSpy.Debugger/Bookmarks/MarkerBookmark.cs
  8. 21
      Debugger/ILSpy.Debugger/DebuggedType.cs
  9. 32
      Debugger/ILSpy.Debugger/Models/TreeModel/ExpressionNode.cs
  10. 11
      Debugger/ILSpy.Debugger/Services/Debugger/DebuggerService.cs
  11. 5
      Debugger/ILSpy.Debugger/Services/Debugger/IDebugger.cs
  12. 62
      Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs
  13. 17
      Debugger/ILSpy.Debugger/UI/AttachToProcessWindow.xaml.cs
  14. 2
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  15. 12
      ICSharpCode.Decompiler/CodeMappings.cs
  16. 2
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  17. 6
      ILSpy.sln
  18. 102
      ILSpy/MainWindow.xaml.cs
  19. 36
      ILSpy/TextView/DecompilerTextView.cs
  20. 2
      ILSpy/TreeNodes/TypeTreeNode.cs

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

@ -57,10 +57,10 @@ namespace ILSpy.Debugger.AvalonEdit
// create a dictionary line number => first bookmark // create a dictionary line number => first bookmark
Dictionary<int, BookmarkBase> bookmarkDict = new Dictionary<int, BookmarkBase>(); Dictionary<int, BookmarkBase> bookmarkDict = new Dictionary<int, BookmarkBase>();
foreach (var bm in BookmarkManager.Bookmarks) { foreach (var bm in BookmarkManager.Bookmarks) {
if (DebuggedType.CurrentType == null || bm.TypeName != DebuggedType.CurrentType.FullName) if (DebuggedData.CurrentType == null || bm.Type.FullName != DebuggedData.CurrentType.FullName)
continue; continue;
if (bm is BreakpointBookmark && if (bm is BreakpointBookmark &&
((BreakpointBookmark)bm).Language != DebuggerService.CurrentDebugger.Language) ((BreakpointBookmark)bm).Language != DebuggedData.Language)
continue; continue;
int line = bm.LineNumber; int line = bm.LineNumber;
@ -119,8 +119,8 @@ namespace ILSpy.Debugger.AvalonEdit
BookmarkBase result = null; BookmarkBase result = null;
foreach (BookmarkBase bm in BookmarkManager.Bookmarks) { foreach (BookmarkBase bm in BookmarkManager.Bookmarks) {
if (bm.LineNumber == line && if (bm.LineNumber == line &&
DebuggedType.CurrentType != null && DebuggedData.CurrentType != null &&
bm.TypeName == DebuggedType.CurrentType.FullName) { bm.Type.FullName == DebuggedData.CurrentType.FullName) {
if (result == null || bm.ZOrder > result.ZOrder) if (result == null || bm.ZOrder > result.ZOrder)
result = bm; result = bm;
} }
@ -189,11 +189,11 @@ namespace ILSpy.Debugger.AvalonEdit
InvalidateVisual(); InvalidateVisual();
} }
if (DebuggedType.CurrentType == null) if (DebuggedData.CurrentType == null)
return; return;
BreakpointBookmark bm = BookmarkManager.Bookmarks.Find( BreakpointBookmark bm = BookmarkManager.Bookmarks.Find(
b => b.TypeName == DebuggedType.CurrentType.FullName && b => b.Type.FullName == DebuggedData.CurrentType.FullName &&
b.LineNumber == GetLineFromMousePosition(e) b.LineNumber == GetLineFromMousePosition(e)
&& b is BreakpointBookmark) as BreakpointBookmark; && b is BreakpointBookmark) as BreakpointBookmark;
@ -226,24 +226,24 @@ namespace ILSpy.Debugger.AvalonEdit
return; return;
} }
if (e.ChangedButton == MouseButton.Left) { if (e.ChangedButton == MouseButton.Left) {
if (DebuggedType.CurrentType != null) { if (DebuggedData.CurrentType != null) {
// check if the codemappings exists for this line // check if the codemappings exists for this line
var storage = CodeMappings.GetStorage(DebuggerService.CurrentDebugger.Language); var storage = CodeMappings.GetStorage(DebuggedData.Language);
uint token; uint token;
var instruction = storage.GetInstructionByTypeAndLine(DebuggedType.CurrentType.FullName, line, out token); var instruction = storage.GetInstructionByTypeAndLine(DebuggedData.CurrentType.FullName, line, out token);
if (instruction == null || instruction.ILInstructionOffset.From == 0) { if (instruction == null || instruction.ILInstructionOffset.From == 0) {
MessageBox.Show(string.Format("Missing code mappings for {0} at line {1}", DebuggedType.CurrentType.FullName, line), MessageBox.Show(string.Format("Missing code mappings for {0} at line {1}", DebuggedData.CurrentType.FullName, line),
"Code mappings", MessageBoxButton.OK, MessageBoxImage.Information); "Code mappings", MessageBoxButton.OK, MessageBoxImage.Information);
return; return;
} }
// no bookmark on the line: create a new breakpoint // no bookmark on the line: create a new breakpoint
DebuggerService.ToggleBreakpointAt( DebuggerService.ToggleBreakpointAt(
DebuggedType.CurrentType.FullName, DebuggedData.CurrentType,
line, line,
DebuggerService.CurrentDebugger.Language); DebuggedData.Language);
} }
} }
InvalidateVisual(); InvalidateVisual();

7
Debugger/ILSpy.Debugger/AvalonEdit/TextMarkerService.cs

@ -45,8 +45,11 @@ namespace ILSpy.Debugger.AvalonEdit
{ {
if (e.Bookmark is MarkerBookmark) { if (e.Bookmark is MarkerBookmark) {
var bm = (MarkerBookmark)e.Bookmark; var bm = (MarkerBookmark)e.Bookmark;
DocumentLine line = codeEditor.Document.GetLineByNumber(bm.LineNumber); if (DebuggedData.CurrentType != null && DebuggedData.CurrentType.FullName.Equals(bm.Type.FullName, StringComparison.OrdinalIgnoreCase)) {
bm.Marker = bm.CreateMarker(this, line.Offset, line.Length); // add bookmark for the current type
DocumentLine line = codeEditor.Document.GetLineByNumber(bm.LineNumber);
bm.Marker = bm.CreateMarker(this, line.Offset, line.Length);
}
} }
} }

7
Debugger/ILSpy.Debugger/Bookmarks/BookmarkBase.cs

@ -6,6 +6,7 @@ using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp;
using Mono.Cecil;
namespace ILSpy.Debugger.Bookmarks namespace ILSpy.Debugger.Bookmarks
{ {
@ -40,7 +41,7 @@ namespace ILSpy.Debugger.Bookmarks
} }
public string TypeName { get; set; } public TypeDefinition Type { get; set; }
public int LineNumber { public int LineNumber {
get { return location.Line; } get { return location.Line; }
@ -63,9 +64,9 @@ namespace ILSpy.Debugger.Bookmarks
} }
} }
public BookmarkBase(string typeName, AstLocation location) public BookmarkBase(TypeDefinition type, AstLocation location)
{ {
this.TypeName = typeName; this.Type = type;
this.Location = location; this.Location = location;
} }

4
Debugger/ILSpy.Debugger/Bookmarks/BookmarkManager.cs

@ -29,7 +29,7 @@ namespace ILSpy.Debugger.Bookmarks
List<BookmarkBase> marks = new List<BookmarkBase>(); List<BookmarkBase> marks = new List<BookmarkBase>();
foreach (BookmarkBase mark in bookmarks) { foreach (BookmarkBase mark in bookmarks) {
if (typeName == mark.TypeName) { if (typeName == mark.Type.FullName) {
marks.Add(mark); marks.Add(mark);
} }
} }
@ -54,7 +54,7 @@ namespace ILSpy.Debugger.Bookmarks
return false; return false;
if (a.GetType() != b.GetType()) if (a.GetType() != b.GetType())
return false; return false;
if (a.TypeName != b.TypeName) if (a.Type.FullName != b.Type.FullName)
return false; return false;
return a.LineNumber == b.LineNumber; return a.LineNumber == b.LineNumber;
} }

3
Debugger/ILSpy.Debugger/Bookmarks/BreakpointBookmark.cs

@ -8,6 +8,7 @@ using ICSharpCode.Decompiler;
using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp;
using ILSpy.Debugger.AvalonEdit; using ILSpy.Debugger.AvalonEdit;
using ILSpy.Debugger.Services; using ILSpy.Debugger.Services;
using Mono.Cecil;
namespace ILSpy.Debugger.Bookmarks namespace ILSpy.Debugger.Bookmarks
{ {
@ -72,7 +73,7 @@ namespace ILSpy.Debugger.Bookmarks
set { tooltip = value; } set { tooltip = value; }
} }
public BreakpointBookmark(string typeName, AstLocation location, BreakpointAction action, DecompiledLanguages language) : base(typeName, location) public BreakpointBookmark(TypeDefinition type, AstLocation location, BreakpointAction action, DecompiledLanguages language) : base(type, location)
{ {
this.action = action; this.action = action;
this.tooltip = language.ToString(); this.tooltip = language.ToString();

7
Debugger/ILSpy.Debugger/Bookmarks/CurrentLineBookmark.cs

@ -6,6 +6,7 @@ using System.Windows.Media;
using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp;
using ILSpy.Debugger.AvalonEdit; using ILSpy.Debugger.AvalonEdit;
using ILSpy.Debugger.Services; using ILSpy.Debugger.Services;
using Mono.Cecil;
using Mono.CSharp; using Mono.CSharp;
namespace ILSpy.Debugger.Bookmarks namespace ILSpy.Debugger.Bookmarks
@ -23,7 +24,7 @@ namespace ILSpy.Debugger.Bookmarks
static int endLine; static int endLine;
static int endColumn; static int endColumn;
public static void SetPosition(string typeName, int makerStartLine, int makerStartColumn, int makerEndLine, int makerEndColumn) public static void SetPosition(TypeDefinition type, int makerStartLine, int makerStartColumn, int makerEndLine, int makerEndColumn)
{ {
Remove(); Remove();
@ -32,7 +33,7 @@ namespace ILSpy.Debugger.Bookmarks
endLine = makerEndLine; endLine = makerEndLine;
endColumn = makerEndColumn; endColumn = makerEndColumn;
instance = new CurrentLineBookmark(typeName, new AstLocation(startLine, startColumn)); instance = new CurrentLineBookmark(type, new AstLocation(startLine, startColumn));
BookmarkManager.AddMark(instance); BookmarkManager.AddMark(instance);
} }
@ -52,7 +53,7 @@ namespace ILSpy.Debugger.Bookmarks
get { return 100; } get { return 100; }
} }
public CurrentLineBookmark(string typeName, AstLocation location) : base(typeName, location) public CurrentLineBookmark(TypeDefinition type, AstLocation location) : base(type, location)
{ {
} }

3
Debugger/ILSpy.Debugger/Bookmarks/MarkerBookmark.cs

@ -4,12 +4,13 @@
using System; using System;
using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp;
using ILSpy.Debugger.AvalonEdit; using ILSpy.Debugger.AvalonEdit;
using Mono.Cecil;
namespace ILSpy.Debugger.Bookmarks namespace ILSpy.Debugger.Bookmarks
{ {
public abstract class MarkerBookmark : BookmarkBase public abstract class MarkerBookmark : BookmarkBase
{ {
public MarkerBookmark(string typeName, AstLocation location) : base(typeName, location) public MarkerBookmark(TypeDefinition type, AstLocation location) : base(type, location)
{ {
} }

21
Debugger/ILSpy.Debugger/DebuggedType.cs

@ -17,17 +17,24 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using ICSharpCode.Decompiler;
using Mono.Cecil; using Mono.Cecil;
namespace ILSpy.Debugger namespace ILSpy.Debugger
{ {
public static class DebuggedType /// <summary>
/// Contains the data important for debugger from the main application.
/// </summary>
public static class DebuggedData
{ {
static TypeDefinition currentTypeName; /// <summary>
/// Gets or sets the current debugged type
public static TypeDefinition CurrentType { /// </summary>
get { return currentTypeName; } public static TypeDefinition CurrentType { get; set; }
set { currentTypeName = value; }
} /// <summary>
/// Gets or sets the decompiled language.
/// </summary>
public static DecompiledLanguages Language { get; set; }
} }
} }

32
Debugger/ILSpy.Debugger/Models/TreeModel/ExpressionNode.cs

@ -257,22 +257,22 @@ namespace ILSpy.Debugger.Models.TreeModel
if (true) if (true)
return i.ToString(); return i.ToString();
string hex = null; // string hex = null;
for(int len = 1;; len *= 2) { // for(int len = 1;; len *= 2) {
hex = string.Format("{0:X" + len + "}", i); // hex = string.Format("{0:X" + len + "}", i);
if (hex.Length == len) // if (hex.Length == len)
break; // break;
} // }
//
if (true) { // if (true) {
return "0x" + hex; // return "0x" + hex;
} else { // } else {
if (ShowAsHex(i)) { // if (ShowAsHex(i)) {
return String.Format("{0} (0x{1})", i, hex); // return String.Format("{0} (0x{1})", i, hex);
} else { // } else {
return i.ToString(); // return i.ToString();
} // }
} // }
} }
bool ShowAsHex(object i) bool ShowAsHex(object i)

11
Debugger/ILSpy.Debugger/Services/Debugger/DebuggerService.cs

@ -8,6 +8,7 @@ using ICSharpCode.Decompiler;
using ICSharpCode.NRefactory.CSharp.Resolver; using ICSharpCode.NRefactory.CSharp.Resolver;
using ILSpy.Debugger.Bookmarks; using ILSpy.Debugger.Bookmarks;
using ILSpy.Debugger.ToolTips; using ILSpy.Debugger.ToolTips;
using Mono.Cecil;
namespace ILSpy.Debugger.Services namespace ILSpy.Debugger.Services
{ {
@ -162,12 +163,12 @@ namespace ILSpy.Debugger.Services
} }
} }
public static void ToggleBreakpointAt(string typeName, int lineNumber, DecompiledLanguages language) public static void ToggleBreakpointAt(TypeDefinition type, int lineNumber, DecompiledLanguages language)
{ {
BookmarkManager.ToggleBookmark( BookmarkManager.ToggleBookmark(
typeName, lineNumber, type.FullName, lineNumber,
b => b.CanToggle && b is BreakpointBookmark, b => b.CanToggle && b is BreakpointBookmark,
location => new BreakpointBookmark(typeName, location, BreakpointAction.Break, language)); location => new BreakpointBookmark(type, location, BreakpointAction.Break, language));
} }
/* TODO: reimplement this stuff /* TODO: reimplement this stuff
@ -183,9 +184,9 @@ namespace ILSpy.Debugger.Services
CurrentLineBookmark.Remove(); CurrentLineBookmark.Remove();
} }
public static void JumpToCurrentLine(string typeName, int startLine, int startColumn, int endLine, int endColumn) public static void JumpToCurrentLine(TypeDefinition type, int startLine, int startColumn, int endLine, int endColumn)
{ {
CurrentLineBookmark.SetPosition(typeName, startLine, startColumn, endLine, endColumn); CurrentLineBookmark.SetPosition(type, startLine, startColumn, endLine, endColumn);
} }
#region Tool tips #region Tool tips

5
Debugger/ILSpy.Debugger/Services/Debugger/IDebugger.cs

@ -10,11 +10,6 @@ namespace ILSpy.Debugger.Services
{ {
public interface IDebugger : IDisposable public interface IDebugger : IDisposable
{ {
/// <summary>
/// Gets or sets the decompiled language.
/// </summary>
DecompiledLanguages Language { get; set; }
/// <summary> /// <summary>
/// Gets whether the debugger can evaluate the expression. /// Gets whether the debugger can evaluate the expression.
/// </summary> /// </summary>

62
Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs

@ -20,6 +20,7 @@ using ILSpy.Debugger.Bookmarks;
using ILSpy.Debugger.Models.TreeModel; using ILSpy.Debugger.Models.TreeModel;
using ILSpy.Debugger.Services.Debugger; using ILSpy.Debugger.Services.Debugger;
using ILSpy.Debugger.Tooltips; using ILSpy.Debugger.Tooltips;
using Mono.Cecil;
using CorDbg = Debugger; using CorDbg = Debugger;
using Process = Debugger.Process; using Process = Debugger.Process;
using StackFrame = Debugger.StackFrame; using StackFrame = Debugger.StackFrame;
@ -48,7 +49,7 @@ namespace ILSpy.Debugger.Services
private ConcurrentDictionary<string, List<MethodMapping>> CodeMappingsStorage { private ConcurrentDictionary<string, List<MethodMapping>> CodeMappingsStorage {
get { get {
return CodeMappings.GetStorage(Language); return CodeMappings.GetStorage(DebuggedData.Language);
} }
} }
@ -109,8 +110,6 @@ namespace ILSpy.Debugger.Services
string errorProcessPaused = "Error.ProcessPaused"; string errorProcessPaused = "Error.ProcessPaused";
string errorCannotStepNoActiveFunction = "Threads.CannotStepNoActiveFunction"; string errorCannotStepNoActiveFunction = "Threads.CannotStepNoActiveFunction";
public DecompiledLanguages Language { get; set; }
public bool IsDebugging { public bool IsDebugging {
get { get {
return ServiceInitialized && debuggedProcess != null; return ServiceInitialized && debuggedProcess != null;
@ -289,10 +288,10 @@ namespace ILSpy.Debugger.Services
// get the mapped instruction from the current line marker or the next one // get the mapped instruction from the current line marker or the next one
uint token; uint token;
var instruction = CodeMappingsStorage.GetInstructionByTypeAndLine( var instruction = CodeMappingsStorage.GetInstructionByTypeAndLine(
CurrentLineBookmark.Instance.TypeName, CurrentLineBookmark.Instance.Type.FullName,
CurrentLineBookmark.Instance.LineNumber, out token); CurrentLineBookmark.Instance.LineNumber, out token);
var val = CodeMappingsStorage[CurrentLineBookmark.Instance.TypeName]; var val = CodeMappingsStorage[CurrentLineBookmark.Instance.Type.FullName];
var mapping = val.Find(m => m.MetadataToken == token); var mapping = val.Find(m => m.MetadataToken == token);
@ -560,21 +559,19 @@ namespace ILSpy.Debugger.Services
{ {
Breakpoint breakpoint = null; Breakpoint breakpoint = null;
if (Language == bookmark.Language) { uint token;
uint token; SourceCodeMapping map = CodeMappings
SourceCodeMapping map = .GetStorage(bookmark.Language)
CodeMappingsStorage.GetInstructionByTypeAndLine( .GetInstructionByTypeAndLine(bookmark.Type.FullName, bookmark.LineNumber, out token);
bookmark.TypeName, bookmark.LineNumber, out token);
if (map != null) {
if (map != null) { breakpoint = new ILBreakpoint(
breakpoint = new ILBreakpoint( debugger,
debugger, bookmark.Type.FullName,
bookmark.TypeName, bookmark.LineNumber,
bookmark.LineNumber, token,
token, map.ILInstructionOffset.From,
map.ILInstructionOffset.From, bookmark.IsEnabled);
bookmark.IsEnabled);
}
} }
if (breakpoint == null) if (breakpoint == null)
@ -748,7 +745,7 @@ namespace ILSpy.Debugger.Services
foreach (var bookmark in DebuggerService.Breakpoints) { foreach (var bookmark in DebuggerService.Breakpoints) {
var breakpoint = var breakpoint =
debugger.Breakpoints.FirstOrDefault( debugger.Breakpoints.FirstOrDefault(
b => b.Line == bookmark.LineNumber && b.TypeName == bookmark.TypeName); b => b.Line == bookmark.LineNumber && b.TypeName == bookmark.Type.FullName);
if (breakpoint == null) if (breakpoint == null)
continue; continue;
@ -758,22 +755,8 @@ namespace ILSpy.Debugger.Services
void debuggedProcess_DebuggingPaused(object sender, ProcessEventArgs e) void debuggedProcess_DebuggingPaused(object sender, ProcessEventArgs e)
{ {
OnIsProcessRunningChanged(EventArgs.Empty);
//using(new PrintTimes("Jump to current line")) {
JumpToCurrentLine(); JumpToCurrentLine();
//} OnIsProcessRunningChanged(EventArgs.Empty);
// 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, CorDbg.ProcessEventArgs e) void debuggedProcess_DebuggingResumed(object sender, CorDbg.ProcessEventArgs e)
@ -832,9 +815,10 @@ namespace ILSpy.Debugger.Services
uint token = (uint)frame.MethodInfo.MetadataToken; uint token = (uint)frame.MethodInfo.MetadataToken;
int ilOffset = frame.IP; int ilOffset = frame.IP;
int line; int line;
string typeName; TypeDefinition type;
if (CodeMappingsStorage.GetSourceCodeFromMetadataTokenAndOffset(token, ilOffset, out typeName, out line)) if (CodeMappingsStorage.GetSourceCodeFromMetadataTokenAndOffset(token, ilOffset, out type, out line)) {
DebuggerService.JumpToCurrentLine(typeName, line, 0, line, 0); DebuggerService.JumpToCurrentLine(type, line, 0, line, 0);
}
} }
} }

17
Debugger/ILSpy.Debugger/UI/AttachToProcessWindow.xaml.cs

@ -10,7 +10,6 @@ using System.Linq;
using System.Windows; using System.Windows;
using ILSpy.Debugger.Models; using ILSpy.Debugger.Models;
using ILSpy.Debugger.Services;
namespace ILSpy.Debugger.UI namespace ILSpy.Debugger.UI
{ {
@ -25,6 +24,15 @@ namespace ILSpy.Debugger.UI
Loaded += OnLoaded; Loaded += OnLoaded;
} }
public Process SelectedProcess {
get {
if (this.RunningProcesses.SelectedItem != null)
return ((RunningProcess)this.RunningProcesses.SelectedItem).Process;
return null;
}
}
void RefreshProcessList() void RefreshProcessList()
{ {
@ -51,8 +59,8 @@ namespace ILSpy.Debugger.UI
FileName = process.MainModule.FileName, FileName = process.MainModule.FileName,
WindowTitle = process.MainWindowTitle, WindowTitle = process.MainWindowTitle,
Managed = "Managed", Managed = "Managed",
Process = process Process = process
}); });
} }
} }
} catch (Win32Exception) { } catch (Win32Exception) {
@ -68,9 +76,6 @@ namespace ILSpy.Debugger.UI
if (this.RunningProcesses.SelectedItem == null) if (this.RunningProcesses.SelectedItem == null)
return; return;
// start attaching
var process = ((RunningProcess)this.RunningProcesses.SelectedItem).Process;
DebuggerService.CurrentDebugger.Attach(process);
this.DialogResult = true; this.DialogResult = true;
} }

2
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -137,7 +137,7 @@ namespace Decompiler
public TypeDeclaration CreateType(TypeDefinition typeDef) public TypeDeclaration CreateType(TypeDefinition typeDef)
{ {
// create IL code mappings - used for debugger // create CSharp code mappings - used for debugger
if (!CSharpCodeMapping.SourceCodeMappings.ContainsKey(typeDef.FullName)) { if (!CSharpCodeMapping.SourceCodeMappings.ContainsKey(typeDef.FullName)) {
CSharpCodeMapping.SourceCodeMappings.TryAdd(typeDef.FullName, new List<MethodMapping>()); CSharpCodeMapping.SourceCodeMappings.TryAdd(typeDef.FullName, new List<MethodMapping>());
} else { } else {

12
ICSharpCode.Decompiler/CodeMappings.cs

@ -42,7 +42,7 @@ namespace ICSharpCode.Decompiler
/// </summary> /// </summary>
public sealed class MethodMapping public sealed class MethodMapping
{ {
public string TypeName { get; set; } public TypeDefinition Type { get; set; }
public uint MetadataToken { get; set; } public uint MetadataToken { get; set; }
@ -100,7 +100,7 @@ namespace ICSharpCode.Decompiler
if (mapping.Find(map => (int)map.MetadataToken == method.MetadataToken.ToInt32()) == null) { if (mapping.Find(map => (int)map.MetadataToken == method.MetadataToken.ToInt32()) == null) {
currentMethodMapping = new MethodMapping() { currentMethodMapping = new MethodMapping() {
MetadataToken = (uint)method.MetadataToken.ToInt32(), MetadataToken = (uint)method.MetadataToken.ToInt32(),
TypeName = method.DeclaringType.FullName, Type = method.DeclaringType,
MethodCodeMappings = new List<SourceCodeMapping>() MethodCodeMappings = new List<SourceCodeMapping>()
}; };
mapping.Add(currentMethodMapping); mapping.Add(currentMethodMapping);
@ -153,16 +153,16 @@ namespace ICSharpCode.Decompiler
/// <param name="codeMappings">Code mappings storage.</param> /// <param name="codeMappings">Code mappings storage.</param>
/// <param name="token">Metadata token.</param> /// <param name="token">Metadata token.</param>
/// <param name="ilOffset">IL offset.</param> /// <param name="ilOffset">IL offset.</param>
/// <param name="typeName">Type name.</param> /// <param name="typeName">Type definition.</param>
/// <param name="line">Line number.</param> /// <param name="line">Line number.</param>
public static bool GetSourceCodeFromMetadataTokenAndOffset( public static bool GetSourceCodeFromMetadataTokenAndOffset(
this ConcurrentDictionary<string, List<MethodMapping>> codeMappings, this ConcurrentDictionary<string, List<MethodMapping>> codeMappings,
uint token, uint token,
int ilOffset, int ilOffset,
out string typeName, out TypeDefinition type,
out int line) out int line)
{ {
typeName = null; type = null;
line = 0; line = 0;
foreach (var typename in codeMappings.Keys) { foreach (var typename in codeMappings.Keys) {
@ -182,7 +182,7 @@ namespace ICSharpCode.Decompiler
} }
typeName = typename; type = mapping.Type;
line = codeMapping.SourceCodeLine; line = codeMapping.SourceCodeLine;
return true; return true;
} }

2
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -316,7 +316,7 @@ namespace ICSharpCode.Decompiler.Disassembler
if (!ILCodeMapping.SourceCodeMappings.ContainsKey(type.FullName)) { if (!ILCodeMapping.SourceCodeMappings.ContainsKey(type.FullName)) {
ILCodeMapping.SourceCodeMappings.TryAdd(type.FullName, new List<MethodMapping>()); ILCodeMapping.SourceCodeMappings.TryAdd(type.FullName, new List<MethodMapping>());
} else { } else {
ILCodeMapping.SourceCodeMappings.Clear(); ILCodeMapping.SourceCodeMappings[type.FullName].Clear();
} }
// start writing IL // start writing IL

6
ILSpy.sln

@ -1,7 +1,7 @@
 
Microsoft Visual Studio Solution File, Format Version 11.00 Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010 # Visual Studio 2010
# SharpDevelop 4.1.0.7302-alpha # SharpDevelop 4.1.0.7322-alpha
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Debugger", "Debugger", "{1DEB3B4E-03AC-437C-821D-B09FBFCC3E5B}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Debugger", "Debugger", "{1DEB3B4E-03AC-437C-821D-B09FBFCC3E5B}"
ProjectSection(SolutionItems) = postProject ProjectSection(SolutionItems) = postProject
EndProjectSection EndProjectSection
@ -108,4 +108,8 @@ Global
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
EndGlobalSection EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{6D3D0F0D-348D-456A-A6ED-E9BD5EFABB6A} = {1DEB3B4E-03AC-437C-821D-B09FBFCC3E5B}
{1D18D788-F7EE-4585-A23B-34DC8EC63CB8} = {1DEB3B4E-03AC-437C-821D-B09FBFCC3E5B}
EndGlobalSection
EndGlobal EndGlobal

102
ILSpy/MainWindow.xaml.cs

@ -26,12 +26,15 @@ using System.Threading.Tasks;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.FlowAnalysis; using ICSharpCode.Decompiler.FlowAnalysis;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.TreeNodes.Analyzer; using ICSharpCode.ILSpy.TreeNodes.Analyzer;
using ICSharpCode.TreeView; using ICSharpCode.TreeView;
using ILSpy.Debugger;
using ILSpy.Debugger.AvalonEdit; using ILSpy.Debugger.AvalonEdit;
using ILSpy.Debugger.Bookmarks; using ILSpy.Debugger.Bookmarks;
using ILSpy.Debugger.Services; using ILSpy.Debugger.Services;
@ -304,22 +307,25 @@ namespace ICSharpCode.ILSpy
} }
} }
void OpenFiles(string[] fileNames) void OpenFiles(string[] fileNames, bool focusNode = true)
{ {
treeView.UnselectAll(); if (focusNode) {
SharpTreeNode lastNode = null; treeView.UnselectAll();
foreach (string file in fileNames) {
var asm = assemblyList.OpenAssembly(file); SharpTreeNode lastNode = null;
if (asm != null) { foreach (string file in fileNames) {
var node = assemblyListTreeNode.FindAssemblyNode(asm); var asm = assemblyList.OpenAssembly(file);
if (node != null) { if (asm != null) {
treeView.SelectedItems.Add(node); var node = assemblyListTreeNode.FindAssemblyNode(asm);
lastNode = node; if (node != null) {
treeView.SelectedItems.Add(node);
lastNode = node;
}
} }
} }
if (lastNode != null)
treeView.FocusNode(lastNode);
} }
if (lastNode != null)
treeView.FocusNode(lastNode);
} }
void OpenFromGac_Click(object sender, RoutedEventArgs e) void OpenFromGac_Click(object sender, RoutedEventArgs e)
@ -345,32 +351,77 @@ namespace ICSharpCode.ILSpy
#region Debugger commands #region Debugger commands
[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);
}
IDebugger CurrentDebugger { IDebugger CurrentDebugger {
get { get {
return DebuggerService.CurrentDebugger; return DebuggerService.CurrentDebugger;
} }
} }
void StartDebugging(Process process)
{
CurrentDebugger.Attach(process);
EnableDebuggerUI(false);
CurrentDebugger.DebugStopped += OnDebugStopped;
CurrentDebugger.IsProcessRunningChanged += CurrentDebugger_IsProcessRunningChanged;
}
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(this, HWND_TOP);
this.Activate();
// jump to type & expand folding
if (CurrentLineBookmark.Instance != null) {
JumpToReference(CurrentLineBookmark.Instance.Type);
decompilerTextView.UnfoldAndScroll(CurrentLineBookmark.Instance.LineNumber);
}
}
void DebugExecutableExecuted(object sender, ExecutedRoutedEventArgs e) void DebugExecutableExecuted(object sender, ExecutedRoutedEventArgs e)
{ {
OpenFileDialog dialog = new OpenFileDialog() { OpenFileDialog dialog = new OpenFileDialog() {
Filter = ".NET Executable (*.exe) | *.exe", Filter = ".NET Executable (*.exe) | *.exe",
RestoreDirectory = true, RestoreDirectory = true,
DefaultExt = "exe" DefaultExt = "exe"
}; };
var result = dialog.ShowDialog(); if (dialog.ShowDialog() == true) {
if (result.HasValue && result.Value) {
string fileName = dialog.FileName; string fileName = dialog.FileName;
// add it to references // add it to references
OpenFiles(new [] { fileName }); OpenFiles(new [] { fileName }, false);
if (!CurrentDebugger.IsDebugging) { if (!CurrentDebugger.IsDebugging) {
// execute the process // execute the process
CurrentDebugger.Attach(Process.Start(fileName)); this.StartDebugging(Process.Start(fileName));
EnableDebuggerUI(false);
CurrentDebugger.DebugStopped += OnDebugStopped;
} }
} }
} }
@ -383,8 +434,7 @@ namespace ICSharpCode.ILSpy
if (window.ShowDialog() == true) if (window.ShowDialog() == true)
{ {
if (CurrentDebugger.IsDebugging) { if (CurrentDebugger.IsDebugging) {
EnableDebuggerUI(false); this.StartDebugging(window.SelectedProcess);
CurrentDebugger.DebugStopped += OnDebugStopped;
} }
} }
} }
@ -393,7 +443,8 @@ namespace ICSharpCode.ILSpy
void OnDebugStopped(object sender, EventArgs e) void OnDebugStopped(object sender, EventArgs e)
{ {
EnableDebuggerUI(true); EnableDebuggerUI(true);
DebuggerService.CurrentDebugger.DebugStopped -= OnDebugStopped; CurrentDebugger.DebugStopped -= OnDebugStopped;
CurrentDebugger.IsProcessRunningChanged -= CurrentDebugger_IsProcessRunningChanged;
} }
void DetachFromProcessExecuted(object sender, ExecutedRoutedEventArgs e) void DetachFromProcessExecuted(object sender, ExecutedRoutedEventArgs e)
@ -599,8 +650,7 @@ namespace ICSharpCode.ILSpy
void LanguageComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) void LanguageComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{ {
DebuggerService.CurrentDebugger.Language = DebuggedData.Language = sessionSettings.FilterSettings.Language.Name.StartsWith("IL") ? DecompiledLanguages.IL : DecompiledLanguages.CSharp;
sessionSettings.FilterSettings.Language.Name.StartsWith("IL") ? DecompiledLanguages.IL : DecompiledLanguages.CSharp;
} }
} }
} }

36
ILSpy/TextView/DecompilerTextView.cs

@ -34,6 +34,7 @@ using System.Windows.Threading;
using System.Xml; using System.Xml;
using ICSharpCode.AvalonEdit; using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Folding; using ICSharpCode.AvalonEdit.Folding;
using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.AvalonEdit.Highlighting.Xshd; using ICSharpCode.AvalonEdit.Highlighting.Xshd;
@ -42,6 +43,7 @@ using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.NRefactory.Documentation; using ICSharpCode.NRefactory.Documentation;
using ILSpy.Debugger; using ILSpy.Debugger;
using ILSpy.Debugger.AvalonEdit; using ILSpy.Debugger.AvalonEdit;
using ILSpy.Debugger.Bookmarks;
using ILSpy.Debugger.ToolTips; using ILSpy.Debugger.ToolTips;
using Microsoft.Win32; using Microsoft.Win32;
using TextEditorWeakEventManager = ILSpy.Debugger.AvalonEdit.TextEditorWeakEventManager; using TextEditorWeakEventManager = ILSpy.Debugger.AvalonEdit.TextEditorWeakEventManager;
@ -329,7 +331,7 @@ namespace ICSharpCode.ILSpy.TextView
/// </summary> /// </summary>
public void Decompile(ILSpy.Language language, IEnumerable<ILSpyTreeNode> treeNodes, DecompilationOptions options) public void Decompile(ILSpy.Language language, IEnumerable<ILSpyTreeNode> treeNodes, DecompilationOptions options)
{ {
DebuggedType.CurrentType = null; DebuggedData.CurrentType = null;
// Some actions like loading an assembly list cause several selection changes in the tree view, // Some actions like loading an assembly list cause several selection changes in the tree view,
// and each of those will start a decompilation action. // and each of those will start a decompilation action.
bool isDecompilationScheduled = this.nextDecompilationRun != null; bool isDecompilationScheduled = this.nextDecompilationRun != null;
@ -390,6 +392,16 @@ namespace ICSharpCode.ILSpy.TextView
finally { finally {
// repaint bookmarks // repaint bookmarks
iconMargin.InvalidateVisual(); iconMargin.InvalidateVisual();
// show the currentline marker
var bm = CurrentLineBookmark.Instance;
if (bm != null && DebuggedData.CurrentType != null) {
if (DebuggedData.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);
}
}
} }
}); });
} }
@ -623,5 +635,27 @@ namespace ICSharpCode.ILSpy.TextView
return text; return text;
} }
#endregion #endregion
#region Unfold
public void UnfoldAndScroll(int lineNumber)
{
if (lineNumber <= 0 || lineNumber > textEditor.Document.LineCount)
return;
var line = textEditor.Document.GetLineByNumber(lineNumber);
// unfold
var foldings = foldingManager.GetFoldingsContaining(line.Offset);
if (foldings != null) {
foreach (var folding in foldings) {
if (folding.IsFolded) {
folding.IsFolded = false;
}
}
}
// scroll to
textEditor.ScrollTo(lineNumber, 0);
}
#endregion
} }
} }

2
ILSpy/TreeNodes/TypeTreeNode.cs

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

Loading…
Cancel
Save