diff --git a/Debugger/Debugger.Core/Breakpoint.cs b/Debugger/Debugger.Core/Breakpoint.cs
index dd8e8fef9..551bf6390 100644
--- a/Debugger/Debugger.Core/Breakpoint.cs
+++ b/Debugger/Debugger.Core/Breakpoint.cs
@@ -176,11 +176,12 @@ namespace Debugger
public class ILBreakpoint : Breakpoint
{
- public ILBreakpoint(NDebugger debugger, string typeName, int line, uint metadataToken, int offset, bool enabled)
+ public ILBreakpoint(NDebugger debugger, string typeName, string memberReferenceName, int line, uint metadataToken, int offset, bool enabled)
{
this.Debugger = debugger;
this.Line = line;
this.TypeName = typeName;
+ this.MemberReferenceName = memberReferenceName;
this.MetadataToken = metadataToken;
this.ILOffset = offset;
this.Enabled = enabled;
@@ -190,6 +191,8 @@ namespace Debugger
public int ILOffset { get; private set; }
+ public string MemberReferenceName { get; private set; }
+
public override bool SetBreakpoint(Module module)
{
SourcecodeSegment segment = SourcecodeSegment.CreateForIL(module, this.Line, (int)MetadataToken, ILOffset);
diff --git a/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs b/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs
index 0a72f01f6..35bb84845 100644
--- a/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs
+++ b/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs
@@ -68,7 +68,7 @@ namespace Debugger.MetaData
sb.Append(this.ReturnType.Name);
sb.Append(" ");
} else {
- sb.Append("void ");
+ sb.Append("System.Void ");
}
sb.Append(this.DeclaringType.FullName);
@@ -80,7 +80,7 @@ namespace Debugger.MetaData
if (!first)
sb.Append(", ");
first = false;
- sb.Append(p.ParameterType.Name);
+ sb.Append(p.ParameterType.FullName);
sb.Append(" ");
sb.Append(p.Name);
}
@@ -89,6 +89,37 @@ namespace Debugger.MetaData
}
}
+ /// Name including the declaring type, return type without parameters names
+ public string FullNameWithoutParameterNames {
+ get {
+ StringBuilder sb = new StringBuilder();
+
+ if (this.IsStatic) {
+ sb.Append("static ");
+ }
+ if (this.ReturnType != null) {
+ sb.Append(this.ReturnType.Name);
+ sb.Append(" ");
+ } else {
+ sb.Append("System.Void ");
+ }
+
+ sb.Append(this.DeclaringType.FullName);
+ sb.Append(".");
+ sb.Append(this.Name);
+ sb.Append("(");
+ bool first = true;
+ foreach(DebugParameterInfo p in GetParameters()) {
+ if (!first)
+ sb.Append(", ");
+ first = false;
+ sb.Append(p.ParameterType.FullName);
+ }
+ sb.Append(")");
+ return sb.ToString();
+ }
+ }
+
///
public override string Name {
get { return methodProps.Name; }
diff --git a/Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs b/Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs
index f3a1931b7..c2c1236e5 100644
--- a/Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs
+++ b/Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs
@@ -4,10 +4,10 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
+using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
-
using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.AvalonEdit.Utils;
@@ -59,7 +59,8 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit
// create a dictionary line number => first bookmark
Dictionary bookmarkDict = new Dictionary();
foreach (var bm in BookmarkManager.Bookmarks) {
- if (DebugData.CurrentMemberReference == null || bm.Member.FullName != DebugData.CurrentMemberReference.FullName)
+ if (DebugData.DecompiledMemberReferences == null || DebugData.DecompiledMemberReferences.Count == 0 ||
+ !DebugData.DecompiledMemberReferences.ContainsKey(bm.MemberReference.FullName))
continue;
if (bm is BreakpointBookmark &&
((BreakpointBookmark)bm).Language != DebugData.Language)
@@ -121,8 +122,7 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit
BookmarkBase result = null;
foreach (BookmarkBase bm in BookmarkManager.Bookmarks) {
if (bm.LineNumber == line &&
- DebugData.CurrentMemberReference != null &&
- bm.Member.FullName == DebugData.CurrentMemberReference.FullName) {
+ DebugData.DecompiledMemberReferences != null && DebugData.DecompiledMemberReferences.ContainsKey(bm.MemberReference.FullName)) {
if (result == null || bm.ZOrder > result.ZOrder)
result = bm;
}
@@ -190,16 +190,6 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit
dragStarted = true;
InvalidateVisual();
}
-
- if (DebugData.CurrentMemberReference == null)
- return;
-
- BreakpointBookmark bm = BookmarkManager.Bookmarks.Find(
- b => b.Member.FullName == DebugData.CurrentMemberReference.FullName &&
- b.LineNumber == GetLineFromMousePosition(e)
- && b is BreakpointBookmark) as BreakpointBookmark;
-
- this.ToolTip = (bm != null) ? bm.Tooltip : null;
}
protected override void OnMouseUp(MouseButtonEventArgs e)
@@ -228,24 +218,32 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit
return;
}
if (e.ChangedButton == MouseButton.Left) {
- if (DebugData.CurrentMemberReference != null) {
+ if (DebugData.DecompiledMemberReferences != null && DebugData.DecompiledMemberReferences.Count > 0) {
// check if the codemappings exists for this line
var storage = DebugData.CodeMappings;
- uint token;
- var instruction = storage.GetInstructionByTypeAndLine(DebugData.CurrentMemberReference.FullName, line, out token);
+ uint token = 0;
+ foreach (var member in DebugData.DecompiledMemberReferences.Values) {
+ string memberName = member.FullName;
+ var instruction = storage[memberName].GetInstructionByTypeAndLine(memberName, line, out token);
+
+ if (instruction == null) {
+ continue;
+ }
+
+ // no bookmark on the line: create a new breakpoint
+ DebuggerService.ToggleBreakpointAt(
+ member,
+ line,
+ DebugData.Language);
+ break;
+ }
- if (instruction == null) {
- MessageBox.Show(string.Format("Missing code mappings for {0} at line {1}", DebugData.CurrentMemberReference.FullName, line),
+ if (token == 0) {
+ MessageBox.Show(string.Format("Missing code mappings at line {0}.", line),
"Code mappings", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
-
- // no bookmark on the line: create a new breakpoint
- DebuggerService.ToggleBreakpointAt(
- DebugData.CurrentMemberReference,
- line,
- DebugData.Language);
}
}
InvalidateVisual();
diff --git a/Debugger/ILSpy.Debugger/AvalonEdit/TextMarkerService.cs b/Debugger/ILSpy.Debugger/AvalonEdit/TextMarkerService.cs
index 9b1a31be1..92c174391 100644
--- a/Debugger/ILSpy.Debugger/AvalonEdit/TextMarkerService.cs
+++ b/Debugger/ILSpy.Debugger/AvalonEdit/TextMarkerService.cs
@@ -27,7 +27,7 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit
TextSegmentCollection markers = new TextSegmentCollection();
public TextMarkerService()
- {
+ {
BookmarkManager.Added += new BookmarkEventHandler(BookmarkManager_Added);
BookmarkManager.Removed += new BookmarkEventHandler(BookmarkManager_Removed);
}
@@ -53,11 +53,9 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit
{
if (e.Bookmark is MarkerBookmark) {
var bm = (MarkerBookmark)e.Bookmark;
- if (DebugData.CurrentMemberReference != null && DebugData.CurrentMemberReference == bm.Member) {
- // add bookmark for the current type
- DocumentLine line = codeEditor.Document.GetLineByNumber(bm.LineNumber);
- bm.CreateMarker(this, line.Offset, line.Length);
- }
+ // add bookmark for the current type
+ DocumentLine line = codeEditor.Document.GetLineByNumber(bm.LineNumber);
+ bm.CreateMarker(this, line.Offset, line.Length);
}
}
@@ -305,7 +303,7 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit
Redraw();
}
}
-
+
}
///
public object ToolTip { get; set; }
diff --git a/Debugger/ILSpy.Debugger/Bookmarks/BookmarkBase.cs b/Debugger/ILSpy.Debugger/Bookmarks/BookmarkBase.cs
index b452aaa8e..dadee8d2d 100644
--- a/Debugger/ILSpy.Debugger/Bookmarks/BookmarkBase.cs
+++ b/Debugger/ILSpy.Debugger/Bookmarks/BookmarkBase.cs
@@ -41,7 +41,7 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks
}
- public MemberReference Member { get; set; }
+ public MemberReference MemberReference { get; set; }
public int LineNumber {
get { return location.Line; }
@@ -66,7 +66,7 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks
public BookmarkBase(MemberReference member, AstLocation location)
{
- this.Member = member;
+ this.MemberReference = member;
this.Location = location;
}
diff --git a/Debugger/ILSpy.Debugger/Bookmarks/BookmarkManager.cs b/Debugger/ILSpy.Debugger/Bookmarks/BookmarkManager.cs
index 3ec7a14b9..500e1b92f 100644
--- a/Debugger/ILSpy.Debugger/Bookmarks/BookmarkManager.cs
+++ b/Debugger/ILSpy.Debugger/Bookmarks/BookmarkManager.cs
@@ -31,7 +31,7 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks
List marks = new List();
foreach (BookmarkBase mark in bookmarks) {
- if (typeName == mark.Member.FullName) {
+ if (typeName == mark.MemberReference.FullName) {
marks.Add(mark);
}
}
@@ -56,7 +56,7 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks
return false;
if (a.GetType() != b.GetType())
return false;
- if (a.Member.FullName != b.Member.FullName)
+ if (a.MemberReference.FullName != b.MemberReference.FullName)
return false;
return a.LineNumber == b.LineNumber;
}
@@ -150,20 +150,23 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks
// 1. Save it's data
int line = CurrentLineBookmark.Instance.LineNumber;
- var markerType = CurrentLineBookmark.Instance.Member;
+ var markerType = CurrentLineBookmark.Instance.MemberReference;
+
+ if (!oldMappings.ContainsKey(markerType.FullName) || !oldMappings.ContainsKey(markerType.FullName))
+ return;
// 2. Remove it
CurrentLineBookmark.Remove();
// 3. map the marker line
uint token;
- var instruction = oldMappings.GetInstructionByTypeAndLine(markerType.FullName, line, out token);
+ var instruction = oldMappings[markerType.FullName].GetInstructionByTypeAndLine(markerType.FullName, line, out token);
if (instruction == null)
return;
MemberReference memberReference;
int newline;
- if (newMappings.GetSourceCodeFromMetadataTokenAndOffset(markerType.FullName, token, instruction.ILInstructionOffset.From, out memberReference, out newline)) {
+ if (newMappings[markerType.FullName].GetSourceCodeFromMetadataTokenAndOffset(token, instruction.ILInstructionOffset.From, out memberReference, out newline)) {
// 4. create breakpoint for new languages
CurrentLineBookmark.SetPosition(memberReference, newline, 0, newline, 0);
}
@@ -191,13 +194,17 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks
foreach (var bp in oldbps) {
uint token;
- var instruction = oldMappings.GetInstructionByTypeAndLine(bp.Member.FullName, bp.LineNumber, out token);
+ string name = bp.MemberReference.FullName;
+ if (!oldMappings.ContainsKey(name) || !oldMappings.ContainsKey(name))
+ continue;
+
+ var instruction = oldMappings[name].GetInstructionByTypeAndLine(bp.MemberReference.FullName, bp.LineNumber, out token);
if (instruction == null)
continue;
MemberReference memberReference;
int line;
- if (newMappings.GetSourceCodeFromMetadataTokenAndOffset(bp.Member.FullName, token, instruction.ILInstructionOffset.From, out memberReference, out line)) {
+ if (newMappings[name].GetSourceCodeFromMetadataTokenAndOffset(token, instruction.ILInstructionOffset.From, out memberReference, out line)) {
// 2. create breakpoint for new languages
var bookmark = new BreakpointBookmark(memberReference, new AstLocation(line, 0), BreakpointAction.Break, newLanguage);
AddMark(bookmark);
diff --git a/Debugger/ILSpy.Debugger/Bookmarks/BreakpointBookmark.cs b/Debugger/ILSpy.Debugger/Bookmarks/BreakpointBookmark.cs
index 4509abb80..cc4189c83 100644
--- a/Debugger/ILSpy.Debugger/Bookmarks/BreakpointBookmark.cs
+++ b/Debugger/ILSpy.Debugger/Bookmarks/BreakpointBookmark.cs
@@ -91,7 +91,7 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks
ITextMarker marker = markerService.Create(offset, length);
marker.BackgroundColor = Color.FromRgb(180, 38, 38);
marker.ForegroundColor = Colors.White;
- marker.IsVisible = b => b is MarkerBookmark && ((MarkerBookmark)b).Member == DebugData.CurrentMemberReference;
+ marker.IsVisible = b => b is MarkerBookmark && DebugData.DecompiledMemberReferences.ContainsKey(((MarkerBookmark)b).MemberReference.FullName);
marker.Bookmark = this;
this.Marker = marker;
diff --git a/Debugger/ILSpy.Debugger/Bookmarks/CurrentLineBookmark.cs b/Debugger/ILSpy.Debugger/Bookmarks/CurrentLineBookmark.cs
index f1ace04fc..b83f1ca77 100644
--- a/Debugger/ILSpy.Debugger/Bookmarks/CurrentLineBookmark.cs
+++ b/Debugger/ILSpy.Debugger/Bookmarks/CurrentLineBookmark.cs
@@ -81,7 +81,7 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks
ITextMarker marker = markerService.Create(offset + startColumn - 1, length + 1);
marker.BackgroundColor = Colors.Yellow;
marker.ForegroundColor = Colors.Blue;
- marker.IsVisible = b => b is MarkerBookmark && ((MarkerBookmark)b).Member == DebugData.CurrentMemberReference;
+ marker.IsVisible = b => b is MarkerBookmark && DebugData.DecompiledMemberReferences.ContainsKey(((MarkerBookmark)b).MemberReference.FullName);
marker.Bookmark = this;
this.Marker = marker;
return marker;
diff --git a/Debugger/ILSpy.Debugger/DebuggedData.cs b/Debugger/ILSpy.Debugger/DebuggedData.cs
index 426ebd8df..179662bbc 100644
--- a/Debugger/ILSpy.Debugger/DebuggedData.cs
+++ b/Debugger/ILSpy.Debugger/DebuggedData.cs
@@ -18,11 +18,6 @@ namespace ICSharpCode.ILSpy.Debugger
{
static DecompiledLanguages language;
- ///
- /// Gets or sets the current debugged member reference. Can be a type or a member of a type (method, property).
- ///
- public static MemberReference CurrentMemberReference { get; set; }
-
///
/// Gets or sets the decompiled language.
///
@@ -42,19 +37,10 @@ namespace ICSharpCode.ILSpy.Debugger
///
public static IEnumerable LoadedAssemblies { get; set; }
- ///
- /// Returns true if the CurrentMember is a type (TypeDefinition). Otherwise, returns false (is MethodDefinition or PropertyDefinition).
- ///
- public static bool IsCurrentMemberReferenceType {
- get {
- return CurrentMemberReference is TypeDefinition;
- }
- }
-
///
/// Gets or sets the current code mappings.
///
- public static Tuple> CodeMappings { get; set; }
+ public static Dictionary> CodeMappings { get; set; }
///
/// Gets or sets the local variables of the current decompiled type, method, etc.
@@ -64,7 +50,17 @@ namespace ICSharpCode.ILSpy.Debugger
///
/// Gets or sets the old code mappings.
///
- public static Tuple> OldCodeMappings { get; set; }
+ public static Dictionary> OldCodeMappings { get; set; }
+
+ ///
+ /// Gets or sets the MembeReference that was decompiled (a TypeDefinition, MethodDefinition, etc)
+ ///
+ public static Dictionary DecompiledMemberReferences { get; set; }
+
+ ///
+ /// Gets or sets the debug type.
+ ///
+ public static bool DebugWholeTypesOnly { get; set; }
///
/// Occures when the language is changed.
diff --git a/Debugger/ILSpy.Debugger/DebuggerSettings.cs b/Debugger/ILSpy.Debugger/DebuggerSettings.cs
index 7177ac4a5..7599b2527 100644
--- a/Debugger/ILSpy.Debugger/DebuggerSettings.cs
+++ b/Debugger/ILSpy.Debugger/DebuggerSettings.cs
@@ -9,10 +9,13 @@ namespace ICSharpCode.ILSpy.Debugger
public class DebuggerSettings : INotifyPropertyChanged
{
bool showWarnings = true;
+ bool debugWholeTypesOnly = false;
///
/// Show warnings messages.
+ /// Default value is true.
///
+ [DefaultValue(true)]
public bool ShowWarnings {
get { return showWarnings; }
set {
@@ -23,6 +26,21 @@ namespace ICSharpCode.ILSpy.Debugger
}
}
+ ///
+ /// True, if debug only whole types; otherwise false (debug only methods and properties).
+ /// Default value is false.
+ ///
+ [DefaultValue(false)]
+ public bool DebugWholeTypesOnly {
+ get { return debugWholeTypesOnly; }
+ set {
+ if (debugWholeTypesOnly != value) {
+ debugWholeTypesOnly = value;
+ OnPropertyChanged("DebugWholeTypesOnly");
+ }
+ }
+ }
+
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
diff --git a/Debugger/ILSpy.Debugger/Services/Debugger/DebuggerService.cs b/Debugger/ILSpy.Debugger/Services/Debugger/DebuggerService.cs
index eedcb1cec..5ed475333 100644
--- a/Debugger/ILSpy.Debugger/Services/Debugger/DebuggerService.cs
+++ b/Debugger/ILSpy.Debugger/Services/Debugger/DebuggerService.cs
@@ -166,7 +166,7 @@ namespace ICSharpCode.ILSpy.Debugger.Services
public static void ToggleBreakpointAt(MemberReference member, int lineNumber, DecompiledLanguages language)
{
BookmarkManager.ToggleBookmark(
- member.FullName, lineNumber,
+ member.FullName.Replace("::", "."), lineNumber,
b => b.CanToggle && b is BreakpointBookmark,
location => new BreakpointBookmark(member, location, BreakpointAction.Break, language));
}
diff --git a/Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs b/Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs
index ce7216481..07c3275f4 100644
--- a/Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs
+++ b/Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs
@@ -288,10 +288,11 @@ namespace ICSharpCode.ILSpy.Debugger.Services
{
isMatch = false;
frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
+ var debugType = (DebugType)frame.MethodInfo.DeclaringType;
+ string nameKey = DebugData.DebugWholeTypesOnly ? debugType.FullNameWithoutGenericArguments : frame.MethodInfo.FullNameWithoutParameterNames;
// get the mapped instruction from the current line marker or the next one
- return DebugData.CodeMappings.GetInstructionByTypeTokenAndOffset(
- ((DebugType)frame.MethodInfo.DeclaringType).FullNameWithoutGenericArguments,
+ return DebugData.CodeMappings[nameKey].GetInstructionByTypeTokenAndOffset(
(uint)frame.MethodInfo.MetadataToken,
frame.IP, out isMatch);
}
@@ -560,13 +561,16 @@ namespace ICSharpCode.ILSpy.Debugger.Services
Breakpoint breakpoint = null;
uint token;
- SourceCodeMapping map = DebugData.CodeMappings
- .GetInstructionByTypeAndLine(bookmark.Member.FullName, bookmark.LineNumber, out token);
+ SourceCodeMapping map = DebugData.CodeMappings[bookmark.MemberReference.FullName]
+ .GetInstructionByTypeAndLine(bookmark.MemberReference.FullName, bookmark.LineNumber, out token);
if (map != null) {
+ var declaringType = bookmark.MemberReference.DeclaringType;
+
breakpoint = new ILBreakpoint(
debugger,
- bookmark.Member.FullName,
+ (declaringType ?? bookmark.MemberReference).FullName,
+ bookmark.MemberReference.FullName,
bookmark.LineNumber,
token,
map.ILInstructionOffset.From,
@@ -745,7 +749,7 @@ namespace ICSharpCode.ILSpy.Debugger.Services
foreach (var bookmark in DebuggerService.Breakpoints) {
var breakpoint =
debugger.Breakpoints.FirstOrDefault(
- b => b.Line == bookmark.LineNumber && b.TypeName == bookmark.Member.FullName);
+ b => b.Line == bookmark.LineNumber && (b as ILBreakpoint).MemberReferenceName.CreateKey() == bookmark.MemberReference.FullName.CreateKey());
if (breakpoint == null)
continue;
// set the breakpoint only if the module contains the type
@@ -818,14 +822,18 @@ namespace ICSharpCode.ILSpy.Debugger.Services
int ilOffset = frame.IP;
int line;
MemberReference memberReference;
+ string nameKey = DebugData.DebugWholeTypesOnly ? debugType.FullNameWithoutGenericArguments : frame.MethodInfo.FullNameWithoutParameterNames;
- if (DebugData.CodeMappings.GetSourceCodeFromMetadataTokenAndOffset(debugType.FullNameWithoutGenericArguments, token, ilOffset, out memberReference, out line)
- && memberReference.DeclaringType == null) {
- DebuggerService.RemoveCurrentLineMarker();
- DebuggerService.JumpToCurrentLine(memberReference, line, 0, line, 0);
- } else {
- // is possible that the type is not decompiled yet, so we must do a decompilation on demand
- DecompileOnDemand(frame);
+ foreach (var key in DebugData.CodeMappings.Keys) {
+ if (key.CreateKey() == nameKey.CreateKey()) {
+ if (DebugData.CodeMappings[key].GetSourceCodeFromMetadataTokenAndOffset(token, ilOffset, out memberReference, out line)) {
+ DebuggerService.RemoveCurrentLineMarker();
+ DebuggerService.JumpToCurrentLine(memberReference, line, 0, line, 0);
+ } else {
+ // is possible that the type is not decompiled yet, so we must do a decompilation on demand
+ DecompileOnDemand(frame);
+ }
+ }
}
}
}
@@ -837,7 +845,6 @@ namespace ICSharpCode.ILSpy.Debugger.Services
uint token = (uint)frame.MethodInfo.MetadataToken;
int ilOffset = frame.IP;
string fullName = debugType.FullNameWithoutGenericArguments;
- fullName = fullName.Replace("+", "/");
if (DebugData.LoadedAssemblies == null)
throw new NullReferenceException("No DebugData assemblies!");
@@ -845,6 +852,7 @@ namespace ICSharpCode.ILSpy.Debugger.Services
// search for type in the current assembly list
TypeDefinition typeDef = null;
TypeDefinition nestedTypeDef = null;
+ MemberReference member = null;
foreach (var assembly in DebugData.LoadedAssemblies) {
if ((assembly.FullName.StartsWith("System") || assembly.FullName.StartsWith("Microsoft") || assembly.FullName.StartsWith("mscorlib")) &&
@@ -854,9 +862,9 @@ namespace ICSharpCode.ILSpy.Debugger.Services
foreach (var module in assembly.Modules) {
var localType = module.GetType(fullName);
if (localType != null) {
- if (localType.DeclaringType == null)
+ if (localType.DeclaringType == null) {
typeDef = localType;
- else {
+ } else {
nestedTypeDef = localType;
typeDef = localType.DeclaringType;
}
@@ -868,12 +876,22 @@ namespace ICSharpCode.ILSpy.Debugger.Services
}
if (typeDef != null) {
- // decompile on demand
- Tuple> codeMappings = null;
- if (DebugData.CodeMappings.Item1 != (nestedTypeDef ?? typeDef).FullName) {
+ member = nestedTypeDef ?? typeDef;
+
+ // decompile on demand if the type was not decompiled
+ Dictionary> codeMappings = null;
+ if (!DebugData.CodeMappings.ContainsKey(member.FullName)) {
if (DebugData.Language == DecompiledLanguages.IL) {
var dis = new ReflectionDisassembler(new PlainTextOutput(), true, CancellationToken.None);
+
dis.DisassembleType(nestedTypeDef ?? typeDef);
+// else if (ICSharpCode.Decompiler.CodeMappings.DecompiledMember is MethodDefinition)
+// dis.DisassembleMethod(ICSharpCode.Decompiler.CodeMappings.DecompiledMember as MethodDefinition);
+// else if (ICSharpCode.Decompiler.CodeMappings.DecompiledMember is PropertyDefinition)
+// dis.DisassembleProperty(ICSharpCode.Decompiler.CodeMappings.DecompiledMember as PropertyDefinition);
+// else if (ICSharpCode.Decompiler.CodeMappings.DecompiledMember is EventDefinition)
+// dis.DisassembleEvent(ICSharpCode.Decompiler.CodeMappings.DecompiledMember as EventDefinition);
+
codeMappings = dis.CodeMappings;
} else {
AstBuilder builder = new AstBuilder(new DecompilerContext(typeDef.Module));
@@ -886,7 +904,8 @@ namespace ICSharpCode.ILSpy.Debugger.Services
int line;
MemberReference memberReference;
codeMappings = codeMappings ?? DebugData.CodeMappings;
- if (codeMappings.GetSourceCodeFromMetadataTokenAndOffset((nestedTypeDef ?? typeDef).FullName, token, ilOffset, out memberReference, out line)) {
+ string name = (nestedTypeDef ?? typeDef).FullName;
+ if (codeMappings[name].GetSourceCodeFromMetadataTokenAndOffset(token, ilOffset, out memberReference, out line)) {
DebuggerService.RemoveCurrentLineMarker();
DebuggerService.JumpToCurrentLine(nestedTypeDef ?? typeDef, line, 0, line, 0);
} else {
diff --git a/ICSharpCode.Decompiler/Ast/AstBuilder.cs b/ICSharpCode.Decompiler/Ast/AstBuilder.cs
index daab20f0f..aa5dc14f0 100644
--- a/ICSharpCode.Decompiler/Ast/AstBuilder.cs
+++ b/ICSharpCode.Decompiler/Ast/AstBuilder.cs
@@ -46,6 +46,8 @@ namespace ICSharpCode.Decompiler.Ast
this.DecompileMethodBodies = true;
this.LocalVariables = new ConcurrentDictionary>();
+ this.CodeMappings = new Dictionary>();
+ this.DecompiledMemberReferences = new Dictionary();
}
public static bool MemberIsHidden(MemberReference member, DecompilerSettings settings)
@@ -159,6 +161,10 @@ namespace ICSharpCode.Decompiler.Ast
public void AddType(TypeDefinition typeDef)
{
+ // add to mappings information
+ this.DecompiledMemberReferences.Add(typeDef.FullName, typeDef);
+ this.CodeMappings.Add(typeDef.FullName, new List());
+
var astType = CreateType(typeDef);
NamespaceDeclaration astNS = GetCodeNamespace(typeDef.Namespace);
if (astNS != null) {
@@ -170,22 +176,36 @@ namespace ICSharpCode.Decompiler.Ast
public void AddMethod(MethodDefinition method)
{
+ // add to mappings information
+ this.CodeMappings.Add(method.FullName, new List());
+ this.DecompiledMemberReferences.Add(method.FullName, method);
+
AstNode node = method.IsConstructor ? (AstNode)CreateConstructor(method) : CreateMethod(method);
astCompileUnit.AddChild(node, CompilationUnit.MemberRole);
}
public void AddProperty(PropertyDefinition property)
{
+ // add to mappings information
+ this.CodeMappings.Add(property.FullName, new List());
+ this.DecompiledMemberReferences.Add(property.FullName, property);
+
astCompileUnit.AddChild(CreateProperty(property), CompilationUnit.MemberRole);
}
public void AddField(FieldDefinition field)
{
+ this.DecompiledMemberReferences.Add(field.FullName, field);
+
astCompileUnit.AddChild(CreateField(field), CompilationUnit.MemberRole);
}
public void AddEvent(EventDefinition ev)
{
+ // add to mappings information
+ this.DecompiledMemberReferences.Add(ev.FullName, ev);
+ this.CodeMappings.Add(ev.FullName, new List());
+
astCompileUnit.AddChild(CreateEvent(ev), CompilationUnit.MemberRole);
}
@@ -195,11 +215,7 @@ namespace ICSharpCode.Decompiler.Ast
///
/// TypeDeclaration or DelegateDeclaration.
public AttributedNode CreateType(TypeDefinition typeDef)
- {
- // create CSharp code mappings - used for debugger
- if (this.CodeMappings == null)
- this.CodeMappings = new Tuple>(typeDef.FullName, new List());
-
+ {
// create type
TypeDefinition oldCurrentType = context.CurrentType;
context.CurrentType = typeDef;
@@ -603,12 +619,12 @@ namespace ICSharpCode.Decompiler.Ast
// Add events
foreach(EventDefinition eventDef in typeDef.Events) {
- astType.AddChild(CreateEvent(eventDef), TypeDeclaration.MemberRole);
+ astType.AddChild(CreateEvent(eventDef, true), TypeDeclaration.MemberRole);
}
// Add properties
foreach(PropertyDefinition propDef in typeDef.Properties) {
- astType.Members.Add(CreateProperty(propDef));
+ astType.Members.Add(CreateProperty(propDef, true));
}
// Add methods
@@ -616,16 +632,17 @@ namespace ICSharpCode.Decompiler.Ast
if (MemberIsHidden(methodDef, context.Settings)) continue;
if (methodDef.IsConstructor)
- astType.Members.Add(CreateConstructor(methodDef));
+ astType.Members.Add(CreateConstructor(methodDef, true));
else
- astType.Members.Add(CreateMethod(methodDef));
+ astType.Members.Add(CreateMethod(methodDef, true));
}
}
- AttributedNode CreateMethod(MethodDefinition methodDef)
+ AttributedNode CreateMethod(MethodDefinition methodDef, bool isTypeDecompiled = false)
{
// Create mapping - used in debugger
- MemberMapping methodMapping = methodDef.CreateCodeMapping(this.CodeMappings);
+ string name = isTypeDecompiled ? methodDef.DeclaringType.FullName : methodDef.FullName;
+ MemberMapping methodMapping = methodDef.CreateCodeMapping(this.CodeMappings[name], isTypeDecompiled);
MethodDeclaration astMethod = new MethodDeclaration();
astMethod.AddAnnotation(methodDef);
@@ -717,10 +734,11 @@ namespace ICSharpCode.Decompiler.Ast
}
}
- ConstructorDeclaration CreateConstructor(MethodDefinition methodDef)
+ ConstructorDeclaration CreateConstructor(MethodDefinition methodDef, bool isTypeDecompiled = false)
{
// Create mapping - used in debugger
- MemberMapping methodMapping = methodDef.CreateCodeMapping(this.CodeMappings);
+ string name = isTypeDecompiled ? methodDef.DeclaringType.FullName : methodDef.FullName;
+ MemberMapping methodMapping = methodDef.CreateCodeMapping(this.CodeMappings[name], isTypeDecompiled);
ConstructorDeclaration astMethod = new ConstructorDeclaration();
astMethod.AddAnnotation(methodDef);
@@ -750,7 +768,7 @@ namespace ICSharpCode.Decompiler.Ast
return m & ~Modifiers.Private;
}
- MemberDeclaration CreateProperty(PropertyDefinition propDef)
+ MemberDeclaration CreateProperty(PropertyDefinition propDef, bool isTypeDecompiled = false)
{
PropertyDeclaration astProp = new PropertyDeclaration();
astProp.AddAnnotation(propDef);
@@ -785,9 +803,12 @@ namespace ICSharpCode.Decompiler.Ast
}
astProp.Name = CleanName(propDef.Name);
astProp.ReturnType = ConvertType(propDef.PropertyType, propDef);
+
+ string name = isTypeDecompiled ? propDef.DeclaringType.FullName : propDef.FullName;
+
if (propDef.GetMethod != null) {
// Create mapping - used in debugger
- MemberMapping methodMapping = propDef.GetMethod.CreateCodeMapping(this.CodeMappings);
+ MemberMapping methodMapping = propDef.GetMethod.CreateCodeMapping(this.CodeMappings[name], isTypeDecompiled);
astProp.Getter = new Accessor();
astProp.Getter.Body = CreateMethodBody(propDef.GetMethod);
@@ -801,7 +822,7 @@ namespace ICSharpCode.Decompiler.Ast
}
if (propDef.SetMethod != null) {
// Create mapping - used in debugger
- MemberMapping methodMapping = propDef.SetMethod.CreateCodeMapping(this.CodeMappings);
+ MemberMapping methodMapping = propDef.SetMethod.CreateCodeMapping(this.CodeMappings[name], isTypeDecompiled);
astProp.Setter = new Accessor();
astProp.Setter.Body = CreateMethodBody(propDef.SetMethod);
@@ -837,7 +858,7 @@ namespace ICSharpCode.Decompiler.Ast
return astIndexer;
}
- AttributedNode CreateEvent(EventDefinition eventDef)
+ AttributedNode CreateEvent(EventDefinition eventDef, bool isTypeDecompiled = false)
{
if (eventDef.AddMethod != null && eventDef.AddMethod.IsAbstract) {
// An abstract event cannot be custom
@@ -859,9 +880,12 @@ namespace ICSharpCode.Decompiler.Ast
astEvent.Modifiers = ConvertModifiers(eventDef.AddMethod);
else
astEvent.PrivateImplementationType = ConvertType(eventDef.AddMethod.Overrides.First().DeclaringType);
+
+ string name = isTypeDecompiled ? eventDef.DeclaringType.FullName : eventDef.FullName;
+
if (eventDef.AddMethod != null) {
// Create mapping - used in debugger
- MemberMapping methodMapping = eventDef.AddMethod.CreateCodeMapping(this.CodeMappings);
+ MemberMapping methodMapping = eventDef.AddMethod.CreateCodeMapping(this.CodeMappings[name], isTypeDecompiled);
astEvent.AddAccessor = new Accessor {
Body = CreateMethodBody(eventDef.AddMethod)
@@ -872,7 +896,7 @@ namespace ICSharpCode.Decompiler.Ast
}
if (eventDef.RemoveMethod != null) {
// Create mapping - used in debugger
- MemberMapping methodMapping = eventDef.RemoveMethod.CreateCodeMapping(this.CodeMappings);
+ MemberMapping methodMapping = eventDef.AddMethod.CreateCodeMapping(this.CodeMappings[name], isTypeDecompiled);
astEvent.RemoveAccessor = new Accessor {
Body = CreateMethodBody(eventDef.RemoveMethod)
@@ -1371,12 +1395,17 @@ namespace ICSharpCode.Decompiler.Ast
///
///
///
- public Tuple> CodeMappings { get; private set; }
+ public Dictionary> CodeMappings { get; private set; }
///
/// Gets the local variables for the current decompiled type, method, etc.
/// The key is the metadata token.
///
public ConcurrentDictionary> LocalVariables { get; private set; }
+
+ ///
+ ///
+ ///
+ public Dictionary DecompiledMemberReferences { get; private set; }
}
}
diff --git a/ICSharpCode.Decompiler/CodeMappings.cs b/ICSharpCode.Decompiler/CodeMappings.cs
index c169d0e6f..1cedacb45 100644
--- a/ICSharpCode.Decompiler/CodeMappings.cs
+++ b/ICSharpCode.Decompiler/CodeMappings.cs
@@ -27,7 +27,12 @@ namespace ICSharpCode.Decompiler
///
/// Gets the code mappings.
///
- Tuple> CodeMappings { get; }
+ Dictionary> CodeMappings { get; }
+
+ ///
+ /// Gets the MembeReference that is decompiled (a TypeDefinition, MethodDefinition, etc)
+ ///
+ Dictionary DecompiledMemberReferences { get; }
}
///
@@ -133,15 +138,17 @@ namespace ICSharpCode.Decompiler
/// Code mappings helper class.
///
public static class CodeMappings
- {
+ {
///
/// Create code mapping for a method.
///
/// Method to create the mapping for.
- /// Source code mapping storage.
+ /// Source code mapping storage.
+ /// True, if a full type was decompiled; false otherwise.
internal static MemberMapping CreateCodeMapping(
this MethodDefinition member,
- Tuple> codeMappings)
+ List codeMappings,
+ bool isTypeDecompiled)
{
if (member == null || !member.HasBody)
return null;
@@ -151,17 +158,21 @@ namespace ICSharpCode.Decompiler
// create IL/CSharp code mappings - used in debugger
MemberMapping currentMemberMapping = null;
- if (codeMappings.Item1 == member.DeclaringType.FullName) {
- var mapping = codeMappings.Item2;
- if (mapping.Find(map => (int)map.MetadataToken == member.MetadataToken.ToInt32()) == null) {
- currentMemberMapping = new MemberMapping() {
- MetadataToken = (uint)member.MetadataToken.ToInt32(),
- MemberReference = member.DeclaringType.Resolve(),
- MemberCodeMappings = new List(),
- CodeSize = member.Body.CodeSize
- };
- mapping.Add(currentMemberMapping);
- }
+ string key = isTypeDecompiled ? member.DeclaringType.FullName : member.FullName;
+
+ if (codeMappings.Find(map => (int)map.MetadataToken == member.MetadataToken.ToInt32()) == null) {
+ currentMemberMapping = new MemberMapping() {
+ MetadataToken = (uint)member.MetadataToken.ToInt32(),
+ MemberCodeMappings = new List(),
+ CodeSize = member.Body.CodeSize
+ };
+
+ if (isTypeDecompiled)
+ currentMemberMapping.MemberReference = member.DeclaringType.Resolve();
+ else
+ currentMemberMapping.MemberReference = member.Resolve();
+
+ codeMappings.Add(currentMemberMapping);
}
return currentMemberMapping;
@@ -171,31 +182,20 @@ namespace ICSharpCode.Decompiler
/// Gets source code mapping and metadata token based on type name and line number.
///
/// Code mappings storage.
- /// Type name.
+ /// Member reference name.
/// Line number.
/// Metadata token.
///
public static SourceCodeMapping GetInstructionByTypeAndLine(
- this Tuple> codeMappings,
+ this List codeMappings,
string memberReferenceName,
int lineNumber,
out uint metadataToken)
{
if (codeMappings == null)
- throw new ArgumentNullException("CodeMappings storage must be valid!");
-
- if (codeMappings.Item1 != memberReferenceName) {
- metadataToken = 0;
- return null;
- }
-
- if (lineNumber <= 0) {
- metadataToken = 0;
- return null;
- }
+ throw new ArgumentException("CodeMappings storage must be valid!");
- var methodMappings = codeMappings.Item2;
- foreach (var maping in methodMappings) {
+ foreach (var maping in codeMappings) {
var map = maping.MemberCodeMappings.Find(m => m.SourceCodeLine == lineNumber);
if (map != null) {
metadataToken = maping.MetadataToken;
@@ -211,33 +211,26 @@ namespace ICSharpCode.Decompiler
/// Gets a mapping given a type, a token and an IL offset.
///
/// Code mappings storage.
- /// Type name.
+ /// Member reference name.
/// Token.
/// IL offset.
/// True, if perfect match.
/// A code mapping.
public static SourceCodeMapping GetInstructionByTypeTokenAndOffset(
- this Tuple> codeMappings,
- string memberReferenceName,
+ this List codeMappings,
uint token,
- int ilOffset, out bool isMatch)
+ int ilOffset,
+ out bool isMatch)
{
isMatch = false;
- memberReferenceName = memberReferenceName.Replace("+", "/");
if (codeMappings == null)
throw new ArgumentNullException("CodeMappings storage must be valid!");
- if (codeMappings.Item1 != memberReferenceName) {
- return null;
- }
-
- var methodMappings = codeMappings.Item2;
- var maping = methodMappings.Find(m => m.MetadataToken == token);
+ var maping = codeMappings.Find(m => m.MetadataToken == token);
- if (maping == null) {
+ if (maping == null)
return null;
- }
// try find an exact match
var map = maping.MemberCodeMappings.Find(m => m.ILInstructionOffset.From <= ilOffset && ilOffset < m.ILInstructionOffset.To);
@@ -260,31 +253,25 @@ namespace ICSharpCode.Decompiler
/// Gets the source code and type name from metadata token and offset.
///
/// Code mappings storage.
- /// Current type name.
/// Metadata token.
/// IL offset.
/// Type definition.
/// Line number.
/// It is possible to exist to different types from different assemblies with the same metadata token.
public static bool GetSourceCodeFromMetadataTokenAndOffset(
- this Tuple> codeMappings,
- string memberReferenceName,
+ this List codeMappings,
uint token,
int ilOffset,
- out MemberReference type,
+ out MemberReference member,
out int line)
{
- type = null;
+ member = null;
line = 0;
if (codeMappings == null)
- throw new ArgumentNullException("CodeMappings storage must be valid!");
+ throw new ArgumentException("CodeMappings storage must be valid!");
- memberReferenceName = memberReferenceName.Replace("+", "/");
- if (codeMappings.Item1 != memberReferenceName)
- return false;
-
- var mapping = codeMappings.Item2.Find(m => m.MetadataToken == token);
+ var mapping = codeMappings.Find(m => m.MetadataToken == token);
if (mapping == null)
return false;
@@ -299,9 +286,19 @@ namespace ICSharpCode.Decompiler
}
}
- type = mapping.MemberReference;
+ member = mapping.MemberReference;
line = codeMapping.SourceCodeLine;
return true;
}
+
+ ///
+ /// Create a key by replacing "::" with ".", "+" with "/", " " with "";
+ ///
+ /// Item to convert.
+ ///
+ public static string CreateKey(this string item)
+ {
+ return item.Replace("+", "/").Replace("::", ".").Replace(" ", string.Empty);
+ }
}
}
diff --git a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
index 5231b78c1..e898ac86f 100644
--- a/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
+++ b/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
@@ -44,6 +44,9 @@ namespace ICSharpCode.Decompiler.Disassembler
this.cancellationToken = cancellationToken;
this.detectControlStructure = detectControlStructure;
this.methodBodyDisassembler = new MethodBodyDisassembler(output, detectControlStructure, cancellationToken);
+
+ this.CodeMappings = new Dictionary>();
+ this.DecompiledMemberReferences = new Dictionary();
}
#region Disassemble Method
@@ -92,14 +95,21 @@ namespace ICSharpCode.Decompiler.Disassembler
{ MethodImplAttributes.NoOptimization, "nooptimization" },
};
- public void DisassembleMethod(MethodDefinition method)
+ public void DisassembleMethod(MethodDefinition method, bool isTypeDecompiled = false)
{
+ // create mappings for decompiled methods only
+ string name = isTypeDecompiled ? method.DeclaringType.FullName : method.FullName;
+ if (!isTypeDecompiled) {
+ this.CodeMappings.Add(name, new List());
+ this.DecompiledMemberReferences.Add(method.FullName, method);
+ }
+
// write method header
output.WriteDefinition(".method ", method);
- DisassembleMethodInternal(method);
+ DisassembleMethodInternal(method, isTypeDecompiled);
}
- void DisassembleMethodInternal(MethodDefinition method)
+ void DisassembleMethodInternal(MethodDefinition method, bool isTypeDecompiled)
{
// .method public hidebysig specialname
// instance default class [mscorlib]System.IO.TextWriter get_BaseWriter () cil managed
@@ -118,7 +128,6 @@ namespace ICSharpCode.Decompiler.Disassembler
//call convention
WriteEnum(method.CallingConvention & (MethodCallingConvention)0x1f, callingConvention);
-
//return type
method.ReturnType.WriteTo(output);
output.Write(' ');
@@ -149,7 +158,9 @@ namespace ICSharpCode.Decompiler.Disassembler
if (method.HasBody) {
// create IL code mappings - used in debugger
- MemberMapping methodMapping = method.CreateCodeMapping(this.CodeMappings);
+ string name = isTypeDecompiled ? method.DeclaringType.FullName : method.FullName;
+ MemberMapping methodMapping = method.CreateCodeMapping(this.CodeMappings[name], isTypeDecompiled);
+
methodBodyDisassembler.Disassemble(method.Body, methodMapping);
}
@@ -192,8 +203,13 @@ namespace ICSharpCode.Decompiler.Disassembler
{ FieldAttributes.NotSerialized, "notserialized" },
};
- public void DisassembleField(FieldDefinition field)
+ public void DisassembleField(FieldDefinition field, bool isTypeDecompiled = false)
{
+ // create mappings for decompiled fields only
+ if (!isTypeDecompiled) {
+ this.DecompiledMemberReferences.Add(field.FullName, field);
+ }
+
output.WriteDefinition(".field ", field);
WriteEnum(field.Attributes & FieldAttributes.FieldAccessMask, fieldVisibility);
WriteFlags(field.Attributes & ~(FieldAttributes.FieldAccessMask | FieldAttributes.HasDefault), fieldAttributes);
@@ -221,8 +237,15 @@ namespace ICSharpCode.Decompiler.Disassembler
{ PropertyAttributes.HasDefault, "hasdefault" },
};
- public void DisassembleProperty(PropertyDefinition property)
+ public void DisassembleProperty(PropertyDefinition property, bool isTypeDecompiled = false)
{
+ // create mappings for decompiled properties only
+ string name = isTypeDecompiled ? property.DeclaringType.FullName : property.FullName;
+ if (!isTypeDecompiled) {
+ this.CodeMappings.Add(name, new List());
+ this.DecompiledMemberReferences.Add(property.FullName, property);
+ }
+
output.WriteDefinition(".property ", property);
WriteFlags(property.Attributes, propertyAttributes);
property.PropertyType.WriteTo(output);
@@ -230,22 +253,22 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write(DisassemblerHelpers.Escape(property.Name));
OpenBlock(false);
WriteAttributes(property.CustomAttributes);
- WriteNestedMethod(".get", property.GetMethod);
- WriteNestedMethod(".set", property.SetMethod);
+ WriteNestedMethod(".get", property.GetMethod, isTypeDecompiled);
+ WriteNestedMethod(".set", property.SetMethod, isTypeDecompiled);
foreach (var method in property.OtherMethods) {
- WriteNestedMethod(".method", method);
+ WriteNestedMethod(".method", method, isTypeDecompiled);
}
CloseBlock();
}
- void WriteNestedMethod(string keyword, MethodDefinition method)
+ void WriteNestedMethod(string keyword, MethodDefinition method, bool isTypeDecompiled)
{
if (method == null)
return;
if (detectControlStructure) {
output.WriteDefinition(keyword, method);
output.Write(' ');
- DisassembleMethodInternal(method);
+ DisassembleMethodInternal(method, isTypeDecompiled);
} else {
output.Write(keyword);
output.Write(' ');
@@ -261,8 +284,15 @@ namespace ICSharpCode.Decompiler.Disassembler
{ EventAttributes.RTSpecialName, "rtspecialname" },
};
- public void DisassembleEvent(EventDefinition ev)
+ public void DisassembleEvent(EventDefinition ev, bool isTypeDecompiled = false)
{
+ // create mappings for decompiled events only
+ string name = isTypeDecompiled ? ev.DeclaringType.FullName : ev.FullName;
+ if (!isTypeDecompiled) {
+ this.CodeMappings.Add(name, new List());
+ this.DecompiledMemberReferences.Add(ev.FullName, ev);
+ }
+
output.WriteDefinition(".event ", ev);
WriteFlags(ev.Attributes, eventAttributes);
ev.EventType.WriteTo(output);
@@ -270,11 +300,11 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write(DisassemblerHelpers.Escape(ev.Name));
OpenBlock(false);
WriteAttributes(ev.CustomAttributes);
- WriteNestedMethod(".add", ev.AddMethod);
- WriteNestedMethod(".remove", ev.RemoveMethod);
- WriteNestedMethod(".invoke", ev.InvokeMethod);
+ WriteNestedMethod(".add", ev.AddMethod, isTypeDecompiled);
+ WriteNestedMethod(".remove", ev.RemoveMethod, isTypeDecompiled);
+ WriteNestedMethod(".invoke", ev.InvokeMethod, isTypeDecompiled);
foreach (var method in ev.OtherMethods) {
- WriteNestedMethod(".method", method);
+ WriteNestedMethod(".method", method, isTypeDecompiled);
}
CloseBlock();
}
@@ -317,8 +347,10 @@ namespace ICSharpCode.Decompiler.Disassembler
public void DisassembleType(TypeDefinition type)
{
// create IL code mappings - used for debugger
- if (this.CodeMappings == null)
- this.CodeMappings = new Tuple>(type.FullName, new List());
+ if (this.CodeMappings == null) {
+ this.CodeMappings.Add(type.FullName, new List());
+ this.DecompiledMemberReferences.Add(type.FullName, type);
+ }
// start writing IL
output.WriteDefinition(".class ", type);
@@ -383,7 +415,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine("// Fields");
foreach (var field in type.Fields) {
cancellationToken.ThrowIfCancellationRequested();
- DisassembleField(field);
+ DisassembleField(field, true);
}
output.WriteLine();
}
@@ -391,7 +423,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine("// Properties");
foreach (var prop in type.Properties) {
cancellationToken.ThrowIfCancellationRequested();
- DisassembleProperty(prop);
+ DisassembleProperty(prop, true);
}
output.WriteLine();
}
@@ -399,7 +431,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine("// Events");
foreach (var ev in type.Events) {
cancellationToken.ThrowIfCancellationRequested();
- DisassembleEvent(ev);
+ DisassembleEvent(ev, true);
output.WriteLine();
}
output.WriteLine();
@@ -410,7 +442,7 @@ namespace ICSharpCode.Decompiler.Disassembler
foreach (var m in type.Methods) {
cancellationToken.ThrowIfCancellationRequested();
if (!(detectControlStructure && accessorMethods.Contains(m))) {
- DisassembleMethod(m);
+ DisassembleMethod(m, true);
output.WriteLine();
}
}
@@ -605,10 +637,14 @@ namespace ICSharpCode.Decompiler.Disassembler
CloseBlock();
}
+ ///
///
- public Tuple> CodeMappings {
- get;
- private set;
- }
+ ///
+ public Dictionary> CodeMappings { get; private set; }
+
+ ///
+ ///
+ ///
+ public Dictionary DecompiledMemberReferences { get; private set; }
}
}
diff --git a/ILSpy/CSharpLanguage.cs b/ILSpy/CSharpLanguage.cs
index 67ba3d078..ceddd89e2 100644
--- a/ILSpy/CSharpLanguage.cs
+++ b/ILSpy/CSharpLanguage.cs
@@ -92,7 +92,7 @@ namespace ICSharpCode.ILSpy
codeDomBuilder.AddMethod(method);
codeDomBuilder.RunTransformations(transformAbortCondition);
codeDomBuilder.GenerateCode(output);
- OnDecompilationFinished(new DecompileEventArgs { CodeMappings = codeDomBuilder.CodeMappings, LocalVariables = codeDomBuilder.LocalVariables });
+ OnDecompilationFinished(new DecompileEventArgs { CodeMappings = codeDomBuilder.CodeMappings, LocalVariables = codeDomBuilder.LocalVariables, DecompiledMemberReferences = codeDomBuilder.DecompiledMemberReferences });
}
public override void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilationOptions options)
@@ -102,7 +102,7 @@ namespace ICSharpCode.ILSpy
codeDomBuilder.AddProperty(property);
codeDomBuilder.RunTransformations(transformAbortCondition);
codeDomBuilder.GenerateCode(output);
- OnDecompilationFinished(new DecompileEventArgs { CodeMappings = codeDomBuilder.CodeMappings, LocalVariables = codeDomBuilder.LocalVariables });
+ OnDecompilationFinished(new DecompileEventArgs { CodeMappings = codeDomBuilder.CodeMappings, LocalVariables = codeDomBuilder.LocalVariables, DecompiledMemberReferences = codeDomBuilder.DecompiledMemberReferences });
}
public override void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options)
@@ -112,7 +112,7 @@ namespace ICSharpCode.ILSpy
codeDomBuilder.AddField(field);
codeDomBuilder.RunTransformations(transformAbortCondition);
codeDomBuilder.GenerateCode(output);
- OnDecompilationFinished(null);
+ OnDecompilationFinished(new DecompileEventArgs { DecompiledMemberReferences = codeDomBuilder.DecompiledMemberReferences });
}
public override void DecompileEvent(EventDefinition ev, ITextOutput output, DecompilationOptions options)
@@ -122,7 +122,7 @@ namespace ICSharpCode.ILSpy
codeDomBuilder.AddEvent(ev);
codeDomBuilder.RunTransformations(transformAbortCondition);
codeDomBuilder.GenerateCode(output);
- OnDecompilationFinished(new DecompileEventArgs { CodeMappings = codeDomBuilder.CodeMappings, LocalVariables = codeDomBuilder.LocalVariables });
+ OnDecompilationFinished(new DecompileEventArgs { CodeMappings = codeDomBuilder.CodeMappings, LocalVariables = codeDomBuilder.LocalVariables, DecompiledMemberReferences = codeDomBuilder.DecompiledMemberReferences });
}
public override void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options)
@@ -131,7 +131,7 @@ namespace ICSharpCode.ILSpy
codeDomBuilder.AddType(type);
codeDomBuilder.RunTransformations(transformAbortCondition);
codeDomBuilder.GenerateCode(output);
- OnDecompilationFinished(new DecompileEventArgs { CodeMappings = codeDomBuilder.CodeMappings, LocalVariables = codeDomBuilder.LocalVariables });
+ OnDecompilationFinished(new DecompileEventArgs { CodeMappings = codeDomBuilder.CodeMappings, LocalVariables = codeDomBuilder.LocalVariables, DecompiledMemberReferences = codeDomBuilder.DecompiledMemberReferences });
}
public override void DecompileAssembly(AssemblyDefinition assembly, string fileName, ITextOutput output, DecompilationOptions options)
diff --git a/ILSpy/Commands/DebuggerCommands.cs b/ILSpy/Commands/DebuggerCommands.cs
index cdc48d51a..461a2d538 100644
--- a/ILSpy/Commands/DebuggerCommands.cs
+++ b/ILSpy/Commands/DebuggerCommands.cs
@@ -163,8 +163,8 @@ namespace ICSharpCode.ILSpy.Commands
// jump to type & expand folding
if (CurrentLineBookmark.Instance != null) {
- if (CurrentLineBookmark.Instance.Member != DebugData.CurrentMemberReference)
- MainWindow.Instance.JumpToReference(CurrentLineBookmark.Instance.Member);
+ if (!DebugData.DecompiledMemberReferences.ContainsKey(CurrentLineBookmark.Instance.MemberReference.FullName))
+ MainWindow.Instance.JumpToReference(CurrentLineBookmark.Instance.MemberReference);
MainWindow.Instance.TextView.UnfoldAndScroll(CurrentLineBookmark.Instance.LineNumber);
}
diff --git a/ILSpy/ILLanguage.cs b/ILSpy/ILLanguage.cs
index ae503d23c..684d57dc3 100644
--- a/ILSpy/ILLanguage.cs
+++ b/ILSpy/ILLanguage.cs
@@ -55,35 +55,35 @@ namespace ICSharpCode.ILSpy
{
var dis = new ReflectionDisassembler(output, detectControlStructure, options.CancellationToken);
dis.DisassembleMethod(method);
- OnDecompilationFinished(new DecompileEventArgs { CodeMappings = dis.CodeMappings });
+ OnDecompilationFinished(new DecompileEventArgs { CodeMappings = dis.CodeMappings, DecompiledMemberReferences = dis.DecompiledMemberReferences });
}
public override void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options)
{
- new ReflectionDisassembler(output, detectControlStructure, options.CancellationToken).DisassembleField(field);
- OnDecompilationFinished(null);
+ var dis = new ReflectionDisassembler(output, detectControlStructure, options.CancellationToken);
+ dis.DisassembleField(field);
+ OnDecompilationFinished(new DecompileEventArgs { DecompiledMemberReferences = dis.DecompiledMemberReferences });
}
public override void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilationOptions options)
{
var dis = new ReflectionDisassembler(output, detectControlStructure, options.CancellationToken);
dis.DisassembleProperty(property);
- OnDecompilationFinished(new DecompileEventArgs { CodeMappings = dis.CodeMappings });
+ OnDecompilationFinished(new DecompileEventArgs { CodeMappings = dis.CodeMappings, DecompiledMemberReferences = dis.DecompiledMemberReferences });
}
public override void DecompileEvent(EventDefinition ev, ITextOutput output, DecompilationOptions options)
{
var dis = new ReflectionDisassembler(output, detectControlStructure, options.CancellationToken);
dis.DisassembleEvent(ev);
- OnDecompilationFinished(new DecompileEventArgs { CodeMappings = dis.CodeMappings });
+ OnDecompilationFinished(new DecompileEventArgs { CodeMappings = dis.CodeMappings, DecompiledMemberReferences = dis.DecompiledMemberReferences });
}
public override void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options)
{
var dis = new ReflectionDisassembler(output, detectControlStructure, options.CancellationToken);
dis.DisassembleType(type);
-
- OnDecompilationFinished(new DecompileEventArgs { CodeMappings = dis.CodeMappings });
+ OnDecompilationFinished(new DecompileEventArgs { CodeMappings = dis.CodeMappings , DecompiledMemberReferences = dis.DecompiledMemberReferences});
}
public override void DecompileNamespace(string nameSpace, IEnumerable types, ITextOutput output, DecompilationOptions options)
diff --git a/ILSpy/Language.cs b/ILSpy/Language.cs
index dfa663a2d..338a0dbf0 100644
--- a/ILSpy/Language.cs
+++ b/ILSpy/Language.cs
@@ -37,12 +37,17 @@ namespace ICSharpCode.ILSpy
///
/// Gets ot sets the code mappings
///
- public Tuple> CodeMappings { get; set; }
+ public Dictionary> CodeMappings { get; set; }
///
/// Gets or sets the local variables.
///
public ConcurrentDictionary> LocalVariables { get; set; }
+
+ ///
+ /// Gets the list of MembeReferences that are decompiled (TypeDefinitions, MethodDefinitions, etc)
+ ///
+ public Dictionary DecompiledMemberReferences { get; set; }
}
///
diff --git a/ILSpy/Options/DebuggerSettingsPanel.xaml b/ILSpy/Options/DebuggerSettingsPanel.xaml
index 27c24d0b6..9b130bb38 100644
--- a/ILSpy/Options/DebuggerSettingsPanel.xaml
+++ b/ILSpy/Options/DebuggerSettingsPanel.xaml
@@ -5,6 +5,9 @@
Show warning messages
+ Debug whole types only
\ No newline at end of file
diff --git a/ILSpy/Options/DebuggerSettingsPanel.xaml.cs b/ILSpy/Options/DebuggerSettingsPanel.xaml.cs
index 0455dfe14..cd5b7a7d8 100644
--- a/ILSpy/Options/DebuggerSettingsPanel.xaml.cs
+++ b/ILSpy/Options/DebuggerSettingsPanel.xaml.cs
@@ -19,6 +19,10 @@ namespace ICSharpCode.ILSpy.Options
[ExportOptionPage(Title = "Debugger", Order = 1)]
partial class DebuggerSettingsPanel : UserControl, IOptionPage
{
+ private const string DEBUGGER_SETTINGS = "DebuggerSettings";
+ private const string SHOW_WARNINGS = "showWarnings";
+ private const string DEBUG_WHOLE_TYPES_ONLY = "debugWholeTypesOnly";
+
public DebuggerSettingsPanel()
{
InitializeComponent();
@@ -39,19 +43,21 @@ namespace ICSharpCode.ILSpy.Options
public static DebuggerSettings LoadDebuggerSettings(ILSpySettings settings)
{
- XElement e = settings["DebuggerSettings"];
+ XElement e = settings[DEBUGGER_SETTINGS];
DebuggerSettings s = new DebuggerSettings();
- s.ShowWarnings = (bool?)e.Attribute("showWarnings") ?? s.ShowWarnings;
+ s.ShowWarnings = (bool?)e.Attribute(SHOW_WARNINGS) ?? s.ShowWarnings;
+ s.DebugWholeTypesOnly = (bool?)e.Attribute(DEBUG_WHOLE_TYPES_ONLY) ?? s.DebugWholeTypesOnly;
return s;
}
public void Save(XElement root)
{
var s = (DebuggerSettings)this.DataContext;
- XElement section = new XElement("DebuggerSettings");
- section.SetAttributeValue("showWarnings", s.ShowWarnings);
+ XElement section = new XElement(DEBUGGER_SETTINGS);
+ section.SetAttributeValue(SHOW_WARNINGS, s.ShowWarnings);
+ section.SetAttributeValue(DEBUG_WHOLE_TYPES_ONLY, s.DebugWholeTypesOnly);
- XElement existingElement = root.Element("DebuggerSettings");
+ XElement existingElement = root.Element(DEBUGGER_SETTINGS);
if (existingElement != null)
existingElement.ReplaceWith(section);
else
diff --git a/ILSpy/TextView/DecompilerTextView.cs b/ILSpy/TextView/DecompilerTextView.cs
index c07d657a8..e1e836feb 100644
--- a/ILSpy/TextView/DecompilerTextView.cs
+++ b/ILSpy/TextView/DecompilerTextView.cs
@@ -44,6 +44,7 @@ using ICSharpCode.ILSpy.Debugger;
using ICSharpCode.ILSpy.Debugger.AvalonEdit;
using ICSharpCode.ILSpy.Debugger.Bookmarks;
using ICSharpCode.ILSpy.Debugger.Tooltips;
+using ICSharpCode.ILSpy.Options;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.XmlDoc;
using ICSharpCode.NRefactory.Documentation;
@@ -335,9 +336,9 @@ namespace ICSharpCode.ILSpy.TextView
void DoDecompile(DecompilationContext context, int outputLengthLimit)
{
// reset type
- DebugData.CurrentMemberReference = null;
DebugData.OldCodeMappings = DebugData.CodeMappings;
TextEditorListener.Instance.ClosePopup();
+ bool isDecompilationOk = true;
RunWithCancellation(
delegate (CancellationToken ct) { // creation of the background task
@@ -363,39 +364,34 @@ namespace ICSharpCode.ILSpy.TextView
output.WriteLine(ex.ToString());
}
ShowOutput(output);
-
- // reset type
- DebugData.CurrentMemberReference = null;
+ isDecompilationOk = false;
}
finally {
// set the language
DebugData.Language = MainWindow.Instance.sessionSettings.FilterSettings.Language.Name.StartsWith("IL") ? DecompiledLanguages.IL : DecompiledLanguages.CSharp;
+ bool debugOnlyTypes = DebuggerSettingsPanel.CurrentDebuggerSettings.DebugWholeTypesOnly;
+ DebugData.DebugWholeTypesOnly = debugOnlyTypes;
- if (DebugData.CurrentMemberReference != null) {
- // TODO: show margin for single methods and properties
- if (context.TreeNodes.Count() == 1 && DebugData.IsCurrentMemberReferenceType) {
- iconMargin.Visibility = Visibility.Visible;
+ if (isDecompilationOk) {
+ if (DebugData.DecompiledMemberReferences != null && DebugData.DecompiledMemberReferences.Count > 0) {
+
// repaint bookmarks
iconMargin.InvalidateVisual();
// show the currentline marker
var bm = CurrentLineBookmark.Instance;
- if (bm != null && DebugData.CurrentMemberReference != null) {
- if (DebugData.CurrentMemberReference == bm.Member) {
+ if (bm != null) {
+ if (DebugData.DecompiledMemberReferences.ContainsKey(bm.MemberReference.FullName)) {
DocumentLine line = textEditor.Document.GetLineByNumber(bm.LineNumber);
bm.Marker = bm.CreateMarker(textMarkerService, line.Offset, line.Length);
}
UnfoldAndScroll(bm.LineNumber);
}
- } else {
- // hide the margin
- iconMargin.Visibility = Visibility.Collapsed;
}
} else {
// remove currentline marker
CurrentLineBookmark.Remove();
- iconMargin.Visibility = Visibility.Collapsed;
}
}
});
@@ -454,9 +450,6 @@ namespace ICSharpCode.ILSpy.TextView
if (i > 0)
textOutput.WriteLine();
- if (nodes[i] is IMemberTreeNode) {
- DebugData.CurrentMemberReference = (nodes[i] as IMemberTreeNode).Member;
- }
context.Options.CancellationToken.ThrowIfCancellationRequested();
nodes[i].Decompile(context.Language, textOutput, context.Options);
}
@@ -466,8 +459,13 @@ namespace ICSharpCode.ILSpy.TextView
static void Language_DecompileFinished(object sender, DecompileEventArgs e)
{
if (e != null) {
- DebugData.CodeMappings = e.CodeMappings;
+ DebugData.CodeMappings = e.CodeMappings;
DebugData.LocalVariables = e.LocalVariables;
+ DebugData.DecompiledMemberReferences = e.DecompiledMemberReferences;
+ } else {
+ DebugData.CodeMappings = null;
+ DebugData.LocalVariables = null;
+ DebugData.DecompiledMemberReferences = null;
}
}
#endregion