Browse Source

sync bookmarks : types/members and C#/IL(not working 100%).

pull/191/merge
Eusebiu Marcu 14 years ago
parent
commit
a0bff8626e
  1. 65
      Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs
  2. 10
      Debugger/ILSpy.Debugger/Bookmarks/BookmarkManager.cs
  3. 3
      Debugger/ILSpy.Debugger/Bookmarks/BreakpointBookmark.cs
  4. 3
      Debugger/ILSpy.Debugger/Bookmarks/CurrentLineBookmark.cs
  5. 5
      Debugger/ILSpy.Debugger/DebuggedData.cs
  6. 18
      Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs
  7. 51
      Debugger/ILSpy.Debugger/Services/ExtensionMethods.cs
  8. 6
      ICSharpCode.Decompiler/CodeMappings.cs
  9. 6
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  10. 3
      ILSpy/Options/DebuggerSettingsPanel.xaml
  11. 6
      ILSpy/Options/DebuggerSettingsPanel.xaml.cs
  12. 5
      ILSpy/TextView/DecompilerTextView.cs

65
Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs

@ -8,12 +8,14 @@ using System.Linq;
using System.Windows; using System.Windows;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using ICSharpCode.AvalonEdit.Editing; using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.AvalonEdit.Rendering; using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.AvalonEdit.Utils; using ICSharpCode.AvalonEdit.Utils;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy.Debugger.Bookmarks; using ICSharpCode.ILSpy.Debugger.Bookmarks;
using ICSharpCode.ILSpy.Debugger.Services; using ICSharpCode.ILSpy.Debugger.Services;
using ICSharpCode.NRefactory.CSharp;
using Mono.Cecil; using Mono.Cecil;
namespace ICSharpCode.ILSpy.Debugger.AvalonEdit namespace ICSharpCode.ILSpy.Debugger.AvalonEdit
@ -62,9 +64,6 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit
if (DebugData.DecompiledMemberReferences == null || DebugData.DecompiledMemberReferences.Count == 0 || if (DebugData.DecompiledMemberReferences == null || DebugData.DecompiledMemberReferences.Count == 0 ||
!DebugData.DecompiledMemberReferences.ContainsKey(bm.MemberReference.FullName)) !DebugData.DecompiledMemberReferences.ContainsKey(bm.MemberReference.FullName))
continue; continue;
if (bm is BreakpointBookmark &&
((BreakpointBookmark)bm).Language != DebugData.Language)
continue;
int line = bm.LineNumber; int line = bm.LineNumber;
BookmarkBase existingBookmark; BookmarkBase existingBookmark;
@ -232,7 +231,7 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit
uint token = 0; uint token = 0;
foreach (var member in DebugData.DecompiledMemberReferences.Values) { foreach (var member in DebugData.DecompiledMemberReferences.Values) {
string memberName = member.FullName; string memberName = member.FullName;
var instruction = storage[memberName].GetInstructionByTypeAndLine(memberName, line, out token); var instruction = storage[memberName].GetInstructionByLineNumber(line, out token);
if (instruction == null) { if (instruction == null) {
continue; continue;
@ -257,5 +256,63 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit
InvalidateVisual(); InvalidateVisual();
} }
} }
public void SyncBookmarks()
{
if (DebugData.CodeMappings == null || DebugData.CodeMappings.Count == 0)
return;
//remove existing bookmarks and create new ones
List<BreakpointBookmark> newBookmarks = new List<BreakpointBookmark>();
for (int i = BookmarkManager.Bookmarks.Count - 1; i >= 0; --i) {
var breakpoint = BookmarkManager.Bookmarks[i] as BreakpointBookmark;
if (breakpoint == null)
continue;
foreach (var key in DebugData.CodeMappings.Keys) {
var member = DebugData.DecompiledMemberReferences[key];
uint token;
if (member is TypeDefinition) {
var m = member as TypeDefinition;
if (breakpoint.MemberReference is TypeDefinition) {
if (member != breakpoint.MemberReference)
continue;
token = (uint)member.MetadataToken.ToInt32();
} else {
if (!m.ContainsMember(breakpoint.MemberReference))
continue;
token = (uint)breakpoint.MemberReference.MetadataToken.ToInt32();
}
} else {
if (breakpoint.MemberReference is TypeDefinition) {
if (!(breakpoint.MemberReference as TypeDefinition).ContainsMember(member))
continue;
token = (uint)member.MetadataToken.ToInt32();
} else {
if (breakpoint.MemberReference != member)
continue;
token = (uint)breakpoint.MemberReference.MetadataToken.ToInt32();
}
}
bool isMatch;
SourceCodeMapping map = DebugData.CodeMappings[key]
.GetInstructionByTokenAndOffset(token, breakpoint.ILRange.From, out isMatch);
if (map != null) {
newBookmarks.Add(new BreakpointBookmark(
DebugData.DecompiledMemberReferences[key],
new AstLocation(map.SourceCodeLine, 0),
map.ILInstructionOffset, BreakpointAction.Break, DebugData.Language));
BookmarkManager.RemoveMark(breakpoint);
break;
}
}
}
newBookmarks.ForEach(m => BookmarkManager.AddMark(m));
}
} }
} }

