Browse Source

Store code mappings using token as key. Sync bookmarks.

pull/191/merge
Eusebiu Marcu 15 years ago
parent
commit
f6ecd0645a
  1. 4
      Debugger/Debugger.Core/Breakpoint.cs
  2. 59
      Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs
  3. 55
      Debugger/ILSpy.Debugger/Bookmarks/BookmarkManager.cs
  4. 2
      Debugger/ILSpy.Debugger/Bookmarks/BreakpointBookmark.cs
  5. 5
      Debugger/ILSpy.Debugger/Bookmarks/CurrentLineBookmark.cs
  6. 6
      Debugger/ILSpy.Debugger/DebuggedData.cs
  7. 85
      Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs
  8. 43
      Debugger/ILSpy.Debugger/Services/ExtensionMethods.cs
  9. 75
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  10. 40
      ICSharpCode.Decompiler/CodeMappings.cs
  11. 83
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  12. 17
      ILSpy/Commands/DebuggerCommands.cs
  13. 7
      ILSpy/Language.cs
  14. 16
      ILSpy/TextView/DecompilerTextView.cs

4
Debugger/Debugger.Core/Breakpoint.cs

@ -176,7 +176,7 @@ namespace Debugger @@ -176,7 +176,7 @@ namespace Debugger
public class ILBreakpoint : Breakpoint
{
public ILBreakpoint(NDebugger debugger, string typeName, string memberReferenceName, int line, uint metadataToken, int offset, bool enabled)
public ILBreakpoint(NDebugger debugger, string typeName, string memberReferenceName, int line, int metadataToken, int offset, bool enabled)
{
this.Debugger = debugger;
this.Line = line;
@ -187,7 +187,7 @@ namespace Debugger @@ -187,7 +187,7 @@ namespace Debugger
this.Enabled = enabled;
}
public uint MetadataToken { get; private set; }
public int MetadataToken { get; private set; }
public int ILOffset { get; private set; }

59
Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs

@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Input;
@ -62,7 +63,7 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit @@ -62,7 +63,7 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit
Dictionary<int, BookmarkBase> bookmarkDict = new Dictionary<int, BookmarkBase>();
foreach (var bm in BookmarkManager.Bookmarks) {
if (DebugData.DecompiledMemberReferences == null || DebugData.DecompiledMemberReferences.Count == 0 ||
!DebugData.DecompiledMemberReferences.ContainsKey(bm.MemberReference.FullName))
!DebugData.DecompiledMemberReferences.ContainsKey(bm.MemberReference.MetadataToken.ToInt32()))
continue;
int line = bm.LineNumber;
@ -121,7 +122,7 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit @@ -121,7 +122,7 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit
BookmarkBase result = null;
foreach (BookmarkBase bm in BookmarkManager.Bookmarks) {
if (bm.LineNumber == line &&
DebugData.DecompiledMemberReferences != null && DebugData.DecompiledMemberReferences.ContainsKey(bm.MemberReference.FullName)) {
DebugData.DecompiledMemberReferences != null && DebugData.DecompiledMemberReferences.ContainsKey(bm.MemberReference.MetadataToken.ToInt32())) {
if (result == null || bm.ZOrder > result.ZOrder)
result = bm;
}
@ -191,7 +192,7 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit @@ -191,7 +192,7 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit
}
BreakpointBookmark bm = BookmarkManager.Bookmarks.Find(
b => DebugData.CodeMappings.ContainsKey(b.MemberReference.FullName) &&
b => DebugData.CodeMappings != null && DebugData.CodeMappings.ContainsKey(b.MemberReference.MetadataToken.ToInt32()) &&
b.LineNumber == GetLineFromMousePosition(e)
&& b is BreakpointBookmark) as BreakpointBookmark;
@ -224,14 +225,13 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit @@ -224,14 +225,13 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit
return;
}
if (e.ChangedButton == MouseButton.Left) {
if (DebugData.DecompiledMemberReferences != null && DebugData.DecompiledMemberReferences.Count > 0) {
if (DebugData.CodeMappings != null && DebugData.CodeMappings.Count > 0) {
// check if the codemappings exists for this line
var storage = DebugData.CodeMappings;
uint token = 0;
foreach (var member in DebugData.DecompiledMemberReferences.Values) {
string memberName = member.FullName;
var instruction = storage[memberName].GetInstructionByLineNumber(line, out token);
int token = 0;
foreach (var key in storage.Keys) {
var instruction = storage[key].GetInstructionByLineNumber(line, out token);
if (instruction == null) {
continue;
@ -239,7 +239,7 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit @@ -239,7 +239,7 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit
// no bookmark on the line: create a new breakpoint
DebuggerService.ToggleBreakpointAt(
member,
DebugData.DecompiledMemberReferences[key],
line,
instruction.ILInstructionOffset,
DebugData.Language);
@ -259,7 +259,8 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit @@ -259,7 +259,8 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit
public void SyncBookmarks()
{
if (DebugData.CodeMappings == null || DebugData.CodeMappings.Count == 0)
var storage = DebugData.CodeMappings;
if (storage == null || storage.Count == 0)
return;
//remove existing bookmarks and create new ones
@ -269,46 +270,22 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit @@ -269,46 +270,22 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit
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)
var key = breakpoint.MemberReference.MetadataToken.ToInt32();
if (!storage.ContainsKey(key))
continue;
token = (uint)breakpoint.MemberReference.MetadataToken.ToInt32();
}
}
var member = DebugData.DecompiledMemberReferences[key];
bool isMatch;
SourceCodeMapping map = DebugData.CodeMappings[key]
.GetInstructionByTokenAndOffset(token, breakpoint.ILRange.From, out isMatch);
SourceCodeMapping map = storage[key].GetInstructionByTokenAndOffset(
member.MetadataToken.ToInt32(), breakpoint.ILRange.From, out isMatch);
if (map != null) {
newBookmarks.Add(new BreakpointBookmark(
DebugData.DecompiledMemberReferences[key],
new AstLocation(map.SourceCodeLine, 0),
member, new AstLocation(map.SourceCodeLine, 0),
map.ILInstructionOffset, BreakpointAction.Break, DebugData.Language));
BookmarkManager.RemoveMark(breakpoint);
break;
}
}
}

55
Debugger/ILSpy.Debugger/Bookmarks/BookmarkManager.cs

@ -152,71 +152,24 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks @@ -152,71 +152,24 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks
int line = CurrentLineBookmark.Instance.LineNumber;
var markerType = CurrentLineBookmark.Instance.MemberReference;
if (!oldMappings.ContainsKey(markerType.FullName) || !newMappings.ContainsKey(markerType.FullName))
if (!oldMappings.ContainsKey(markerType.MetadataToken.ToInt32()) || !newMappings.ContainsKey(markerType.MetadataToken.ToInt32()))
return;
// 2. Remove it
CurrentLineBookmark.Remove();
// 3. map the marker line
uint token;
var instruction = oldMappings[markerType.FullName].GetInstructionByLineNumber(line, out token);
int token;
var instruction = oldMappings[markerType.MetadataToken.ToInt32()].GetInstructionByLineNumber(line, out token);
if (instruction == null)
return;
MemberReference memberReference;
int newline;
if (newMappings[markerType.FullName].GetSourceCodeFromMetadataTokenAndOffset(token, instruction.ILInstructionOffset.From, out memberReference, out newline)) {
if (newMappings[markerType.MetadataToken.ToInt32()].GetSourceCodeFromMetadataTokenAndOffset(token, instruction.ILInstructionOffset.From, out memberReference, out newline)) {
// 4. create breakpoint for new languages
CurrentLineBookmark.SetPosition(memberReference, newline, 0, newline, 0);
}
}
/// <summary>
/// Synchronize the IL<->C# breakpoints bookmarks.
/// </summary>
/// <param name="oldLanguage">Old language.</param>
/// <param name="newLanguage">New language.</param>
static void SyncBreakpointBookmarks(DecompiledLanguages oldLanguage, DecompiledLanguages newLanguage)
{
// checks
var oldMappings = DebugData.OldCodeMappings;
var newMappings = DebugData.CodeMappings;
if (oldMappings == null || newMappings == null)
return;
// 1. map the breakpoint lines
var oldbps = bookmarks.FindAll(b => b is BreakpointBookmark &&
((BreakpointBookmark)b).Language == oldLanguage);
if (oldbps == null || oldbps.Count == 0)
return;
foreach (var bp in oldbps) {
uint token;
string name = bp.MemberReference.FullName;
if (!oldMappings.ContainsKey(name) || !newMappings.ContainsKey(name))
continue;
var instruction = oldMappings[name].GetInstructionByLineNumber(bp.LineNumber, out token);
if (instruction == null)
continue;
MemberReference memberReference;
int 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), instruction.ILInstructionOffset, BreakpointAction.Break, newLanguage);
AddMark(bookmark);
}
}
// 3. remove all breakpoints for the old language
for (int i = bookmarks.Count - 1; i >= 0; --i) {
var bm = bookmarks[i];
if (bm is BreakpointBookmark && ((BreakpointBookmark)bm).Language == oldLanguage)
RemoveMark(bm);
}
}
}
}

