Browse Source

fix step in/out.

pull/191/merge
Eusebiu Marcu 15 years ago
parent
commit
ee3f9e9b7a
  1. 38
      Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs
  2. 59
      Debugger/ILSpy.Debugger/Bookmarks/BookmarkManager.cs
  3. 9
      Debugger/ILSpy.Debugger/DebuggedData.cs
  4. 65
      Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs
  5. 39
      Debugger/ILSpy.Debugger/Services/ExtensionMethods.cs
  6. 7
      ILSpy/Commands/DebuggerCommands.cs
  7. 44
      ILSpy/TextView/DecompilerTextView.cs

38
Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs

@ -290,6 +290,44 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit @@ -290,6 +290,44 @@ namespace ICSharpCode.ILSpy.Debugger.AvalonEdit
}
newBookmarks.ForEach(m => BookmarkManager.AddMark(m));
SyncCurrentLineBookmark();
}
void SyncCurrentLineBookmark()
{
// checks
if (CurrentLineBookmark.Instance == null)
return;
var oldMappings = DebugData.OldCodeMappings;
var newMappings = DebugData.CodeMappings;
if (oldMappings == null || newMappings == null)
return;
// 1. Save it's data
int line = CurrentLineBookmark.Instance.LineNumber;
var markerType = CurrentLineBookmark.Instance.MemberReference;
if (!oldMappings.ContainsKey(markerType.MetadataToken.ToInt32()) || !newMappings.ContainsKey(markerType.MetadataToken.ToInt32()))
return;
// 2. Remove it
CurrentLineBookmark.Remove();
// 3. map the marker line
int token;
var instruction = oldMappings[markerType.MetadataToken.ToInt32()].GetInstructionByLineNumber(line, out token);
if (instruction == null)
return;
MemberReference memberReference;
int newline;
if (newMappings[markerType.MetadataToken.ToInt32()].GetInstructionByTokenAndOffset(token, instruction.ILInstructionOffset.From, out memberReference, out newline)) {
// 4. create breakpoint for new languages
CurrentLineBookmark.SetPosition(memberReference, newline, 0, newline, 0);
}
}
}
}

59
Debugger/ILSpy.Debugger/Bookmarks/BookmarkManager.cs

@ -113,63 +113,4 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks @@ -113,63 +113,4 @@ namespace ICSharpCode.ILSpy.Debugger.Bookmarks
public static event BookmarkEventHandler Removed;
public static event BookmarkEventHandler Added;
}
// This is for the synchronize bookmarks logic
public static partial class BookmarkManager
{
static BookmarkManager()
{
DebugData.LanguageChanged += OnLanguageChanged;
}
static void OnLanguageChanged(object sender, LanguageEventArgs e)
{
var oldLanguage = e.OldLanguage;
var newLanguage = e.NewLanguage;
SyncCurrentLineBookmark(oldLanguage, newLanguage);
//SyncBreakpointBookmarks(oldLanguage, newLanguage);
}
/// <summary>
/// Synchronize the IL<->C# current line marker.
/// </summary>
/// <param name="oldLanguage">Old language.</param>
/// <param name="newLanguage">New language.</param>
static void SyncCurrentLineBookmark(DecompiledLanguages oldLanguage, DecompiledLanguages newLanguage)
{
// checks
if (CurrentLineBookmark.Instance == null)
return;
var oldMappings = DebugData.OldCodeMappings;
var newMappings = DebugData.CodeMappings;
if (oldMappings == null || newMappings == null)
return;
// 1. Save it's data
int line = CurrentLineBookmark.Instance.LineNumber;
var markerType = CurrentLineBookmark.Instance.MemberReference;
if (!oldMappings.ContainsKey(markerType.MetadataToken.ToInt32()) || !newMappings.ContainsKey(markerType.MetadataToken.ToInt32()))
return;
// 2. Remove it
CurrentLineBookmark.Remove();
// 3. map the marker line
int token;
var instruction = oldMappings[markerType.MetadataToken.ToInt32()].GetInstructionByLineNumber(line, out token);
if (instruction == null)
return;
MemberReference memberReference;
int newline;
if (newMappings[markerType.MetadataToken.ToInt32()].GetInstructionByTokenAndOffset(token, instruction.ILInstructionOffset.From, out memberReference, out newline)) {
// 4. create breakpoint for new languages
CurrentLineBookmark.SetPosition(memberReference, newline, 0, newline, 0);
}
}
}
}

9
Debugger/ILSpy.Debugger/DebuggedData.cs

