diff --git a/Debugger/ILSpy.Debugger/Bookmarks/BookmarkManager.cs b/Debugger/ILSpy.Debugger/Bookmarks/BookmarkManager.cs index b69ee9ebe..4405a0231 100644 --- a/Debugger/ILSpy.Debugger/Bookmarks/BookmarkManager.cs +++ b/Debugger/ILSpy.Debugger/Bookmarks/BookmarkManager.cs @@ -3,7 +3,9 @@ using System; using System.Collections.Generic; +using ICSharpCode.Decompiler; using ICSharpCode.NRefactory.CSharp; +using Mono.Cecil; using Mono.CSharp; namespace ILSpy.Debugger.Bookmarks @@ -13,6 +15,53 @@ namespace ILSpy.Debugger.Bookmarks /// public static class BookmarkManager { + static BookmarkManager() + { + DebugData.LanguageChanged += OnLanguageChanged; + } + + static void OnLanguageChanged(object sender, LanguageEventArgs e) + { + var oldLanguage = e.OldLanguage; + var newLanguage = e.NewLanguage; + + // synchronize the IL<->C# breakpoints + + // 1. map the breakpoint lines + var oldbps = bookmarks.FindAll(b => b is BreakpointBookmark && ((BreakpointBookmark)b).Language == oldLanguage); + if (oldbps == null || oldbps.Count == 0) + return; + + var oldMappings = CodeMappings.GetStorage(oldLanguage); + var newMappings = CodeMappings.GetStorage(newLanguage); + + if (oldMappings == null || oldMappings.Count == 0 || + newMappings == null || newMappings.Count == 0) + return; + + foreach (var bp in oldbps) { + uint token; + var instruction = oldMappings.GetInstructionByTypeAndLine(DebugData.CurrentType.FullName, bp.LineNumber, out token); + if (instruction == null) + continue; + + TypeDefinition type; + int line; + if (newMappings.GetSourceCodeFromMetadataTokenAndOffset(token, instruction.ILInstructionOffset.From, out type, out line)) { + // 2. create breakpoint for new languages + var bookmark = new BreakpointBookmark(type, new AstLocation(line, 0), 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); + } + } + static List bookmarks = new List(); public static List Bookmarks { diff --git a/Debugger/ILSpy.Debugger/DebuggedType.cs b/Debugger/ILSpy.Debugger/DebuggedType.cs index b649334b3..a2923e432 100644 --- a/Debugger/ILSpy.Debugger/DebuggedType.cs +++ b/Debugger/ILSpy.Debugger/DebuggedType.cs @@ -28,6 +28,8 @@ namespace ILSpy.Debugger /// public static class DebugData { + static DecompiledLanguages language; + /// /// Gets or sets the current debugged type /// @@ -36,11 +38,45 @@ namespace ILSpy.Debugger /// /// Gets or sets the decompiled language. /// - public static DecompiledLanguages Language { get; set; } + public static DecompiledLanguages Language { + get { return language; } + set { + var oldLanguage = language; + if (value != language) { + language = value; + OnLanguageChanged(new LanguageEventArgs(oldLanguage, language)); + } + } + } /// /// List of loaded assemblies. /// public static IEnumerable LoadedAssemblies { get; set; } + + /// + /// Occures when the language is changed. + /// + public static event EventHandler LanguageChanged; + + private static void OnLanguageChanged(LanguageEventArgs e) + { + if (LanguageChanged != null) { + LanguageChanged(null, e); + } + } + } + + public class LanguageEventArgs : EventArgs + { + public DecompiledLanguages OldLanguage { get; private set; } + + public DecompiledLanguages NewLanguage { get; private set; } + + public LanguageEventArgs(DecompiledLanguages oldLanguage, DecompiledLanguages newLanguage) + { + this.OldLanguage = oldLanguage; + this.NewLanguage = newLanguage; + } } } diff --git a/Debugger/ILSpy.Debugger/Services/Debugger/DebuggerService.cs b/Debugger/ILSpy.Debugger/Services/Debugger/DebuggerService.cs index 62a2f88ef..f37645d8e 100644 --- a/Debugger/ILSpy.Debugger/Services/Debugger/DebuggerService.cs +++ b/Debugger/ILSpy.Debugger/Services/Debugger/DebuggerService.cs @@ -205,6 +205,9 @@ namespace ILSpy.Debugger.Services var doc = (TextDocument)e.Editor.Document; var line = doc.GetLineByNumber(logicPos.Line); + if (line.Offset + logicPos.Column >= doc.TextLength) + return; + var c = doc.GetText(line.Offset + logicPos.Column, 1); if (string.IsNullOrEmpty(c) || c == "\n" || c == "\t") return; diff --git a/ICSharpCode.Decompiler/CodeMappings.cs b/ICSharpCode.Decompiler/CodeMappings.cs index efa7d5011..0b8572f79 100644 --- a/ICSharpCode.Decompiler/CodeMappings.cs +++ b/ICSharpCode.Decompiler/CodeMappings.cs @@ -34,11 +34,6 @@ namespace ICSharpCode.Decompiler /// public ILRange ILInstructionOffset { get; set; } - /// - /// Gets or sets the current types at the source code line. E.g.: for int a = dictionary.Count; the list will contain System.Int32 and System.Collections.Generic.Dictionary<TKey, TValue>. - /// - public List InnerTypes { get; set; } - public int[] ToArray() { int[] result = new int[2]; diff --git a/ILSpy/MainWindow.xaml b/ILSpy/MainWindow.xaml index c946b4145..2949d12f2 100644 --- a/ILSpy/MainWindow.xaml +++ b/ILSpy/MainWindow.xaml @@ -70,9 +70,7 @@ + SelectedItem="{Binding FilterSettings.Language}"/> diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs index 7cee60d89..74c174ef1 100644 --- a/ILSpy/MainWindow.xaml.cs +++ b/ILSpy/MainWindow.xaml.cs @@ -49,7 +49,7 @@ namespace ICSharpCode.ILSpy { NavigationHistory history = new NavigationHistory(); ILSpySettings spySettings; - SessionSettings sessionSettings; + internal SessionSettings sessionSettings; AssemblyListManager assemblyListManager; AssemblyList assemblyList; AssemblyListTreeNode assemblyListTreeNode; @@ -548,12 +548,7 @@ namespace ICSharpCode.ILSpy analyzerRow.MinHeight = 0; analyzerRow.Height = new GridLength(0); } - - void LanguageComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) - { - DebugData.Language = sessionSettings.FilterSettings.Language.Name.StartsWith("IL") ? DecompiledLanguages.IL : DecompiledLanguages.CSharp; - } - + public void UnselectAll() { treeView.UnselectAll(); diff --git a/ILSpy/TextView/DecompilerTextView.cs b/ILSpy/TextView/DecompilerTextView.cs index e1bdad57c..584c77cdb 100644 --- a/ILSpy/TextView/DecompilerTextView.cs +++ b/ILSpy/TextView/DecompilerTextView.cs @@ -401,6 +401,10 @@ namespace ICSharpCode.ILSpy.TextView ShowOutput(output); } finally { + + // set the language + DebugData.Language = MainWindow.Instance.sessionSettings.FilterSettings.Language.Name.StartsWith("IL") ? DecompiledLanguages.IL : DecompiledLanguages.CSharp; + if (DebugData.CurrentType != null && context.TreeNodes.Count() == 1) { iconMargin.Visibility = Visibility.Visible; // repaint bookmarks