2
Debugger/ILSpy.Debugger/Bookmarks/BreakpointBookmark.cs

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

5
Debugger/ILSpy.Debugger/Bookmarks/CurrentLineBookmark.cs

@ -3,9 +3,10 @@ @@ -3,9 +3,10 @@
using System;
using System.Windows.Media;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy.Debugger.AvalonEdit;
using ICSharpCode.ILSpy.Debugger.Services;
using ICSharpCode.NRefactory.CSharp;
using Mono.Cecil;
using Mono.CSharp;
@ -82,7 +83,7 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks @@ -82,7 +83,7 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks
marker.BackgroundColor = Colors.Yellow;
marker.ForegroundColor = Colors.Blue;
marker.IsVisible = b => b is MarkerBookmark && DebugData.DecompiledMemberReferences != null &&
DebugData.DecompiledMemberReferences.ContainsKey(((MarkerBookmark)b).MemberReference.FullName);
DebugData.DecompiledMemberReferences.ContainsKey(((MarkerBookmark)b).MemberReference.MetadataToken.ToInt32());
marker.Bookmark = this;
this.Marker = marker;
return marker;

6
Debugger/ILSpy.Debugger/DebuggedData.cs

@ -40,7 +40,7 @@ namespace ICSharpCode.ILSpy.Debugger @@ -40,7 +40,7 @@ namespace ICSharpCode.ILSpy.Debugger
/// <summary>
/// Gets or sets the current code mappings.
/// </summary>
public static Dictionary<string, List<MemberMapping>> CodeMappings { get; set; }
public static Dictionary<int, List<MemberMapping>> CodeMappings { get; set; }
/// <summary>
/// Gets or sets the local variables of the current decompiled type, method, etc.
@ -50,12 +50,12 @@ namespace ICSharpCode.ILSpy.Debugger @@ -50,12 +50,12 @@ namespace ICSharpCode.ILSpy.Debugger
/// <summary>
/// Gets or sets the old code mappings.
/// </summary>
public static Dictionary<string, List<MemberMapping>> OldCodeMappings { get; set; }
public static Dictionary<int, List<MemberMapping>> OldCodeMappings { get; set; }
/// <summary>
/// Gets or sets the MembeReference that was decompiled (a TypeDefinition, MethodDefinition, etc)
/// </summary>
public static Dictionary<string, MemberReference> DecompiledMemberReferences { get; set; }
public static Dictionary<int, MemberReference> DecompiledMemberReferences { get; set; }
/// <summary>
/// Occures when the language is changed.

85
Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs

