.NET Decompiler with support for PDB generation, ReadyToRun, Metadata (&more) - cross-platform!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

163 lines
4.4 KiB

// 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.Generic;
using ICSharpCode.Decompiler;
using ICSharpCode.NRefactory.CSharp;
using Mono.Cecil;
using Mono.CSharp;
namespace ILSpy.Debugger.Bookmarks
{
/// <summary>
/// Static class that maintains the list of bookmarks and breakpoints.
/// </summary>
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<BookmarkBase> bookmarks = new List<BookmarkBase>();
public static List<BookmarkBase> Bookmarks {
get {
return bookmarks;
}
}
public static List<BookmarkBase> GetBookmarks(string typeName)
{
if (typeName == null)
throw new ArgumentNullException("typeName");
List<BookmarkBase> marks = new List<BookmarkBase>();
foreach (BookmarkBase mark in bookmarks) {
if (typeName == mark.Type.FullName) {
marks.Add(mark);
}
}
return marks;
}
public static void AddMark(BookmarkBase bookmark)
{
if (bookmark == null) return;
if (bookmarks.Contains(bookmark)) return;
if (bookmarks.Exists(b => IsEqualBookmark(b, bookmark))) return;
bookmarks.Add(bookmark);
OnAdded(new BookmarkEventArgs(bookmark));
}
static bool IsEqualBookmark(BookmarkBase a, BookmarkBase b)
{
if (a == b)
return true;
if (a == null || b == null)
return false;
if (a.GetType() != b.GetType())
return false;
if (a.Type.FullName != b.Type.FullName)
return false;
return a.LineNumber == b.LineNumber;
}
public static void RemoveMark(BookmarkBase bookmark)
{
bookmarks.Remove(bookmark);
OnRemoved(new BookmarkEventArgs(bookmark));
}
public static void Clear()
{
while (bookmarks.Count > 0) {
var b = bookmarks[bookmarks.Count - 1];
bookmarks.RemoveAt(bookmarks.Count - 1);
OnRemoved(new BookmarkEventArgs(b));
}
}
internal static void Initialize()
{
}
static void OnRemoved(BookmarkEventArgs e)
{
if (Removed != null) {
Removed(null, e);
}
}
static void OnAdded(BookmarkEventArgs e)
{
if (Added != null) {
Added(null, e);
}
}
public static void ToggleBookmark(string typeName, int line,
Predicate<BookmarkBase> canToggle,
Func<AstLocation, BookmarkBase> bookmarkFactory)
{
foreach (BookmarkBase bookmark in GetBookmarks(typeName)) {
if (canToggle(bookmark) && bookmark.LineNumber == line) {
BookmarkManager.RemoveMark(bookmark);
return;
}
}
// no bookmark at that line: create a new bookmark
BookmarkManager.AddMark(bookmarkFactory(new AstLocation(line, 0)));
}
public static event BookmarkEventHandler Removed;
public static event BookmarkEventHandler Added;
}
}