@ -63,15 +63,20 @@ namespace ICSharpCode.ILSpy.Debugger @@ -63,15 +63,20 @@ namespace ICSharpCode.ILSpy.Debugger
public static ConcurrentDictionary<int, IEnumerable<ILVariable>> LocalVariables { get; set; }
/// <summary>
/// Gets or sets the old code mappings.
/// (internal) Gets or sets the old code mappings.
/// </summary>
public static Dictionary<int, List<MemberMapping>> OldCodeMappings { get; set; }
/// <summary>
/// Gets or sets the MembeReference that was decompiled (a TypeDefinition, MethodDefinition, etc)
/// (internal) Gets or sets the MembeReference that was decompiled (a TypeDefinition, MethodDefinition, etc)
/// </summary>
public static Dictionary<int, MemberReference> DecompiledMemberReferences { get; set; }
/// <summary>
/// Gets or (internal) sets the current token, IL offset and member reference. Used for step in/out.
/// </summary>
public static Tuple<int, int, MemberReference> DebugStepInformation { get; set; }
/// <summary>
/// Occures when the language is changed.
/// </summary>

65
Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs

@ -1,13 +1,10 @@ @@ -1,13 +1,10 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Media;
@ -15,15 +12,13 @@ using Debugger; @@ -15,15 +12,13 @@ using Debugger;
using Debugger.Interop.CorPublish;
using Debugger.MetaData;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.Visitors;
using ICSharpCode.ILSpy.Debugger.Bookmarks;
using ICSharpCode.ILSpy.Debugger.Models.TreeModel;
using ICSharpCode.ILSpy.Debugger.Services.Debugger;
using ICSharpCode.ILSpy.Debugger.Tooltips;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.Visitors;
using Mono.Cecil;
using CorDbg = Debugger;
using Process = Debugger.Process;
@ -808,19 +803,19 @@ namespace ICSharpCode.ILSpy.Debugger.Services @@ -808,19 +803,19 @@ namespace ICSharpCode.ILSpy.Debugger.Services
int line;
MemberReference memberReference;
if (DebugData.CodeMappings.ContainsKey(token) &&
if (DebugData.CodeMappings.ContainsKey(token) &&
DebugData.CodeMappings[token].GetInstructionByTokenAndOffset(token, ilOffset, out memberReference, out line)) {
DebugData.DebugStepInformation = null; // we do not need to step into/out
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);
StepIntoFrame(frame);
}
}
}
void DecompileOnDemand(StackFrame frame)
void StepIntoFrame(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;
@ -858,53 +853,13 @@ namespace ICSharpCode.ILSpy.Debugger.Services @@ -858,53 +853,13 @@ namespace ICSharpCode.ILSpy.Debugger.Services
if (typeDef != null) {
TypeDefinition type = nestedTypeDef ?? typeDef;
MemberReference memberReference = null;
// 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(type);
codeMappings = dis.CodeMappings;
} else {
// decompile type
AstBuilder builder = new AstBuilder(new DecompilerContext(typeDef.Module));
builder.AddType(type);
builder.GenerateCode(new PlainTextOutput());
memberReference = builder.CodeMappings[token][0].MemberReference;
// decompile member
builder = new AstBuilder(new DecompilerContext(typeDef.Module) { CurrentType = type });
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);
var output = new PlainTextOutput();
builder.GenerateCode(output);
DebugData.CodeMappings = codeMappings = builder.CodeMappings;
DebugData.DecompiledMemberReferences = members = builder.DecompiledMemberReferences;
}
}
// try jump
int line;
codeMappings = codeMappings ?? DebugData.CodeMappings;
if (codeMappings[token].GetInstructionByTokenAndOffset(token, ilOffset, out memberReference, out line)) {
DebuggerService.RemoveCurrentLineMarker();
DebuggerService.JumpToCurrentLine(memberReference, line, 0, line, 0);
} else {
StepOut();
}
DebugData.DebugStepInformation = Tuple.Create(token, ilOffset, type.GetMemberByToken(token));
} else {
Debug.Assert(typeDef != null, "No type was found!");
}
}
}
public void ShowAttachDialog()
{
throw new NotImplementedException();

39
Debugger/ILSpy.Debugger/Services/ExtensionMethods.cs

@ -400,5 +400,44 @@ namespace ICSharpCode.ILSpy.Debugger.Services @@ -400,5 +400,44 @@ namespace ICSharpCode.ILSpy.Debugger.Services
{
scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset + offset);
}
/// <summary>
/// Gets the member by token.
/// </summary>
/// <param name="type">Type.</param>
/// <param name="memberToken">Member metadata token.</param>
/// <returns></returns>
public static MemberReference GetMemberByToken(this TypeDefinition type, int memberToken)
{
if (type.HasMethods) {
foreach (var member in type.Methods) {
if (member.MetadataToken.ToInt32() == memberToken)
return member;
}
}
if (type.HasProperties) {
foreach (var member in type.Properties) {
if (member.MetadataToken.ToInt32() == memberToken)
return member;
}
}
if (type.HasEvents) {
foreach (var member in type.Events) {
if (member.MetadataToken.ToInt32() == memberToken)
return member;
}
}
if (type.HasFields) {
foreach (var member in type.Fields) {
if (member.MetadataToken.ToInt32() == memberToken)
return member;
}
}
return null;
}
}
}