@ -288,13 +288,10 @@ namespace ICSharpCode.ILSpy.Debugger.Services @@ -288,13 +288,10 @@ namespace ICSharpCode.ILSpy.Debugger.Services
{
isMatch = false;
frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
var debugType = (DebugType)frame.MethodInfo.DeclaringType;
string nameKey = debugType.FullNameWithoutGenericArguments;
int key = frame.MethodInfo.MetadataToken;
// get the mapped instruction from the current line marker or the next one
return DebugData.CodeMappings[nameKey].GetInstructionByTokenAndOffset(
(uint)frame.MethodInfo.MetadataToken,
frame.IP, out isMatch);
return DebugData.CodeMappings[key].GetInstructionByTokenAndOffset(key, frame.IP, out isMatch);
}
StackFrame GetStackFrame()
@ -560,25 +557,14 @@ namespace ICSharpCode.ILSpy.Debugger.Services @@ -560,25 +557,14 @@ namespace ICSharpCode.ILSpy.Debugger.Services
{
Breakpoint breakpoint = null;
uint token;
SourceCodeMapping map = DebugData.CodeMappings[bookmark.MemberReference.FullName]
.GetInstructionByLineNumber(bookmark.LineNumber, out token);
if (map != null) {
var declaringType = bookmark.MemberReference.DeclaringType;
breakpoint = new ILBreakpoint(
debugger,
(declaringType ?? bookmark.MemberReference).FullName,
bookmark.MemberReference.DeclaringType.FullName,
bookmark.MemberReference.FullName,
bookmark.LineNumber,
token,
map.ILInstructionOffset.From,
bookmark.MemberReference.MetadataToken.ToInt32(),
bookmark.ILRange.From,
bookmark.IsEnabled);
}
if (breakpoint == null)
return;
debugger.Breakpoints.Add(breakpoint);
// Action setBookmarkColor = delegate {
@ -749,7 +735,7 @@ namespace ICSharpCode.ILSpy.Debugger.Services @@ -749,7 +735,7 @@ namespace ICSharpCode.ILSpy.Debugger.Services
foreach (var bookmark in DebuggerService.Breakpoints) {
var breakpoint =
debugger.Breakpoints.FirstOrDefault(
b => b.Line == bookmark.LineNumber && (b as ILBreakpoint).MemberReferenceName.CreateKey() == bookmark.MemberReference.FullName.CreateKey());
b => b.Line == bookmark.LineNumber && (b as ILBreakpoint).MetadataToken == bookmark.MemberReference.MetadataToken.ToInt32());
if (breakpoint == null)
continue;
// set the breakpoint only if the module contains the type
@ -817,16 +803,13 @@ namespace ICSharpCode.ILSpy.Debugger.Services @@ -817,16 +803,13 @@ namespace ICSharpCode.ILSpy.Debugger.Services
if (frame == null)
return;
uint token = (uint)frame.MethodInfo.MetadataToken;
var debugType = (DebugType)frame.MethodInfo.DeclaringType;
int token = frame.MethodInfo.MetadataToken;
int ilOffset = frame.IP;
int line;
MemberReference memberReference;
string nameKey = debugType.FullNameWithoutGenericArguments;
foreach (var key in DebugData.CodeMappings.Keys) {
if (key.CreateKey() == nameKey.CreateKey()) {
if (DebugData.CodeMappings[key].GetSourceCodeFromMetadataTokenAndOffset(token, ilOffset, out memberReference, out line)) {
if (DebugData.CodeMappings.ContainsKey(token)) {
if (DebugData.CodeMappings[token].GetSourceCodeFromMetadataTokenAndOffset(token, ilOffset, out memberReference, out line)) {
DebuggerService.RemoveCurrentLineMarker();
DebuggerService.JumpToCurrentLine(memberReference, line, 0, line, 0);
} else {
@ -834,15 +817,19 @@ namespace ICSharpCode.ILSpy.Debugger.Services @@ -834,15 +817,19 @@ namespace ICSharpCode.ILSpy.Debugger.Services
DecompileOnDemand(frame);
}
}
else {
// is possible that the type is not decompiled yet, so we must do a decompilation on demand
DecompileOnDemand(frame);
}
}
}
void DecompileOnDemand(StackFrame frame)
{
string debuggeeVersion = frame.MethodInfo.DebugModule.Process.DebuggeeVersion.Substring(1, 3); // should retrieve 2.0, 3.0, 4.0
var debugType = (DebugType)frame.MethodInfo.DeclaringType;
uint token = (uint)frame.MethodInfo.MetadataToken;
int token = frame.MethodInfo.MetadataToken;
int ilOffset = frame.IP;
string fullName = debugType.FullNameWithoutGenericArguments;
@ -852,7 +839,6 @@ namespace ICSharpCode.ILSpy.Debugger.Services @@ -852,7 +839,6 @@ 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")) &&
@ -876,40 +862,55 @@ namespace ICSharpCode.ILSpy.Debugger.Services @@ -876,40 +862,55 @@ namespace ICSharpCode.ILSpy.Debugger.Services
}
if (typeDef != null) {
member = nestedTypeDef ?? typeDef;
TypeDefinition type = nestedTypeDef ?? typeDef;
MemberReference memberReference = null;
// decompile on demand if the type was not decompiled
Dictionary<string, List<MemberMapping>> codeMappings = null;
if (!DebugData.CodeMappings.ContainsKey(member.FullName)) {
// decompile on demand if the type was no decompiled
Dictionary<int, List<MemberMapping>> codeMappings = null;
Dictionary<int, MemberReference> members = null;
if (!DebugData.CodeMappings.ContainsKey(token)) {
if (DebugData.Language == DecompiledLanguages.IL) {
var dis = new ReflectionDisassembler(new PlainTextOutput(), true, CancellationToken.None);
dis.DisassembleType(nestedTypeDef ?? typeDef);
dis.DisassembleType(type);
codeMappings = dis.CodeMappings;
} else {
// decompile type
AstBuilder builder = new AstBuilder(new DecompilerContext(typeDef.Module));
builder.AddType(nestedTypeDef ?? typeDef);
builder.AddType(type);
builder.GenerateCode(new PlainTextOutput());
memberReference = builder.DecompiledMemberReferences[token];
// decompile member
var context = new DecompilerContext(typeDef.Module);
context.CurrentType = type;
builder = new AstBuilder(context);
if (memberReference is PropertyDefinition)
builder.AddProperty(memberReference as PropertyDefinition);
else if (memberReference is MethodDefinition)
builder.AddMethod(memberReference as MethodDefinition);
else if (memberReference is EventDefinition)
builder.AddEvent(memberReference as EventDefinition);
builder.GenerateCode(new PlainTextOutput());
codeMappings = builder.CodeMappings;
DebugData.CodeMappings = codeMappings = builder.CodeMappings;
DebugData.DecompiledMemberReferences = members = builder.DecompiledMemberReferences;
}
}
// try jump
int line;
MemberReference memberReference;
codeMappings = codeMappings ?? DebugData.CodeMappings;
string name = (nestedTypeDef ?? typeDef).FullName;
if (codeMappings[name].GetSourceCodeFromMetadataTokenAndOffset(token, ilOffset, out memberReference, out line)) {
if (codeMappings[token].GetSourceCodeFromMetadataTokenAndOffset(token, ilOffset, out memberReference, out line)) {
DebuggerService.RemoveCurrentLineMarker();
DebuggerService.JumpToCurrentLine(nestedTypeDef ?? typeDef, line, 0, line, 0);
DebuggerService.JumpToCurrentLine(members[token], line, 0, line, 0);
} else {
StepOut();
}
} else {
// continue since we cannot find the debugged type
Debug.Assert(typeDef != null, string.Format("The type {0} was not found!", fullName));
}
}
}
public void ShowAttachDialog()
{
throw new NotImplementedException();

43
Debugger/ILSpy.Debugger/Services/ExtensionMethods.cs

@ -400,48 +400,5 @@ namespace ICSharpCode.ILSpy.Debugger.Services @@ -400,48 +400,5 @@ namespace ICSharpCode.ILSpy.Debugger.Services
{
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;
}
}
}

75
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -46,8 +46,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -46,8 +46,8 @@ namespace ICSharpCode.Decompiler.Ast
this.DecompileMethodBodies = true;
this.LocalVariables = new ConcurrentDictionary<int, IEnumerable<ILVariable>>();
this.CodeMappings = new Dictionary<string, List<MemberMapping>>();
this.DecompiledMemberReferences = new Dictionary<string, MemberReference>();
this.CodeMappings = new Dictionary<int, List<MemberMapping>>();
this.DecompiledMemberReferences = new Dictionary<int, MemberReference>();
}
public static bool MemberIsHidden(MemberReference member, DecompilerSettings settings)
@ -161,10 +161,6 @@ namespace ICSharpCode.Decompiler.Ast @@ -161,10 +161,6 @@ 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<MemberMapping>());
var astType = CreateType(typeDef);
NamespaceDeclaration astNS = GetCodeNamespace(typeDef.Namespace);
if (astNS != null) {
@ -176,36 +172,22 @@ namespace ICSharpCode.Decompiler.Ast @@ -176,36 +172,22 @@ namespace ICSharpCode.Decompiler.Ast
public void AddMethod(MethodDefinition method)
{
// add to mappings information
this.CodeMappings.Add(method.FullName, new List<MemberMapping>());
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<MemberMapping>());
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<MemberMapping>());
astCompileUnit.AddChild(CreateEvent(ev), CompilationUnit.MemberRole);
}
@ -619,12 +601,12 @@ namespace ICSharpCode.Decompiler.Ast @@ -619,12 +601,12 @@ namespace ICSharpCode.Decompiler.Ast
// Add events
foreach(EventDefinition eventDef in typeDef.Events) {
astType.AddChild(CreateEvent(eventDef, true), TypeDeclaration.MemberRole);
astType.AddChild(CreateEvent(eventDef), TypeDeclaration.MemberRole);
}
// Add properties
foreach(PropertyDefinition propDef in typeDef.Properties) {
astType.Members.Add(CreateProperty(propDef, true));
astType.Members.Add(CreateProperty(propDef));
}
// Add methods
@ -632,17 +614,17 @@ namespace ICSharpCode.Decompiler.Ast @@ -632,17 +614,17 @@ namespace ICSharpCode.Decompiler.Ast
if (MemberIsHidden(methodDef, context.Settings)) continue;
if (methodDef.IsConstructor)
astType.Members.Add(CreateConstructor(methodDef, true));
astType.Members.Add(CreateConstructor(methodDef));
else
astType.Members.Add(CreateMethod(methodDef, true));
astType.Members.Add(CreateMethod(methodDef));
}
}
AttributedNode CreateMethod(MethodDefinition methodDef, bool isTypeDecompiled = false)
AttributedNode CreateMethod(MethodDefinition methodDef)
{
// Create mapping - used in debugger
string name = isTypeDecompiled ? methodDef.DeclaringType.FullName : methodDef.FullName;
MemberMapping methodMapping = methodDef.CreateCodeMapping(this.CodeMappings[name], isTypeDecompiled);
int currentMemberToken = CreateCodeMappings(methodDef.MetadataToken.ToInt32(), methodDef);
MemberMapping methodMapping = methodDef.CreateCodeMapping(this.CodeMappings[currentMemberToken]);
MethodDeclaration astMethod = new MethodDeclaration();
astMethod.AddAnnotation(methodDef);
@ -734,11 +716,11 @@ namespace ICSharpCode.Decompiler.Ast @@ -734,11 +716,11 @@ namespace ICSharpCode.Decompiler.Ast
}
}
ConstructorDeclaration CreateConstructor(MethodDefinition methodDef, bool isTypeDecompiled = false)
ConstructorDeclaration CreateConstructor(MethodDefinition methodDef)
{
// Create mapping - used in debugger
string name = isTypeDecompiled ? methodDef.DeclaringType.FullName : methodDef.FullName;
MemberMapping methodMapping = methodDef.CreateCodeMapping(this.CodeMappings[name], isTypeDecompiled);
int currentMemberToken = CreateCodeMappings(methodDef.MetadataToken.ToInt32(), methodDef);
MemberMapping methodMapping = methodDef.CreateCodeMapping(this.CodeMappings[currentMemberToken]);
ConstructorDeclaration astMethod = new ConstructorDeclaration();
astMethod.AddAnnotation(methodDef);
@ -768,7 +750,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -768,7 +750,7 @@ namespace ICSharpCode.Decompiler.Ast
return m & ~Modifiers.Private;
}
MemberDeclaration CreateProperty(PropertyDefinition propDef, bool isTypeDecompiled = false)
MemberDeclaration CreateProperty(PropertyDefinition propDef)
{
PropertyDeclaration astProp = new PropertyDeclaration();
astProp.AddAnnotation(propDef);
@ -804,11 +786,10 @@ namespace ICSharpCode.Decompiler.Ast @@ -804,11 +786,10 @@ 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[name], isTypeDecompiled);
int currentMemberToken = CreateCodeMappings(propDef.GetMethod.MetadataToken.ToInt32(), propDef);
MemberMapping methodMapping = propDef.GetMethod.CreateCodeMapping(this.CodeMappings[currentMemberToken]);
astProp.Getter = new Accessor();
astProp.Getter.Body = CreateMethodBody(propDef.GetMethod);
@ -822,7 +803,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -822,7 +803,8 @@ namespace ICSharpCode.Decompiler.Ast
}
if (propDef.SetMethod != null) {
// Create mapping - used in debugger
MemberMapping methodMapping = propDef.SetMethod.CreateCodeMapping(this.CodeMappings[name], isTypeDecompiled);
int currentMemberToken = CreateCodeMappings(propDef.SetMethod.MetadataToken.ToInt32(), propDef);
MemberMapping methodMapping = propDef.SetMethod.CreateCodeMapping(this.CodeMappings[currentMemberToken]);
astProp.Setter = new Accessor();
astProp.Setter.Body = CreateMethodBody(propDef.SetMethod);
@ -858,7 +840,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -858,7 +840,7 @@ namespace ICSharpCode.Decompiler.Ast
return astIndexer;
}
AttributedNode CreateEvent(EventDefinition eventDef, bool isTypeDecompiled = false)
AttributedNode CreateEvent(EventDefinition eventDef)
{
if (eventDef.AddMethod != null && eventDef.AddMethod.IsAbstract) {
// An abstract event cannot be custom
@ -881,11 +863,10 @@ namespace ICSharpCode.Decompiler.Ast @@ -881,11 +863,10 @@ namespace ICSharpCode.Decompiler.Ast
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[name], isTypeDecompiled);
int currentMemberToken = CreateCodeMappings(eventDef.AddMethod.MetadataToken.ToInt32(), eventDef);
MemberMapping methodMapping = eventDef.AddMethod.CreateCodeMapping(this.CodeMappings[currentMemberToken]);
astEvent.AddAccessor = new Accessor {
Body = CreateMethodBody(eventDef.AddMethod)
@ -896,7 +877,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -896,7 +877,8 @@ namespace ICSharpCode.Decompiler.Ast
}
if (eventDef.RemoveMethod != null) {
// Create mapping - used in debugger
MemberMapping methodMapping = eventDef.AddMethod.CreateCodeMapping(this.CodeMappings[name], isTypeDecompiled);
int currentMemberToken = CreateCodeMappings(eventDef.RemoveMethod.MetadataToken.ToInt32(), eventDef);
MemberMapping methodMapping = eventDef.RemoveMethod.CreateCodeMapping(this.CodeMappings[currentMemberToken]);
astEvent.RemoveAccessor = new Accessor {
Body = CreateMethodBody(eventDef.RemoveMethod)
@ -926,6 +908,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -926,6 +908,8 @@ namespace ICSharpCode.Decompiler.Ast
FieldDeclaration CreateField(FieldDefinition fieldDef)
{
this.DecompiledMemberReferences.Add(fieldDef.MetadataToken.ToInt32(), fieldDef);
FieldDeclaration astField = new FieldDeclaration();
astField.AddAnnotation(fieldDef);
VariableInitializer initializer = new VariableInitializer(CleanName(fieldDef.Name));
@ -1395,7 +1379,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -1395,7 +1379,7 @@ namespace ICSharpCode.Decompiler.Ast
/// <summary>
/// <inheritdoc/>
/// </summary>
public Dictionary<string, List<MemberMapping>> CodeMappings { get; private set; }
public Dictionary<int, List<MemberMapping>> CodeMappings { get; private set; }
/// <summary>
/// Gets the local variables for the current decompiled type, method, etc.
@ -1406,6 +1390,13 @@ namespace ICSharpCode.Decompiler.Ast @@ -1406,6 +1390,13 @@ namespace ICSharpCode.Decompiler.Ast
/// <summary>
/// <inheritdoc/>
/// </summary>
public Dictionary<string, MemberReference> DecompiledMemberReferences { get; private set; }
public Dictionary<int, MemberReference> DecompiledMemberReferences { get; private set; }
private int CreateCodeMappings(int token, MemberReference member)
{
this.CodeMappings.Add(token, new List<MemberMapping>());
this.DecompiledMemberReferences.Add(token, member);
return token;
}
}
}

40
ICSharpCode.Decompiler/CodeMappings.cs

@ -41,13 +41,15 @@ namespace ICSharpCode.Decompiler @@ -41,13 +41,15 @@ namespace ICSharpCode.Decompiler
{
/// <summary>
/// Gets the code mappings.
/// <remarks>Key is the metadata token.</remarks>
/// </summary>
Dictionary<string, List<MemberMapping>> CodeMappings { get; }
Dictionary<int, List<MemberMapping>> CodeMappings { get; }
/// <summary>
/// Gets the MembeReference that is decompiled (a TypeDefinition, MethodDefinition, etc)
/// <remarks>Key is the metadata token.</remarks>
/// </summary>
Dictionary<string, MemberReference> DecompiledMemberReferences { get; }
Dictionary<int, MemberReference> DecompiledMemberReferences { get; }
}
/// <summary>
@ -117,9 +119,9 @@ namespace ICSharpCode.Decompiler @@ -117,9 +119,9 @@ namespace ICSharpCode.Decompiler
public MemberReference MemberReference { get; internal set; }
/// <summary>
/// Metadata token of the method.
/// Metadata token of the member.
/// </summary>
public uint MetadataToken { get; internal set; }
public int MetadataToken { get; internal set; }
/// <summary>
/// Gets or sets the code size for the member mapping.
@ -162,8 +164,7 @@ namespace ICSharpCode.Decompiler @@ -162,8 +164,7 @@ namespace ICSharpCode.Decompiler
/// <param name="isTypeDecompiled">True, if a full type was decompiled; false otherwise.</param>
internal static MemberMapping CreateCodeMapping(
this MethodDefinition member,
List<MemberMapping> codeMappings,
bool isTypeDecompiled)
List<MemberMapping> codeMappings)
{
if (member == null || !member.HasBody)
return null;
@ -173,20 +174,15 @@ namespace ICSharpCode.Decompiler @@ -173,20 +174,15 @@ namespace ICSharpCode.Decompiler
// create IL/CSharp code mappings - used in debugger
MemberMapping currentMemberMapping = null;
string key = isTypeDecompiled ? member.DeclaringType.FullName : member.FullName;
if (codeMappings.Find(map => (int)map.MetadataToken == member.MetadataToken.ToInt32()) == null) {
if (codeMappings.Find(map => map.MetadataToken == member.MetadataToken.ToInt32()) == null) {
currentMemberMapping = new MemberMapping() {
MetadataToken = (uint)member.MetadataToken.ToInt32(),
MetadataToken = member.MetadataToken.ToInt32(),
MemberCodeMappings = new List<SourceCodeMapping>(),
MemberReference = member,
CodeSize = member.Body.CodeSize
};
if (isTypeDecompiled)
currentMemberMapping.MemberReference = member.DeclaringType.Resolve();
else
currentMemberMapping.MemberReference = member.Resolve();
codeMappings.Add(currentMemberMapping);
}
@ -204,7 +200,7 @@ namespace ICSharpCode.Decompiler @@ -204,7 +200,7 @@ namespace ICSharpCode.Decompiler
public static SourceCodeMapping GetInstructionByLineNumber(
this List<MemberMapping> codeMappings,
int lineNumber,
out uint metadataToken)
out int metadataToken)
{
if (codeMappings == null)
throw new ArgumentException("CodeMappings storage must be valid!");
@ -231,7 +227,7 @@ namespace ICSharpCode.Decompiler @@ -231,7 +227,7 @@ namespace ICSharpCode.Decompiler
/// <returns>A code mapping.</returns>
public static SourceCodeMapping GetInstructionByTokenAndOffset(
this List<MemberMapping> codeMappings,
uint token,
int token,
int ilOffset,
out bool isMatch)
{
@ -273,7 +269,7 @@ namespace ICSharpCode.Decompiler @@ -273,7 +269,7 @@ namespace ICSharpCode.Decompiler
/// <remarks>It is possible to exist to different types from different assemblies with the same metadata token.</remarks>
public static bool GetSourceCodeFromMetadataTokenAndOffset(
this List<MemberMapping> codeMappings,
uint token,
int token,
int ilOffset,
out MemberReference member,
out int line)
@ -303,15 +299,5 @@ namespace ICSharpCode.Decompiler @@ -303,15 +299,5 @@ namespace ICSharpCode.Decompiler
line = codeMapping.SourceCodeLine;
return true;
}
/// <summary>
/// Create a key by replacing "::" with ".", "+" with "/", " " with "";
/// </summary>
/// <param name="item">Item to convert.</param>
/// <returns></returns>
public static string CreateKey(this string item)
{
return item.Replace("+", "/").Replace("::", ".").Replace(" ", string.Empty);
}
}
}

83
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -35,6 +35,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -35,6 +35,7 @@ namespace ICSharpCode.Decompiler.Disassembler
bool detectControlStructure;
bool isInType; // whether we are currently disassembling a whole type (-> defaultCollapsed for foldings)
MethodBodyDisassembler methodBodyDisassembler;
int currentMemberToken;
public ReflectionDisassembler(ITextOutput output, bool detectControlStructure, CancellationToken cancellationToken)
{
@ -45,8 +46,8 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -45,8 +46,8 @@ namespace ICSharpCode.Decompiler.Disassembler
this.detectControlStructure = detectControlStructure;
this.methodBodyDisassembler = new MethodBodyDisassembler(output, detectControlStructure, cancellationToken);
this.CodeMappings = new Dictionary<string, List<MemberMapping>>();
this.DecompiledMemberReferences = new Dictionary<string, MemberReference>();
this.CodeMappings = new Dictionary<int, List<MemberMapping>>();
this.DecompiledMemberReferences = new Dictionary<int, MemberReference>();
}
#region Disassemble Method
@ -95,21 +96,17 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -95,21 +96,17 @@ namespace ICSharpCode.Decompiler.Disassembler
{ MethodImplAttributes.NoOptimization, "nooptimization" },
};
public void DisassembleMethod(MethodDefinition method, bool isTypeDecompiled = false)
public void DisassembleMethod(MethodDefinition method)
{
// create mappings for decompiled methods only
string name = isTypeDecompiled ? method.DeclaringType.FullName : method.FullName;
if (!isTypeDecompiled) {
this.CodeMappings.Add(name, new List<MemberMapping>());
this.DecompiledMemberReferences.Add(method.FullName, method);
}
currentMemberToken = CreateCodeMappings(method.MetadataToken.ToInt32(), method);
// write method header
output.WriteDefinition(".method ", method);
DisassembleMethodInternal(method, isTypeDecompiled);
DisassembleMethodInternal(method);
}
void DisassembleMethodInternal(MethodDefinition method, bool isTypeDecompiled)
void DisassembleMethodInternal(MethodDefinition method)
{
// .method public hidebysig specialname
// instance default class [mscorlib]System.IO.TextWriter get_BaseWriter () cil managed
@ -158,8 +155,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -158,8 +155,7 @@ namespace ICSharpCode.Decompiler.Disassembler
if (method.HasBody) {
// create IL code mappings - used in debugger
string name = isTypeDecompiled ? method.DeclaringType.FullName : method.FullName;
MemberMapping methodMapping = method.CreateCodeMapping(this.CodeMappings[name], isTypeDecompiled);
MemberMapping methodMapping = method.CreateCodeMapping(this.CodeMappings[currentMemberToken]);
methodBodyDisassembler.Disassemble(method.Body, methodMapping);
}
@ -203,12 +199,10 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -203,12 +199,10 @@ namespace ICSharpCode.Decompiler.Disassembler
{ FieldAttributes.NotSerialized, "notserialized" },
};
public void DisassembleField(FieldDefinition field, bool isTypeDecompiled = false)
public void DisassembleField(FieldDefinition field)
{
// create mappings for decompiled fields only
if (!isTypeDecompiled) {
this.DecompiledMemberReferences.Add(field.FullName, field);
}
this.DecompiledMemberReferences.Add(field.MetadataToken.ToInt32(), field);
output.WriteDefinition(".field ", field);
WriteEnum(field.Attributes & FieldAttributes.FieldAccessMask, fieldVisibility);
@ -237,14 +231,10 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -237,14 +231,10 @@ namespace ICSharpCode.Decompiler.Disassembler
{ PropertyAttributes.HasDefault, "hasdefault" },
};
public void DisassembleProperty(PropertyDefinition property, bool isTypeDecompiled = false)
public void DisassembleProperty(PropertyDefinition property)
{
// create mappings for decompiled properties only
string name = isTypeDecompiled ? property.DeclaringType.FullName : property.FullName;
if (!isTypeDecompiled) {
this.CodeMappings.Add(name, new List<MemberMapping>());
this.DecompiledMemberReferences.Add(property.FullName, property);
}
currentMemberToken = CreateCodeMappings(property.MetadataToken.ToInt32(), property);
output.WriteDefinition(".property ", property);
WriteFlags(property.Attributes, propertyAttributes);
@ -253,22 +243,22 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -253,22 +243,22 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write(DisassemblerHelpers.Escape(property.Name));
OpenBlock(false);
WriteAttributes(property.CustomAttributes);
WriteNestedMethod(".get", property.GetMethod, isTypeDecompiled);
WriteNestedMethod(".set", property.SetMethod, isTypeDecompiled);
WriteNestedMethod(".get", property.GetMethod);
WriteNestedMethod(".set", property.SetMethod);
foreach (var method in property.OtherMethods) {
WriteNestedMethod(".method", method, isTypeDecompiled);
WriteNestedMethod(".method", method);
}
CloseBlock();
}
void WriteNestedMethod(string keyword, MethodDefinition method, bool isTypeDecompiled)
void WriteNestedMethod(string keyword, MethodDefinition method)
{
if (method == null)
return;
if (detectControlStructure) {
output.WriteDefinition(keyword, method);
output.Write(' ');
DisassembleMethodInternal(method, isTypeDecompiled);
DisassembleMethodInternal(method);
} else {
output.Write(keyword);
output.Write(' ');
@ -284,14 +274,10 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -284,14 +274,10 @@ namespace ICSharpCode.Decompiler.Disassembler
{ EventAttributes.RTSpecialName, "rtspecialname" },
};
public void DisassembleEvent(EventDefinition ev, bool isTypeDecompiled = false)
public void DisassembleEvent(EventDefinition ev)
{
// create mappings for decompiled events only
string name = isTypeDecompiled ? ev.DeclaringType.FullName : ev.FullName;
if (!isTypeDecompiled) {
this.CodeMappings.Add(name, new List<MemberMapping>());
this.DecompiledMemberReferences.Add(ev.FullName, ev);
}
currentMemberToken = CreateCodeMappings(ev.MetadataToken.ToInt32(), ev);
output.WriteDefinition(".event ", ev);
WriteFlags(ev.Attributes, eventAttributes);
@ -300,11 +286,11 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -300,11 +286,11 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write(DisassemblerHelpers.Escape(ev.Name));
OpenBlock(false);
WriteAttributes(ev.CustomAttributes);
WriteNestedMethod(".add", ev.AddMethod, isTypeDecompiled);
WriteNestedMethod(".remove", ev.RemoveMethod, isTypeDecompiled);
WriteNestedMethod(".invoke", ev.InvokeMethod, isTypeDecompiled);
WriteNestedMethod(".add", ev.AddMethod);
WriteNestedMethod(".remove", ev.RemoveMethod);
WriteNestedMethod(".invoke", ev.InvokeMethod);
foreach (var method in ev.OtherMethods) {
WriteNestedMethod(".method", method, isTypeDecompiled);
WriteNestedMethod(".method", method);
}
CloseBlock();
}
@ -346,10 +332,6 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -346,10 +332,6 @@ namespace ICSharpCode.Decompiler.Disassembler
public void DisassembleType(TypeDefinition type)
{
// create IL code mappings - used for debugger
this.CodeMappings.Add(type.FullName, new List<MemberMapping>());
this.DecompiledMemberReferences.Add(type.FullName, type);
// start writing IL
output.WriteDefinition(".class ", type);
@ -413,7 +395,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -413,7 +395,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine("// Fields");
foreach (var field in type.Fields) {
cancellationToken.ThrowIfCancellationRequested();
DisassembleField(field, true);
DisassembleField(field);
}
output.WriteLine();
}
@ -421,7 +403,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -421,7 +403,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine("// Properties");
foreach (var prop in type.Properties) {
cancellationToken.ThrowIfCancellationRequested();
DisassembleProperty(prop, true);
DisassembleProperty(prop);
}
output.WriteLine();
}
@ -429,7 +411,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -429,7 +411,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine("// Events");
foreach (var ev in type.Events) {
cancellationToken.ThrowIfCancellationRequested();
DisassembleEvent(ev, true);
DisassembleEvent(ev);
output.WriteLine();
}
output.WriteLine();
@ -440,7 +422,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -440,7 +422,7 @@ namespace ICSharpCode.Decompiler.Disassembler
foreach (var m in type.Methods) {
cancellationToken.ThrowIfCancellationRequested();
if (!(detectControlStructure && accessorMethods.Contains(m))) {
DisassembleMethod(m, true);
DisassembleMethod(m);
output.WriteLine();
}
}
@ -638,11 +620,18 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -638,11 +620,18 @@ namespace ICSharpCode.Decompiler.Disassembler
/// <summary>
/// <inheritdoc/>
/// </summary>
public Dictionary<string, List<MemberMapping>> CodeMappings { get; private set; }
public Dictionary<int, List<MemberMapping>> CodeMappings { get; private set; }
/// <summary>
/// <inheritdoc/>
/// </summary>
public Dictionary<string, MemberReference> DecompiledMemberReferences { get; private set; }
public Dictionary<int, MemberReference> DecompiledMemberReferences { get; private set; }
private int CreateCodeMappings(int token, MemberReference member)
{
this.CodeMappings.Add(token, new List<MemberMapping>());
this.DecompiledMemberReferences.Add(token, member);
return token;
}
}
}