10
Debugger/ILSpy.Debugger/Bookmarks/BookmarkManager.cs

@ -128,7 +128,7 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks
var newLanguage = e.NewLanguage; var newLanguage = e.NewLanguage;
SyncCurrentLineBookmark(oldLanguage, newLanguage); SyncCurrentLineBookmark(oldLanguage, newLanguage);
SyncBreakpointBookmarks(oldLanguage, newLanguage); //SyncBreakpointBookmarks(oldLanguage, newLanguage);
} }
/// <summary> /// <summary>
@ -152,7 +152,7 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks
int line = CurrentLineBookmark.Instance.LineNumber; int line = CurrentLineBookmark.Instance.LineNumber;
var markerType = CurrentLineBookmark.Instance.MemberReference; var markerType = CurrentLineBookmark.Instance.MemberReference;
if (!oldMappings.ContainsKey(markerType.FullName) || !oldMappings.ContainsKey(markerType.FullName)) if (!oldMappings.ContainsKey(markerType.FullName) || !newMappings.ContainsKey(markerType.FullName))
return; return;
// 2. Remove it // 2. Remove it
@ -160,7 +160,7 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks
// 3. map the marker line // 3. map the marker line
uint token; uint token;
var instruction = oldMappings[markerType.FullName].GetInstructionByTypeAndLine(markerType.FullName, line, out token); var instruction = oldMappings[markerType.FullName].GetInstructionByLineNumber(line, out token);
if (instruction == null) if (instruction == null)
return; return;
@ -195,10 +195,10 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks
foreach (var bp in oldbps) { foreach (var bp in oldbps) {
uint token; uint token;
string name = bp.MemberReference.FullName; string name = bp.MemberReference.FullName;
if (!oldMappings.ContainsKey(name) || !oldMappings.ContainsKey(name)) if (!oldMappings.ContainsKey(name) || !newMappings.ContainsKey(name))
continue; continue;
var instruction = oldMappings[name].GetInstructionByTypeAndLine(bp.MemberReference.FullName, bp.LineNumber, out token); var instruction = oldMappings[name].GetInstructionByLineNumber(bp.LineNumber, out token);
if (instruction == null) if (instruction == null)
continue; continue;

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

@ -91,7 +91,8 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks
ITextMarker marker = markerService.Create(offset, length); ITextMarker marker = markerService.Create(offset, length);
marker.BackgroundColor = Color.FromRgb(180, 38, 38); marker.BackgroundColor = Color.FromRgb(180, 38, 38);
marker.ForegroundColor = Colors.White; marker.ForegroundColor = Colors.White;
marker.IsVisible = b => b is MarkerBookmark && DebugData.DecompiledMemberReferences.ContainsKey(((MarkerBookmark)b).MemberReference.FullName); marker.IsVisible = b => b is MarkerBookmark && DebugData.DecompiledMemberReferences != null &&
DebugData.DecompiledMemberReferences.ContainsKey(((MarkerBookmark)b).MemberReference.FullName);
marker.Bookmark = this; marker.Bookmark = this;
this.Marker = marker; this.Marker = marker;

3
Debugger/ILSpy.Debugger/Bookmarks/CurrentLineBookmark.cs

@ -81,7 +81,8 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks
ITextMarker marker = markerService.Create(offset + startColumn - 1, length + 1); ITextMarker marker = markerService.Create(offset + startColumn - 1, length + 1);
marker.BackgroundColor = Colors.Yellow; marker.BackgroundColor = Colors.Yellow;
marker.ForegroundColor = Colors.Blue; marker.ForegroundColor = Colors.Blue;
marker.IsVisible = b => b is MarkerBookmark && DebugData.DecompiledMemberReferences.ContainsKey(((MarkerBookmark)b).MemberReference.FullName); marker.IsVisible = b => b is MarkerBookmark && DebugData.DecompiledMemberReferences != null &&
DebugData.DecompiledMemberReferences.ContainsKey(((MarkerBookmark)b).MemberReference.FullName);
marker.Bookmark = this; marker.Bookmark = this;
this.Marker = marker; this.Marker = marker;
return marker; return marker;

5
Debugger/ILSpy.Debugger/DebuggedData.cs

@ -57,11 +57,6 @@ namespace ICSharpCode.ILSpy.Debugger
/// </summary> /// </summary>
public static Dictionary<string, MemberReference> DecompiledMemberReferences { get; set; } public static Dictionary<string, MemberReference> DecompiledMemberReferences { get; set; }
/// <summary>
/// Gets or sets the debug type.
/// </summary>
public static bool DebugWholeTypesOnly { get; set; }
/// <summary> /// <summary>
/// Occures when the language is changed. /// Occures when the language is changed.
/// </summary> /// </summary>

18
Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs

@ -289,10 +289,10 @@ namespace ICSharpCode.ILSpy.Debugger.Services
isMatch = false; isMatch = false;
frame = debuggedProcess.SelectedThread.MostRecentStackFrame; frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
var debugType = (DebugType)frame.MethodInfo.DeclaringType; var debugType = (DebugType)frame.MethodInfo.DeclaringType;
string nameKey = DebugData.DebugWholeTypesOnly ? debugType.FullNameWithoutGenericArguments : frame.MethodInfo.FullNameWithoutParameterNames; string nameKey = debugType.FullNameWithoutGenericArguments;
// 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
return DebugData.CodeMappings[nameKey].GetInstructionByTypeTokenAndOffset( return DebugData.CodeMappings[nameKey].GetInstructionByTokenAndOffset(
(uint)frame.MethodInfo.MetadataToken, (uint)frame.MethodInfo.MetadataToken,
frame.IP, out isMatch); frame.IP, out isMatch);
} }
@ -562,7 +562,7 @@ namespace ICSharpCode.ILSpy.Debugger.Services
uint token; uint token;
SourceCodeMapping map = DebugData.CodeMappings[bookmark.MemberReference.FullName] SourceCodeMapping map = DebugData.CodeMappings[bookmark.MemberReference.FullName]
.GetInstructionByTypeAndLine(bookmark.MemberReference.FullName, bookmark.LineNumber, out token); .GetInstructionByLineNumber(bookmark.LineNumber, out token);
if (map != null) { if (map != null) {
var declaringType = bookmark.MemberReference.DeclaringType; var declaringType = bookmark.MemberReference.DeclaringType;
@ -822,7 +822,7 @@ namespace ICSharpCode.ILSpy.Debugger.Services
int ilOffset = frame.IP; int ilOffset = frame.IP;
int line; int line;
MemberReference memberReference; MemberReference memberReference;
string nameKey = DebugData.DebugWholeTypesOnly ? debugType.FullNameWithoutGenericArguments : frame.MethodInfo.FullNameWithoutParameterNames; string nameKey = debugType.FullNameWithoutGenericArguments;
foreach (var key in DebugData.CodeMappings.Keys) { foreach (var key in DebugData.CodeMappings.Keys) {
if (key.CreateKey() == nameKey.CreateKey()) { if (key.CreateKey() == nameKey.CreateKey()) {
@ -883,15 +883,7 @@ namespace ICSharpCode.ILSpy.Debugger.Services
if (!DebugData.CodeMappings.ContainsKey(member.FullName)) { if (!DebugData.CodeMappings.ContainsKey(member.FullName)) {
if (DebugData.Language == DecompiledLanguages.IL) { if (DebugData.Language == DecompiledLanguages.IL) {
var dis = new ReflectionDisassembler(new PlainTextOutput(), true, CancellationToken.None); var dis = new ReflectionDisassembler(new PlainTextOutput(), true, CancellationToken.None);
dis.DisassembleType(nestedTypeDef ?? typeDef);
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; codeMappings = dis.CodeMappings;
} else { } else {
AstBuilder builder = new AstBuilder(new DecompilerContext(typeDef.Module)); AstBuilder builder = new AstBuilder(new DecompilerContext(typeDef.Module));

51
Debugger/ILSpy.Debugger/Services/ExtensionMethods.cs

@ -14,6 +14,8 @@ using System.Windows.Media;
using System.Xml; using System.Xml;
using System.Xml.Linq; using System.Xml.Linq;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.Debugger.Services namespace ICSharpCode.ILSpy.Debugger.Services
{ {
/// <summary> /// <summary>
@ -344,7 +346,7 @@ namespace ICSharpCode.ILSpy.Debugger.Services
int bytes; int bytes;
while ((bytes = sourceStream.Read(buffer, 0, buffer.Length)) > 0) while ((bytes = sourceStream.Read(buffer, 0, buffer.Length)) > 0)
targetStream.Write(buffer, 0, bytes); targetStream.Write(buffer, 0, bytes);
} }
} }
/// <summary> /// <summary>
@ -358,8 +360,8 @@ namespace ICSharpCode.ILSpy.Debugger.Services
public static ScrollViewer GetScrollViewer(this DependencyObject o) public static ScrollViewer GetScrollViewer(this DependencyObject o)
{ {
var scrollViewer = o as ScrollViewer; var scrollViewer = o as ScrollViewer;
if (scrollViewer != null) { if (scrollViewer != null) {
return scrollViewer; return scrollViewer;
} }
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(o); i++) for (int i = 0; i < VisualTreeHelper.GetChildrenCount(o); i++)
@ -398,5 +400,48 @@ namespace ICSharpCode.ILSpy.Debugger.Services
{ {
scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + offset); scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + offset);
} }
/// <summary>
/// Verifies if the type contains the member.
/// </summary>
/// <param name="type"></param>
/// <param name="member"></param>
/// <returns></returns>
public static bool ContainsMember(this TypeDefinition type, MemberReference member)
{
// check fields
if (member is FieldDefinition) {
foreach (var field in type.Fields) {
if (field == member)
return true;
}
}
// check properties
if (member is PropertyDefinition) {
foreach (var field in type.Properties) {
if (field.Resolve() == member)
return true;
}
}
// check methods
if (member is MethodDefinition) {
foreach (var field in type.Methods) {
if (field == member)
return true;
}
}
// check events
if (member is EventDefinition) {
foreach (var field in type.Events) {
if (field == member)
return true;
}
}
return false;
}
} }
} }

6
ICSharpCode.Decompiler/CodeMappings.cs

@ -201,9 +201,8 @@ namespace ICSharpCode.Decompiler
/// <param name="lineNumber">Line number.</param> /// <param name="lineNumber">Line number.</param>
/// <param name="metadataToken">Metadata token.</param> /// <param name="metadataToken">Metadata token.</param>
/// <returns></returns> /// <returns></returns>
public static SourceCodeMapping GetInstructionByTypeAndLine( public static SourceCodeMapping GetInstructionByLineNumber(
this List<MemberMapping> codeMappings, this List<MemberMapping> codeMappings,
string memberReferenceName,
int lineNumber, int lineNumber,
out uint metadataToken) out uint metadataToken)
{ {
@ -226,12 +225,11 @@ namespace ICSharpCode.Decompiler
/// Gets a mapping given a type, a token and an IL offset. /// Gets a mapping given a type, a token and an IL offset.
/// </summary> /// </summary>
/// <param name="codeMappings">Code mappings storage.</param> /// <param name="codeMappings">Code mappings storage.</param>
/// <param name="memberReferenceName">Member reference name.</param>
/// <param name="token">Token.</param> /// <param name="token">Token.</param>
/// <param name="ilOffset">IL offset.</param> /// <param name="ilOffset">IL offset.</param>
/// <param name="isMatch">True, if perfect match.</param> /// <param name="isMatch">True, if perfect match.</param>
/// <returns>A code mapping.</returns> /// <returns>A code mapping.</returns>
public static SourceCodeMapping GetInstructionByTypeTokenAndOffset( public static SourceCodeMapping GetInstructionByTokenAndOffset(
this List<MemberMapping> codeMappings, this List<MemberMapping> codeMappings,
uint token, uint token,
int ilOffset, int ilOffset,

6
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -347,10 +347,8 @@ namespace ICSharpCode.Decompiler.Disassembler
public void DisassembleType(TypeDefinition type) public void DisassembleType(TypeDefinition type)
{ {
// create IL code mappings - used for debugger // create IL code mappings - used for debugger
if (this.CodeMappings == null) { this.CodeMappings.Add(type.FullName, new List<MemberMapping>());
this.CodeMappings.Add(type.FullName, new List<MemberMapping>()); this.DecompiledMemberReferences.Add(type.FullName, type);
this.DecompiledMemberReferences.Add(type.FullName, type);
}
// start writing IL // start writing IL
output.WriteDefinition(".class ", type); output.WriteDefinition(".class ", type);

3
ILSpy/Options/DebuggerSettingsPanel.xaml

@ -5,9 +5,6 @@
<Grid> <Grid>
<StackPanel Margin="10"> <StackPanel Margin="10">
<CheckBox IsChecked="{Binding ShowWarnings}">Show warning messages</CheckBox> <CheckBox IsChecked="{Binding ShowWarnings}">Show warning messages</CheckBox>
<CheckBox
ToolTip="If checked, debug only whole types; otherwise debug only methods or properties."
IsChecked="{Binding DebugWholeTypesOnly}">Debug whole types only</CheckBox>
</StackPanel> </StackPanel>
</Grid> </Grid>
</UserControl> </UserControl>

6
ILSpy/Options/DebuggerSettingsPanel.xaml.cs

@ -21,8 +21,7 @@ namespace ICSharpCode.ILSpy.Options
{ {
private const string DEBUGGER_SETTINGS = "DebuggerSettings"; private const string DEBUGGER_SETTINGS = "DebuggerSettings";
private const string SHOW_WARNINGS = "showWarnings"; private const string SHOW_WARNINGS = "showWarnings";
private const string DEBUG_WHOLE_TYPES_ONLY = "debugWholeTypesOnly";
public DebuggerSettingsPanel() public DebuggerSettingsPanel()
{ {
InitializeComponent(); InitializeComponent();
@ -46,7 +45,7 @@ namespace ICSharpCode.ILSpy.Options
XElement e = settings[DEBUGGER_SETTINGS]; XElement e = settings[DEBUGGER_SETTINGS];
DebuggerSettings s = new DebuggerSettings(); DebuggerSettings s = new DebuggerSettings();
s.ShowWarnings = (bool?)e.Attribute(SHOW_WARNINGS) ?? s.ShowWarnings; s.ShowWarnings = (bool?)e.Attribute(SHOW_WARNINGS) ?? s.ShowWarnings;
s.DebugWholeTypesOnly = (bool?)e.Attribute(DEBUG_WHOLE_TYPES_ONLY) ?? s.DebugWholeTypesOnly;
return s; return s;
} }
@ -55,7 +54,6 @@ namespace ICSharpCode.ILSpy.Options
var s = (DebuggerSettings)this.DataContext; var s = (DebuggerSettings)this.DataContext;
XElement section = new XElement(DEBUGGER_SETTINGS); XElement section = new XElement(DEBUGGER_SETTINGS);
section.SetAttributeValue(SHOW_WARNINGS, s.ShowWarnings); section.SetAttributeValue(SHOW_WARNINGS, s.ShowWarnings);
section.SetAttributeValue(DEBUG_WHOLE_TYPES_ONLY, s.DebugWholeTypesOnly);
XElement existingElement = root.Element(DEBUGGER_SETTINGS); XElement existingElement = root.Element(DEBUGGER_SETTINGS);
if (existingElement != null) if (existingElement != null)

5
ILSpy/TextView/DecompilerTextView.cs

@ -380,11 +380,10 @@ namespace ICSharpCode.ILSpy.TextView
isDecompilationOk = false; isDecompilationOk = false;
} }
finally { finally {
// sync bookmarks
iconMargin.SyncBookmarks();
// set the language // set the language
DebugData.Language = MainWindow.Instance.sessionSettings.FilterSettings.Language.Name.StartsWith("IL") ? DecompiledLanguages.IL : DecompiledLanguages.CSharp; DebugData.Language = MainWindow.Instance.sessionSettings.FilterSettings.Language.Name.StartsWith("IL") ? DecompiledLanguages.IL : DecompiledLanguages.CSharp;
bool debugOnlyTypes = DebuggerSettingsPanel.CurrentDebuggerSettings.DebugWholeTypesOnly;
DebugData.DebugWholeTypesOnly = debugOnlyTypes;
if (isDecompilationOk) { if (isDecompilationOk) {
if (DebugData.DecompiledMemberReferences != null && DebugData.DecompiledMemberReferences.Count > 0) { if (DebugData.DecompiledMemberReferences != null && DebugData.DecompiledMemberReferences.Count > 0) {

Loading…
Cancel
Save