7
ILSpy/Commands/DebuggerCommands.cs

@ -164,11 +164,8 @@ namespace ICSharpCode.ILSpy.Commands @@ -164,11 +164,8 @@ namespace ICSharpCode.ILSpy.Commands
SendWpfWindowPos(inst, HWND_TOP); inst.Activate();
// jump to type & expand folding
var bm = CurrentLineBookmark.Instance;
if (bm != null) {
inst.JumpToReference(bm.MemberReference);
inst.TextView.UnfoldAndScroll(bm.LineNumber);
}
if (DebugData.DebugStepInformation != null)
inst.JumpToReference(DebugData.DebugStepInformation.Item3);
inst.SetStatus("Debugging...", Brushes.Red);
}

44
ILSpy/TextView/DecompilerTextView.cs

@ -20,11 +20,8 @@ using System; @@ -20,11 +20,8 @@ using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
@ -44,12 +41,11 @@ using ICSharpCode.Decompiler; @@ -44,12 +41,11 @@ using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy.Debugger;
using ICSharpCode.ILSpy.Debugger.AvalonEdit;
using ICSharpCode.ILSpy.Debugger.Bookmarks;
using ICSharpCode.ILSpy.Debugger.Services;
using ICSharpCode.ILSpy.Debugger.Tooltips;
using ICSharpCode.ILSpy.Options;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.XmlDoc;
using ICSharpCode.NRefactory.Documentation;
using ICSharpCode.NRefactory.TypeSystem;
using Microsoft.Win32;
using Mono.Cecil;
using TextEditorWeakEventManager = ICSharpCode.ILSpy.Debugger.AvalonEdit.TextEditorWeakEventManager;
@ -348,8 +344,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -348,8 +344,7 @@ namespace ICSharpCode.ILSpy.TextView
void DoDecompile(DecompilationContext context, int outputLengthLimit)
{
// reset type
DebugData.OldCodeMappings = DebugData.CodeMappings;
// close popup
TextEditorListener.Instance.ClosePopup();
bool isDecompilationOk = true;
@ -378,35 +373,37 @@ namespace ICSharpCode.ILSpy.TextView @@ -378,35 +373,37 @@ namespace ICSharpCode.ILSpy.TextView
}
ShowOutput(output);
isDecompilationOk = false;
}
finally {
this.Test(isDecompilationOk);
} finally {
this.UpdateDebugUI(isDecompilationOk);
}
});
}
void Test(bool isDecompilationOk)
void UpdateDebugUI(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) {
if (DebugData.DebugStepInformation != null) {
// repaint bookmarks
iconMargin.InvalidateVisual();
// show the currentline marker
int token = DebugData.DebugStepInformation.Item1;
int ilOffset = DebugData.DebugStepInformation.Item2;
bool isMatch;
var map = DebugData.CodeMappings[token].GetInstructionByTokenAndOffset(token, ilOffset, out isMatch);
int line = map.SourceCodeLine;
DebuggerService.RemoveCurrentLineMarker();
DebuggerService.JumpToCurrentLine(DebugData.DebugStepInformation.Item3, line, 0, line, 0);
// create 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);
}
DocumentLine docline = textEditor.Document.GetLineByNumber(line);
bm.Marker = bm.CreateMarker(textMarkerService, docline.Offset + 1, docline.Length);
UnfoldAndScroll(line);
}
} else {
// remove currentline marker
@ -462,9 +459,12 @@ namespace ICSharpCode.ILSpy.TextView @@ -462,9 +459,12 @@ namespace ICSharpCode.ILSpy.TextView
static void DecompileNodes(DecompilationContext context, ITextOutput textOutput)
{
// reset data
DebugData.OldCodeMappings = DebugData.CodeMappings;
DebugData.CodeMappings = null;
DebugData.LocalVariables = null;
DebugData.DecompiledMemberReferences = null;
// set the language
DebugData.Language = MainWindow.Instance.sessionSettings.FilterSettings.Language.Name.StartsWith("IL") ? DecompiledLanguages.IL : DecompiledLanguages.CSharp;
var nodes = context.TreeNodes;
context.Language.DecompileFinished += Language_DecompileFinished;

Loading…
Cancel
Save