17
ILSpy/Commands/DebuggerCommands.cs

@ -11,6 +11,7 @@ using System.Windows.Interop; @@ -11,6 +11,7 @@ using System.Windows.Interop;
using System.Windows.Media;
using System.Xml.Linq;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.ILSpy.Debugger;
using ICSharpCode.ILSpy.Debugger.Bookmarks;
using ICSharpCode.ILSpy.Debugger.Services;
@ -157,19 +158,21 @@ namespace ICSharpCode.ILSpy.Commands @@ -157,19 +158,21 @@ namespace ICSharpCode.ILSpy.Commands
return;
}
var inst = MainWindow.Instance;
// breakpoint was hit => bring to front the main window
SendWpfWindowPos(MainWindow.Instance, HWND_TOP);
MainWindow.Instance.Activate();
SendWpfWindowPos(inst, HWND_TOP); inst.Activate();
// jump to type & expand folding
if (CurrentLineBookmark.Instance != null) {
if (!DebugData.DecompiledMemberReferences.ContainsKey(CurrentLineBookmark.Instance.MemberReference.FullName))
MainWindow.Instance.JumpToReference(CurrentLineBookmark.Instance.MemberReference);
var bm = CurrentLineBookmark.Instance;
if (bm != null) {
if (!DebugData.DecompiledMemberReferences.ContainsKey(bm.MemberReference.MetadataToken.ToInt32()))
inst.JumpToReference(bm.MemberReference);
MainWindow.Instance.TextView.UnfoldAndScroll(CurrentLineBookmark.Instance.LineNumber);
inst.TextView.UnfoldAndScroll(bm.LineNumber);
}
MainWindow.Instance.SetStatus("Debugging...", Brushes.Red);
inst.SetStatus("Debugging...", Brushes.Red);
}
}

