Browse Source

debug methods - part 1.

pull/191/merge
Eusebiu Marcu 14 years ago
parent
commit
802702908a
  1. 6
      Debugger/ILSpy.Debugger/AvalonEdit/TextMarkerService.cs
  2. 9
      Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs
  3. 43
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  4. 38
      ICSharpCode.Decompiler/CodeMappings.cs
  5. 37
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  6. 4
      ILSpy/Commands/DebuggerCommands.cs
  7. 3
      ILSpy/ExtensionMethods.cs
  8. 2
      ILSpy/Language.cs
  9. 55
      ILSpy/TextView/DecompilerTextView.cs

6
Debugger/ILSpy.Debugger/AvalonEdit/TextMarkerService.cs

@ -54,8 +54,10 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit @@ -54,8 +54,10 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit
if (e.Bookmark is MarkerBookmark) {
var bm = (MarkerBookmark)e.Bookmark;
// add bookmark for the current type
DocumentLine line = codeEditor.Document.GetLineByNumber(bm.LineNumber);
bm.CreateMarker(this, line.Offset, line.Length);
if (bm.LineNumber < codeEditor.Document.LineCount) {
DocumentLine line = codeEditor.Document.GetLineByNumber(bm.LineNumber);
bm.CreateMarker(this, line.Offset, line.Length);
}
}
}

9
Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs

@ -822,7 +822,6 @@ namespace ICSharpCode.ILSpy.Debugger.Services @@ -822,7 +822,6 @@ namespace ICSharpCode.ILSpy.Debugger.Services
DecompileOnDemand(frame);
}
}
}
void DecompileOnDemand(StackFrame frame)
@ -878,12 +877,10 @@ namespace ICSharpCode.ILSpy.Debugger.Services @@ -878,12 +877,10 @@ namespace ICSharpCode.ILSpy.Debugger.Services
AstBuilder builder = new AstBuilder(new DecompilerContext(typeDef.Module));
builder.AddType(type);
builder.GenerateCode(new PlainTextOutput());
memberReference = builder.DecompiledMemberReferences[token];
memberReference = builder.CodeMappings[token][0].MemberReference;
// decompile member
var context = new DecompilerContext(typeDef.Module);
context.CurrentType = type;
builder = new AstBuilder(context);
builder = new AstBuilder(new DecompilerContext(typeDef.Module) { CurrentType = type });
if (memberReference is PropertyDefinition)
builder.AddProperty(memberReference as PropertyDefinition);
else if (memberReference is MethodDefinition)
@ -902,7 +899,7 @@ namespace ICSharpCode.ILSpy.Debugger.Services @@ -902,7 +899,7 @@ namespace ICSharpCode.ILSpy.Debugger.Services
codeMappings = codeMappings ?? DebugData.CodeMappings;
if (codeMappings[token].GetSourceCodeFromMetadataTokenAndOffset(token, ilOffset, out memberReference, out line)) {
DebuggerService.RemoveCurrentLineMarker();
DebuggerService.JumpToCurrentLine(members[token], line, 0, line, 0);
DebuggerService.JumpToCurrentLine(memberReference, line, 0, line, 0);
} else {
StepOut();
}