7
ILSpy/Language.cs

@ -32,12 +32,12 @@ namespace ICSharpCode.ILSpy @@ -32,12 +32,12 @@ namespace ICSharpCode.ILSpy
/// <summary>
/// Decompilation event arguments.
/// </summary>
public sealed class DecompileEventArgs : EventArgs
public sealed class DecompileEventArgs : EventArgs, ICodeMappings
{
/// <summary>
/// Gets ot sets the code mappings
/// </summary>
public Dictionary<string, List<MemberMapping>> CodeMappings { get; set; }
public Dictionary<int, List<MemberMapping>> CodeMappings { get; set; }
/// <summary>
/// Gets or sets the local variables.
@ -47,7 +47,7 @@ namespace ICSharpCode.ILSpy @@ -47,7 +47,7 @@ namespace ICSharpCode.ILSpy
/// <summary>
/// Gets the list of MembeReferences that are decompiled (TypeDefinitions, MethodDefinitions, etc)
/// </summary>
public Dictionary<string, MemberReference> DecompiledMemberReferences { get; set; }
public Dictionary<int, MemberReference> DecompiledMemberReferences { get; set; }
}
/// <summary>
@ -111,6 +111,7 @@ namespace ICSharpCode.ILSpy @@ -111,6 +111,7 @@ namespace ICSharpCode.ILSpy
public virtual void DecompileNamespace(string nameSpace, IEnumerable<TypeDefinition> types, ITextOutput output, DecompilationOptions options)
{
WriteCommentLine(output, nameSpace);
OnDecompilationFinished(null);
}
public virtual void DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options)

16
ILSpy/TextView/DecompilerTextView.cs

@ -394,7 +394,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -394,7 +394,7 @@ namespace ICSharpCode.ILSpy.TextView
// show the currentline marker
var bm = CurrentLineBookmark.Instance;
if (bm != null) {
if (DebugData.DecompiledMemberReferences.ContainsKey(bm.MemberReference.FullName)) {
if (DebugData.DecompiledMemberReferences.ContainsKey(bm.MemberReference.MetadataToken.ToInt32())) {
DocumentLine line = textEditor.Document.GetLineByNumber(bm.LineNumber);
bm.Marker = bm.CreateMarker(textMarkerService, line.Offset, line.Length);
}
@ -456,6 +456,11 @@ namespace ICSharpCode.ILSpy.TextView @@ -456,6 +456,11 @@ namespace ICSharpCode.ILSpy.TextView
static void DecompileNodes(DecompilationContext context, ITextOutput textOutput)
{
// reset data
DebugData.CodeMappings = null;
DebugData.LocalVariables = null;
DebugData.DecompiledMemberReferences = null;
var nodes = context.TreeNodes;
context.Language.DecompileFinished += Language_DecompileFinished;
for (int i = 0; i < nodes.Length; i++) {
@ -471,13 +476,16 @@ namespace ICSharpCode.ILSpy.TextView @@ -471,13 +476,16 @@ namespace ICSharpCode.ILSpy.TextView
static void Language_DecompileFinished(object sender, DecompileEventArgs e)
{
if (e != null) {
if (DebugData.CodeMappings == null) {
DebugData.CodeMappings = e.CodeMappings;
DebugData.LocalVariables = e.LocalVariables;
DebugData.DecompiledMemberReferences = e.DecompiledMemberReferences;
} else {
DebugData.CodeMappings = null;
DebugData.LocalVariables = null;
DebugData.DecompiledMemberReferences = null;
DebugData.CodeMappings.AddRange(e.CodeMappings);
DebugData.DecompiledMemberReferences.AddRange(e.DecompiledMemberReferences);
if (e.LocalVariables != null)
DebugData.LocalVariables.AddRange(e.LocalVariables);
}
}
}
#endregion

Loading…
Cancel
Save