43
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -31,7 +31,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -31,7 +31,7 @@ namespace ICSharpCode.Decompiler.Ast
IncludeTypeParameterDefinitions = 2
}
public class AstBuilder : ICodeMappings
public class AstBuilder : BaseCodeMappings
{
DecompilerContext context;
CompilationUnit astCompileUnit = new CompilationUnit();
@ -623,8 +623,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -623,8 +623,8 @@ namespace ICSharpCode.Decompiler.Ast
AttributedNode CreateMethod(MethodDefinition methodDef)
{
// Create mapping - used in debugger
int currentMemberToken = CreateCodeMappings(methodDef.MetadataToken.ToInt32(), methodDef);
MemberMapping methodMapping = methodDef.CreateCodeMapping(this.CodeMappings[currentMemberToken]);
CreateCodeMappings(methodDef.MetadataToken.ToInt32(), methodDef);
MemberMapping methodMapping = methodDef.CreateCodeMapping(this.CodeMappings[methodDef.MetadataToken.ToInt32()]);
MethodDeclaration astMethod = new MethodDeclaration();
astMethod.AddAnnotation(methodDef);
@ -719,8 +719,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -719,8 +719,8 @@ namespace ICSharpCode.Decompiler.Ast
ConstructorDeclaration CreateConstructor(MethodDefinition methodDef)
{
// Create mapping - used in debugger
int currentMemberToken = CreateCodeMappings(methodDef.MetadataToken.ToInt32(), methodDef);
MemberMapping methodMapping = methodDef.CreateCodeMapping(this.CodeMappings[currentMemberToken]);
CreateCodeMappings(methodDef.MetadataToken.ToInt32(), methodDef);
MemberMapping methodMapping = methodDef.CreateCodeMapping(this.CodeMappings[methodDef.MetadataToken.ToInt32()]);
ConstructorDeclaration astMethod = new ConstructorDeclaration();
astMethod.AddAnnotation(methodDef);
@ -788,8 +788,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -788,8 +788,8 @@ namespace ICSharpCode.Decompiler.Ast
if (propDef.GetMethod != null) {
// Create mapping - used in debugger
int currentMemberToken = CreateCodeMappings(propDef.GetMethod.MetadataToken.ToInt32(), propDef);
MemberMapping methodMapping = propDef.GetMethod.CreateCodeMapping(this.CodeMappings[currentMemberToken]);
CreateCodeMappings(propDef.GetMethod.MetadataToken.ToInt32(), propDef);
MemberMapping methodMapping = propDef.GetMethod.CreateCodeMapping(this.CodeMappings[propDef.GetMethod.MetadataToken.ToInt32()], propDef);
astProp.Getter = new Accessor();
astProp.Getter.Body = CreateMethodBody(propDef.GetMethod);
@ -803,8 +803,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -803,8 +803,8 @@ namespace ICSharpCode.Decompiler.Ast
}
if (propDef.SetMethod != null) {
// Create mapping - used in debugger
int currentMemberToken = CreateCodeMappings(propDef.SetMethod.MetadataToken.ToInt32(), propDef);
MemberMapping methodMapping = propDef.SetMethod.CreateCodeMapping(this.CodeMappings[currentMemberToken]);
CreateCodeMappings(propDef.SetMethod.MetadataToken.ToInt32(), propDef);
MemberMapping methodMapping = propDef.SetMethod.CreateCodeMapping(this.CodeMappings[propDef.SetMethod.MetadataToken.ToInt32()], propDef);
astProp.Setter = new Accessor();
astProp.Setter.Body = CreateMethodBody(propDef.SetMethod);
@ -865,8 +865,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -865,8 +865,8 @@ namespace ICSharpCode.Decompiler.Ast
if (eventDef.AddMethod != null) {
// Create mapping - used in debugger
int currentMemberToken = CreateCodeMappings(eventDef.AddMethod.MetadataToken.ToInt32(), eventDef);
MemberMapping methodMapping = eventDef.AddMethod.CreateCodeMapping(this.CodeMappings[currentMemberToken]);
CreateCodeMappings(eventDef.AddMethod.MetadataToken.ToInt32(), eventDef);
MemberMapping methodMapping = eventDef.AddMethod.CreateCodeMapping(this.CodeMappings[eventDef.AddMethod.MetadataToken.ToInt32()], eventDef);
astEvent.AddAccessor = new Accessor {
Body = CreateMethodBody(eventDef.AddMethod)
@ -877,8 +877,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -877,8 +877,8 @@ namespace ICSharpCode.Decompiler.Ast
}
if (eventDef.RemoveMethod != null) {
// Create mapping - used in debugger
int currentMemberToken = CreateCodeMappings(eventDef.RemoveMethod.MetadataToken.ToInt32(), eventDef);
MemberMapping methodMapping = eventDef.RemoveMethod.CreateCodeMapping(this.CodeMappings[currentMemberToken]);
CreateCodeMappings(eventDef.RemoveMethod.MetadataToken.ToInt32(), eventDef);
MemberMapping methodMapping = eventDef.RemoveMethod.CreateCodeMapping(this.CodeMappings[eventDef.RemoveMethod.MetadataToken.ToInt32()], eventDef);
astEvent.RemoveAccessor = new Accessor {
Body = CreateMethodBody(eventDef.RemoveMethod)
@ -1376,27 +1376,10 @@ namespace ICSharpCode.Decompiler.Ast @@ -1376,27 +1376,10 @@ namespace ICSharpCode.Decompiler.Ast
return type.CustomAttributes.Any(attr => attr.AttributeType.FullName == "System.FlagsAttribute");
}
/// <summary>
/// <inheritdoc/>
/// </summary>
public Dictionary<int, List<MemberMapping>> CodeMappings { get; private set; }
/// <summary>
/// Gets the local variables for the current decompiled type, method, etc.
/// <remarks>The key is the metadata token.</remarks>
/// </summary>
public ConcurrentDictionary<int, IEnumerable<ILVariable>> LocalVariables { get; private set; }
/// <summary>
/// <inheritdoc/>
/// </summary>
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;
}
}
}

38
ICSharpCode.Decompiler/CodeMappings.cs

@ -35,21 +35,36 @@ namespace ICSharpCode.Decompiler @@ -35,21 +35,36 @@ namespace ICSharpCode.Decompiler
}
/// <summary>
/// Interface for decompliler classes : AstBuilder & ReflectionDisassembler.
/// Base class for decompliler classes : AstBuilder & ReflectionDisassembler.
/// </summary>
public interface ICodeMappings
public abstract class BaseCodeMappings
{
/// <summary>
/// Gets the code mappings.
/// <remarks>Key is the metadata token.</remarks>
/// </summary>
Dictionary<int, List<MemberMapping>> CodeMappings { get; }
public Dictionary<int, List<MemberMapping>> CodeMappings { get; protected set; }
/// <summary>
/// Gets the MembeReference that is decompiled (a TypeDefinition, MethodDefinition, etc)
/// Gets the MembeReference that is decompiled (a MethodDefinition, PropertyDefinition etc.)
/// <remarks>Key is the metadata token.</remarks>
/// </summary>
Dictionary<int, MemberReference> DecompiledMemberReferences { get; }
public Dictionary<int, MemberReference> DecompiledMemberReferences { get; protected set; }
/// <summary>
/// Create data in the CodeMappings and DecompiledMemberReferences.
/// </summary>
/// <param name="token">Token of the current method.</param>
/// <param name="member">Current member (MethodDefinition, PropertyDefinition, EventDefinition).</param>
/// <remarks>The token is used in CodeMappings; member (and its token) is used in DecompiledMemberReferences.</remarks>
protected virtual void CreateCodeMappings(int token, MemberReference member)
{
this.CodeMappings.Add(token, new List<MemberMapping>());
int t = member.MetadataToken.ToInt32();
if (!this.DecompiledMemberReferences.ContainsKey(t))
this.DecompiledMemberReferences.Add(t, member);
}
}
/// <summary>
@ -90,9 +105,9 @@ namespace ICSharpCode.Decompiler @@ -90,9 +105,9 @@ namespace ICSharpCode.Decompiler
currentList.AddRange(MemberMapping.InvertedList);
} else {
// if the current list contains the last mapping, add also the last gap
var lastInverted = MemberMapping.InvertedList.LastOrDefault();
if (lastInverted != null && lastInverted.From == currentList[currentList.Count - 1].To)
currentList.Add(lastInverted);
// var lastInverted = MemberMapping.InvertedList.LastOrDefault();
// if (lastInverted != null && lastInverted.From == currentList[currentList.Count - 1].To)
// currentList.Add(lastInverted);
}
// set the output
@ -161,10 +176,11 @@ namespace ICSharpCode.Decompiler @@ -161,10 +176,11 @@ namespace ICSharpCode.Decompiler
/// </summary>
/// <param name="method">Method to create the mapping for.</param>
/// <param name="codeMappings">Source code mapping storage.</param>
/// <param name="isTypeDecompiled">True, if a full type was decompiled; false otherwise.</param>
/// <param name="actualMemberReference">The actual member reference.</param>
internal static MemberMapping CreateCodeMapping(
this MethodDefinition member,
List<MemberMapping> codeMappings)
List<MemberMapping> codeMappings,
MemberReference actualMemberReference = null)
{
if (member == null || !member.HasBody)
return null;
@ -179,7 +195,7 @@ namespace ICSharpCode.Decompiler @@ -179,7 +195,7 @@ namespace ICSharpCode.Decompiler
currentMemberMapping = new MemberMapping() {
MetadataToken = member.MetadataToken.ToInt32(),
MemberCodeMappings = new List<SourceCodeMapping>(),
MemberReference = member,
MemberReference = actualMemberReference ?? member,
CodeSize = member.Body.CodeSize
};

37
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -28,14 +28,14 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -28,14 +28,14 @@ namespace ICSharpCode.Decompiler.Disassembler
/// <summary>
/// Disassembles type and member definitions.
/// </summary>
public sealed class ReflectionDisassembler : ICodeMappings
public sealed class ReflectionDisassembler : BaseCodeMappings
{
ITextOutput output;
CancellationToken cancellationToken;
bool detectControlStructure;
bool isInType; // whether we are currently disassembling a whole type (-> defaultCollapsed for foldings)
MethodBodyDisassembler methodBodyDisassembler;
int currentMemberToken;
MemberReference currentMember;
public ReflectionDisassembler(ITextOutput output, bool detectControlStructure, CancellationToken cancellationToken)
{
@ -98,8 +98,8 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -98,8 +98,8 @@ namespace ICSharpCode.Decompiler.Disassembler
public void DisassembleMethod(MethodDefinition method)
{
// create mappings for decompiled methods only
currentMemberToken = CreateCodeMappings(method.MetadataToken.ToInt32(), method);
// set current member
currentMember = method;
// write method header
output.WriteDefinition(".method ", method);
@ -155,7 +155,8 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -155,7 +155,8 @@ namespace ICSharpCode.Decompiler.Disassembler
if (method.HasBody) {
// create IL code mappings - used in debugger
MemberMapping methodMapping = method.CreateCodeMapping(this.CodeMappings[currentMemberToken]);
CreateCodeMappings(method.MetadataToken.ToInt32(), currentMember);
MemberMapping methodMapping = method.CreateCodeMapping(this.CodeMappings[method.MetadataToken.ToInt32()], currentMember);
methodBodyDisassembler.Disassemble(method.Body, methodMapping);
}
@ -233,8 +234,8 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -233,8 +234,8 @@ namespace ICSharpCode.Decompiler.Disassembler
public void DisassembleProperty(PropertyDefinition property)
{
// create mappings for decompiled properties only
currentMemberToken = CreateCodeMappings(property.MetadataToken.ToInt32(), property);
// set current member
currentMember = property;
output.WriteDefinition(".property ", property);
WriteFlags(property.Attributes, propertyAttributes);
@ -245,6 +246,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -245,6 +246,7 @@ namespace ICSharpCode.Decompiler.Disassembler
WriteAttributes(property.CustomAttributes);
WriteNestedMethod(".get", property.GetMethod);
WriteNestedMethod(".set", property.SetMethod);
foreach (var method in property.OtherMethods) {
WriteNestedMethod(".method", method);
}
@ -276,8 +278,8 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -276,8 +278,8 @@ namespace ICSharpCode.Decompiler.Disassembler
public void DisassembleEvent(EventDefinition ev)
{
// create mappings for decompiled events only
currentMemberToken = CreateCodeMappings(ev.MetadataToken.ToInt32(), ev);
// set current member
currentMember = ev;
output.WriteDefinition(".event ", ev);
WriteFlags(ev.Attributes, eventAttributes);
@ -616,22 +618,5 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -616,22 +618,5 @@ namespace ICSharpCode.Decompiler.Disassembler
WriteAttributes(asm.CustomAttributes);
CloseBlock();
}
/// <summary>
/// <inheritdoc/>
/// </summary>
public Dictionary<int, List<MemberMapping>> CodeMappings { get; private set; }
/// <summary>
/// <inheritdoc/>
/// </summary>
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;
}
}
}

4
ILSpy/Commands/DebuggerCommands.cs

@ -166,9 +166,7 @@ namespace ICSharpCode.ILSpy.Commands @@ -166,9 +166,7 @@ namespace ICSharpCode.ILSpy.Commands
// jump to type & expand folding
var bm = CurrentLineBookmark.Instance;
if (bm != null) {
if (!DebugData.DecompiledMemberReferences.ContainsKey(bm.MemberReference.MetadataToken.ToInt32()))
inst.JumpToReference(bm.MemberReference);
inst.JumpToReference(bm.MemberReference);
inst.TextView.UnfoldAndScroll(bm.LineNumber);
}

3
ILSpy/ExtensionMethods.cs

@ -32,7 +32,8 @@ namespace ICSharpCode.ILSpy @@ -32,7 +32,8 @@ namespace ICSharpCode.ILSpy
public static void AddRange<T>(this ICollection<T> list, IEnumerable<T> items)
{
foreach (T item in items)
list.Add(item);
if (!list.Contains(item))
list.Add(item);
}
/// <summary>

2
ILSpy/Language.cs

@ -32,7 +32,7 @@ namespace ICSharpCode.ILSpy @@ -32,7 +32,7 @@ namespace ICSharpCode.ILSpy
/// <summary>
/// Decompilation event arguments.
/// </summary>
public sealed class DecompileEventArgs : EventArgs, ICodeMappings
public sealed class DecompileEventArgs : EventArgs
{
/// <summary>
/// Gets ot sets the code mappings

55
ILSpy/TextView/DecompilerTextView.cs

@ -380,35 +380,40 @@ namespace ICSharpCode.ILSpy.TextView @@ -380,35 +380,40 @@ namespace ICSharpCode.ILSpy.TextView
isDecompilationOk = false;
}
finally {
// sync bookmarks
iconMargin.SyncBookmarks();
// set the language
DebugData.Language = MainWindow.Instance.sessionSettings.FilterSettings.Language.Name.StartsWith("IL") ? DecompiledLanguages.IL : DecompiledLanguages.CSharp;
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) {
if (DebugData.DecompiledMemberReferences.ContainsKey(bm.MemberReference.MetadataToken.ToInt32())) {
DocumentLine line = textEditor.Document.GetLineByNumber(bm.LineNumber);
bm.Marker = bm.CreateMarker(textMarkerService, line.Offset, line.Length);
}
UnfoldAndScroll(bm.LineNumber);
}
}
} else {
// remove currentline marker
CurrentLineBookmark.Remove();
}
this.Test(isDecompilationOk);
}
});
}
void Test(bool isDecompilationOk)
{
// sync bookmarks
iconMargin.SyncBookmarks();
// set the language
DebugData.Language = MainWindow.Instance.sessionSettings.FilterSettings.Language.Name.StartsWith("IL") ? DecompiledLanguages.IL : DecompiledLanguages.CSharp;
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) {
if (DebugData.DecompiledMemberReferences.ContainsKey(bm.MemberReference.MetadataToken.ToInt32())) {
DocumentLine line = textEditor.Document.GetLineByNumber(bm.LineNumber);
bm.Marker = bm.CreateMarker(textMarkerService, line.Offset + 1, line.Length);
}
UnfoldAndScroll(bm.LineNumber);
}
}
} else {
// remove currentline marker
CurrentLineBookmark.Remove();
}
}
static Task<AvalonEditTextOutput> DecompileAsync(DecompilationContext context, int outputLengthLimit)
{
Debug.WriteLine("Start decompilation of {0} tree nodes", context.TreeNodes.Length);

Loading…
Cancel
Save