Browse Source

Remove dynamic code. Simplify debugging decompiled code.

pull/19/head
Eusebiu Marcu 14 years ago committed by Daniel Grunwald
parent
commit
5d5d266a9d
  1. 26
      src/AddIns/Debugger/Debugger.AddIn/Pads/BreakPointsPad.cs
  2. 79
      src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs
  3. 3
      src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml.cs
  4. 18
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/IconBarMargin.cs
  5. 19
      src/AddIns/DisplayBindings/ILSpyAddIn/DebuggerDecompilerService.cs
  6. 5
      src/AddIns/DisplayBindings/ILSpyAddIn/LaunchILSpy/ILSpyAssemblyResolver.cs
  7. 42
      src/AddIns/DisplayBindings/ILSpyAddIn/NavigateToDecompiledEntityService.cs
  8. 27
      src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/CodeView.cs
  9. 71
      src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/DecompiledViewContent.cs
  10. 34
      src/Main/Base/Project/Src/Bookmarks/Pad/BookmarkPad.cs
  11. 7
      src/Main/Base/Project/Src/Gui/AbstractViewContentWithoutFile.cs
  12. 13
      src/Main/Base/Project/Src/Services/Debugger/CurrentLineBookmark.cs
  13. 7
      src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs
  14. 49
      src/Main/Base/Project/Src/Services/Debugger/DecompiledBreakpointBookmark.cs
  15. 9
      src/Main/Base/Project/Src/Services/File/FileService.cs
  16. 7
      src/Main/Base/Project/Src/Services/NavigationService/NavigationService.cs

26
src/AddIns/Debugger/Debugger.AddIn/Pads/BreakPointsPad.cs

@ -1,8 +1,10 @@ @@ -1,8 +1,10 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
using System;
using System.Windows;
using System.Windows.Controls;
using Debugger;
using Debugger.AddIn.Pads.Controls;
using ICSharpCode.Core;
@ -66,5 +68,29 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -66,5 +68,29 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
{
return mark.IsVisibleInBookmarkPad && mark is BreakpointBookmark;
}
protected override void OnItemActivated(object sender, EventArgs e)
{
var node = CurrentItem;
if (node == null)
return;
SDBookmark mark = node.Mark as SDBookmark;
if (mark == null)
return;
string fileName = mark.FileName;
if (mark is DecompiledBreakpointBookmark) {
// get information from breakpoint and navigate to the decompiled type
string assemblyFile, typeName;
if (DecompiledBreakpointBookmark.GetAssemblyAndType(fileName, out assemblyFile, out typeName)) {
NavigationService.NavigateTo(assemblyFile, typeName, string.Empty, mark.LineNumber, false);
}
} else {
// jump to normal breakpoint
FileService.JumpToFilePosition(fileName, mark.LineNumber, 1);
// TODO: if other types of breakpoint bookmarks are available, one should do jumping/navigation here
}
}
}
}

79
src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs

@ -2,7 +2,6 @@ @@ -2,7 +2,6 @@
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
@ -755,10 +754,20 @@ namespace ICSharpCode.SharpDevelop.Services @@ -755,10 +754,20 @@ namespace ICSharpCode.SharpDevelop.Services
Breakpoint breakpoint = null;
if (bookmark is DecompiledBreakpointBookmark) {
try {
if (debuggerDecompilerService == null) {
LoggingService.Warn("No IDebuggerDecompilerService found!");
return;
}
var dbb = (DecompiledBreakpointBookmark)bookmark;
var memberReference = dbb.MemberReference;
int token = memberReference.MetadataToken.ToInt32();
MemberReference memberReference = null;
string assemblyFile, typeName;
if (DecompiledBreakpointBookmark.GetAssemblyAndType(dbb.FileName, out assemblyFile, out typeName)) {
memberReference = dbb.GetMemberReference(debuggerDecompilerService.GetAssemblyResolver(assemblyFile));
}
int token = memberReference.MetadataToken.ToInt32();
if (!debuggerDecompilerService.CheckMappings(token))
debuggerDecompilerService.DecompileOnDemand(memberReference as TypeDefinition);
@ -770,7 +779,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -770,7 +779,7 @@ namespace ICSharpCode.SharpDevelop.Services
// create BP
breakpoint = new ILBreakpoint(
debugger,
dbb.MemberReference.FullName,
memberReference.FullName,
dbb.LineNumber,
memberReference.MetadataToken.ToInt32(),
methodToken,
@ -779,6 +788,9 @@ namespace ICSharpCode.SharpDevelop.Services @@ -779,6 +788,9 @@ namespace ICSharpCode.SharpDevelop.Services
debugger.Breakpoints.Add(breakpoint);
}
} catch (System.Exception ex) {
LoggingService.Error("Error on DecompiledBreakpointBookmark: " + ex.Message);
}
} else {
breakpoint = debugger.Breakpoints.Add(bookmark.FileName, null, bookmark.LineNumber, 0, bookmark.IsEnabled);
}
@ -1038,58 +1050,51 @@ namespace ICSharpCode.SharpDevelop.Services @@ -1038,58 +1050,51 @@ namespace ICSharpCode.SharpDevelop.Services
DebuggerService.JumpToCurrentLine(nextStatement.Filename, nextStatement.StartLine, nextStatement.StartColumn, nextStatement.EndLine, nextStatement.EndColumn);
}
} else {
JumpToDecompiledCode();
}
}
void JumpToDecompiledCode()
{
if (debuggerDecompilerService == null) {
LoggingService.Warn("No IDebuggerDecompilerService found!");
return;
}
// check for options - if these options are enabled, debugging decompiled code should not continue
if (debuggedProcess.Options.EnableJustMyCode || debuggedProcess.Options.StepOverNoSymbols) {
LoggingService.Info("Decompiled code debugging is disabled!");
return;
}
// use most recent stack frame because we don't have the symbols
var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
if (frame == null)
return;
int typeToken = frame.MethodInfo.DeclaringType.MetadataToken;
Debug.Assert(frame != null);
// get external data
int typeToken = frame.MethodInfo.DeclaringType.MetadataToken;
int methodToken = frame.MethodInfo.MetadataToken;
int ilOffset = frame.IP;
int[] ilRanges = null;
int line = -1;
bool isMatch = false;
if (debuggerDecompilerService.GetILAndLineNumber(typeToken, methodToken, ilOffset, out ilRanges, out line, out isMatch)) {
debuggerDecompilerService.DebugStepInformation = null; // we do not need to step into/out
// update marker
var debugType = (DebugType)frame.MethodInfo.DeclaringType;
debuggerDecompilerService.DebugStepInformation = Tuple.Create(methodToken, ilOffset);
foreach (dynamic vc in WorkbenchSingleton.Workbench.ViewContentCollection.OfType<AbstractViewContentWithoutFile>()) {
if (vc == null || vc.MemberReference == null)
continue;
if (vc.MemberReference.MetadataToken.ToInt32() == debugType.MetadataToken) {
CurrentLineBookmark.SetPosition(vc, line, 0, line, 0);
var wbw = vc.WorkbenchWindow as IWorkbenchWindow;
if (wbw != null)
wbw.SelectWindow();
return;
}
}
// the decompiled content was closed so we have to recreate it
StepIntoUnknownFrame(frame, methodToken, ilOffset);
if (debuggerDecompilerService.GetILAndLineNumber(typeToken, methodToken, ilOffset, out ilRanges, out line, out isMatch)) {
// update marker & navigate to line
NavigationService.NavigateTo(debugType.DebugModule.FullPath,
debugType.FullNameWithoutGenericArguments,
string.Empty,
line);
} else {
StepIntoUnknownFrame(frame, methodToken, ilOffset);
}
// no line => do decompilation
NavigationService.NavigateTo(debugType.DebugModule.FullPath,
debugType.FullNameWithoutGenericArguments,
string.Empty);
}
}
void StepIntoUnknownFrame(Debugger.StackFrame frame, int token, int ilOffset)
{
var debugType = (DebugType)frame.MethodInfo.DeclaringType;
string fullName = debugType.FullNameWithoutGenericArguments;
debuggerDecompilerService.DebugStepInformation = Tuple.Create(token, ilOffset);
NavigationService.NavigateTo(debugType.DebugModule.FullPath, debugType.FullNameWithoutGenericArguments, string.Empty);
}
StopAttachedProcessDialogResult ShowStopAttachedProcessDialog()
{
string caption = StringParser.Parse("${res:XML.MainMenu.DebugMenu.Stop}");

3
src/AddIns/Debugger/Debugger.AddIn/Tooltips/DebuggerTooltipControl.xaml.cs

@ -105,8 +105,7 @@ namespace Debugger.AddIn.Tooltips @@ -105,8 +105,7 @@ namespace Debugger.AddIn.Tooltips
if (provider != null) {
editor = provider.TextEditor;
} else {
dynamic codeView = viewContent.Control;
editor = codeView.TextEditor as ITextEditor;
editor = viewContent.GetService(typeof(ITextEditor)) as ITextEditor;
}
if (editor != null) {

18
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/IconBarMargin.cs

@ -238,14 +238,16 @@ namespace ICSharpCode.AvalonEdit.AddIn @@ -238,14 +238,16 @@ namespace ICSharpCode.AvalonEdit.AddIn
DebuggerService.ToggleBreakpointAt(textEditor, line);
return;
}
// create breakpoint for the decompiled content
dynamic viewContent = WorkbenchSingleton.Workbench.ActiveContent;
if (viewContent is AbstractViewContentWithoutFile) {
dynamic codeView = ((AbstractViewContentWithoutFile)viewContent).Control;
var editor = codeView.TextEditor as ITextEditor;
var memberReference = viewContent.MemberReference as MemberReference;
if (editor != null && !string.IsNullOrEmpty(editor.FileName))
DebuggerService.ToggleBreakpointAt(memberReference, editor, line);
// create breakpoint for the other posible active contents
var viewContent = WorkbenchSingleton.Workbench.ActiveContent as AbstractViewContentWithoutFile;
if (viewContent != null && viewContent.Tag is MemberReference) {
var memberReference = (MemberReference)viewContent.Tag;
textEditor = viewContent.Services.GetService(typeof(ITextEditor)) as ITextEditor;
if (textEditor != null) {
DebuggerService.ToggleBreakpointAt(memberReference, textEditor, line);
return;
}
}
}
}

19
src/AddIns/DisplayBindings/ILSpyAddIn/DebuggerDecompilerService.cs

@ -3,10 +3,12 @@ @@ -3,10 +3,12 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.Decompiler.ILAst;
using ICSharpCode.ILSpyAddIn.LaunchILSpy;
using ICSharpCode.SharpDevelop.Debugging;
using Mono.Cecil;
@ -17,6 +19,8 @@ namespace ICSharpCode.ILSpyAddIn @@ -17,6 +19,8 @@ namespace ICSharpCode.ILSpyAddIn
/// </summary>
public class DebuggerDecompilerService : IDebuggerDecompilerService
{
ILSpyAssemblyResolver resolver;
static DebuggerDecompilerService()
{
DebugInformation = new ConcurrentDictionary<int, DecompileInformation>();
@ -166,5 +170,20 @@ namespace ICSharpCode.ILSpyAddIn @@ -166,5 +170,20 @@ namespace ICSharpCode.ILSpyAddIn
return null;
}
public IAssemblyResolver GetAssemblyResolver(string assemblyFile)
{
if (string.IsNullOrEmpty(assemblyFile))
throw new ArgumentException("assemblyFile is null or empty");
string folderPath = Path.GetDirectoryName(assemblyFile);
if (resolver == null)
return (resolver = new ILSpyAssemblyResolver(folderPath));
if (string.Compare(folderPath, resolver.FolderPath, StringComparison.OrdinalIgnoreCase) != 0)
return (resolver = new ILSpyAssemblyResolver(folderPath));
return resolver;
}
}
}

5
src/AddIns/DisplayBindings/ILSpyAddIn/LaunchILSpy/ILSpyAssemblyResolver.cs

@ -22,10 +22,15 @@ namespace ICSharpCode.ILSpyAddIn.LaunchILSpy @@ -22,10 +22,15 @@ namespace ICSharpCode.ILSpyAddIn.LaunchILSpy
if (string.IsNullOrEmpty(decompiledAssemblyFolder))
throw new ArgumentException("Invalid working folder");
FolderPath = decompiledAssemblyFolder;
this.directoryInfo = new DirectoryInfo(decompiledAssemblyFolder);
this.cache = new Dictionary<string, AssemblyDefinition> ();
}
public string FolderPath {
get; private set;
}
public AssemblyDefinition Resolve(AssemblyNameReference name)
{
return this.Resolve(name, new ReaderParameters());

42
src/AddIns/DisplayBindings/ILSpyAddIn/NavigateToDecompiledEntityService.cs

@ -48,29 +48,45 @@ namespace ICSharpCode.ILSpyAddIn @@ -48,29 +48,45 @@ namespace ICSharpCode.ILSpyAddIn
if (string.IsNullOrEmpty(typeName))
throw new ArgumentException("typeName is null or empty");
foreach (var vc in WorkbenchSingleton.Workbench.ViewContentCollection.OfType<DecompiledViewContent>()) {
if (string.Equals(vc.AssemblyFile, assemblyFile, StringComparison.OrdinalIgnoreCase) && typeName == vc.FullTypeName) {
vc.WorkbenchWindow.SelectWindow();
vc.JumpToEntity(entityTag);
foreach (var viewContent in WorkbenchSingleton.Workbench.ViewContentCollection.OfType<DecompiledViewContent>()) {
if (string.Equals(viewContent.AssemblyFile, assemblyFile, StringComparison.OrdinalIgnoreCase) && typeName == viewContent.FullTypeName) {
viewContent.WorkbenchWindow.SelectWindow();
viewContent.JumpToEntity(entityTag);
return;
}
}
WorkbenchSingleton.Workbench.ShowView(new DecompiledViewContent(assemblyFile, typeName, entityTag));
}
public bool NavigateToMember(string assemblyFile, string typeName, string entityTag, int lineNumber)
public bool NavigateToMember(string assemblyFile, string typeName, string entityTag, int lineNumber, bool updateMarker)
{
//close the window if exists - this is a workaround
foreach (var vc in WorkbenchSingleton.Workbench.ViewContentCollection.OfType<DecompiledViewContent>()) {
if (string.Equals(vc.AssemblyFile, assemblyFile, StringComparison.OrdinalIgnoreCase) && typeName == vc.FullTypeName) {
vc.WorkbenchWindow.CloseWindow(true);
break;
if (string.IsNullOrEmpty(assemblyFile))
throw new ArgumentException("assemblyFile is null or empty");
if (string.IsNullOrEmpty(typeName))
throw new ArgumentException("typeName is null or empty");
// jump to line number if the decompiled view content exits - no need for a new decompilation
foreach (var viewContent in WorkbenchSingleton.Workbench.ViewContentCollection.OfType<DecompiledViewContent>()) {
if (string.Equals(viewContent.AssemblyFile, assemblyFile, StringComparison.OrdinalIgnoreCase) && typeName == viewContent.FullTypeName) {
if (updateMarker) {
viewContent.UpdateDebuggingUI();
}
viewContent.JumpToLineNumber(lineNumber);
viewContent.WorkbenchWindow.SelectWindow();
return true;
}
}
var view = new DecompiledViewContent(assemblyFile, typeName, entityTag);
view.DecompilationFinished += delegate { view.JumpTo(lineNumber); };
WorkbenchSingleton.Workbench.ShowView(view);
// create a new decompiled view
var decompiledView = new DecompiledViewContent(assemblyFile, typeName, entityTag);
decompiledView.DecompilationFinished += delegate {
if (updateMarker) {
decompiledView.UpdateDebuggingUI();
}
decompiledView.JumpToLineNumber(lineNumber);
};
WorkbenchSingleton.Workbench.ShowView(decompiledView);
return true;
}
}

27
src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/CodeView.cs

@ -25,17 +25,17 @@ namespace ICSharpCode.ILSpyAddIn.ViewContent @@ -25,17 +25,17 @@ namespace ICSharpCode.ILSpyAddIn.ViewContent
public DecompiledTextEditorAdapter(TextEditor textEditor) : base(textEditor)
{}
public string DecompiledFullTypeName { get; set; }
public string DecompiledFileName { get; set; }
public override ICSharpCode.Core.FileName FileName {
get { return ICSharpCode.Core.FileName.Create(DecompiledFullTypeName); }
get { return ICSharpCode.Core.FileName.Create(DecompiledFileName); }
}
}
/// <summary>
/// Equivalent to AE.AddIn CodeEditor, but without editing capabilities.
/// </summary>
public class CodeView : Grid, IDisposable, ICodeEditor
class CodeView : Grid, IDisposable, ICodeEditor
{
public event EventHandler DocumentChanged;
@ -44,11 +44,10 @@ namespace ICSharpCode.ILSpyAddIn.ViewContent @@ -44,11 +44,10 @@ namespace ICSharpCode.ILSpyAddIn.ViewContent
readonly IconBarMargin iconMargin;
readonly TextMarkerService textMarkerService;
public CodeView(string decompiledFullTypeName)
public CodeView(string decompiledFileName)
{
DecompiledFullTypeName = decompiledFullTypeName;
this.adapter = new DecompiledTextEditorAdapter(new SharpDevelopTextEditor { IsReadOnly = true }) {
DecompiledFullTypeName = decompiledFullTypeName
DecompiledFileName = decompiledFileName
};
this.Children.Add(adapter.TextEditor);
adapter.TextEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition("C#");
@ -64,6 +63,7 @@ namespace ICSharpCode.ILSpyAddIn.ViewContent @@ -64,6 +63,7 @@ namespace ICSharpCode.ILSpyAddIn.ViewContent
this.adapter.TextEditor.TextArea.TextView.LineTransformers.Add(textMarkerService);
this.adapter.TextEditor.TextArea.TextView.Services.AddService(typeof(ITextMarkerService), textMarkerService);
this.adapter.TextEditor.TextArea.TextView.Services.AddService(typeof(IBookmarkMargin), iconBarManager);
// DON'T add the editor in textview ervices - will mess the setting of breakpoints
// add events
this.adapter.TextEditor.MouseHover += TextEditorMouseHover;
@ -230,16 +230,6 @@ namespace ICSharpCode.ILSpyAddIn.ViewContent @@ -230,16 +230,6 @@ namespace ICSharpCode.ILSpyAddIn.ViewContent
get { return iconBarManager; }
}
public AvalonEditTextEditorAdapter Adapter {
get {
return adapter;
}
}
public string DecompiledFullTypeName {
get; private set;
}
public void Dispose()
{
}
@ -249,9 +239,9 @@ namespace ICSharpCode.ILSpyAddIn.ViewContent @@ -249,9 +239,9 @@ namespace ICSharpCode.ILSpyAddIn.ViewContent
if (lineNumber <= 0 || lineNumber > adapter.Document.TotalNumberOfLines)
return;
//var line = adapter.TextEditor.Document.GetLineByNumber(lineNumber);
// var line = adapter.TextEditor.Document.GetLineByNumber(lineNumber);
// unfold
// // unfold
// var foldings = foldingManager.GetFoldingsContaining(line.Offset);
// if (foldings != null) {
// foreach (var folding in foldings) {
@ -260,6 +250,7 @@ namespace ICSharpCode.ILSpyAddIn.ViewContent @@ -260,6 +250,7 @@ namespace ICSharpCode.ILSpyAddIn.ViewContent
// }
// }
// }
// scroll to
adapter.TextEditor.ScrollTo(lineNumber, 0);
}

71
src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/DecompiledViewContent.cs

@ -16,6 +16,7 @@ using ICSharpCode.NRefactory.Utils; @@ -16,6 +16,7 @@ using ICSharpCode.NRefactory.Utils;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Bookmarks;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui;
using Mono.Cecil;
@ -24,7 +25,7 @@ namespace ICSharpCode.ILSpyAddIn @@ -24,7 +25,7 @@ namespace ICSharpCode.ILSpyAddIn
/// <summary>
/// Hosts a decompiled type.
/// </summary>
public class DecompiledViewContent : AbstractViewContentWithoutFile
class DecompiledViewContent : AbstractViewContentWithoutFile
{
readonly string assemblyFile;
readonly string fullTypeName;
@ -43,14 +44,17 @@ namespace ICSharpCode.ILSpyAddIn @@ -43,14 +44,17 @@ namespace ICSharpCode.ILSpyAddIn
#region Constructor
public DecompiledViewContent(string assemblyFile, string fullTypeName, string entityTag)
{
codeView = new CodeView(string.Format("{0},{1}", assemblyFile, fullTypeName));
// TODO: create options for decompiling in a specific language
this.tempFileName = string.Format("{0}{1}{2}.cs", assemblyFile, DecompiledBreakpointBookmark.SEPARATOR, fullTypeName);
this.codeView = new CodeView(tempFileName);
this.assemblyFile = assemblyFile;
this.fullTypeName = fullTypeName;
this.jumpToEntityTagWhenDecompilationFinished = entityTag;
string shortTypeName = fullTypeName.Substring(fullTypeName.LastIndexOf('.') + 1);
this.TitleName = "[" + shortTypeName + "]";
tempFileName = string.Format("decompiled/{0}.cs", fullTypeName);
this.InfoTip = tempFileName;
Thread thread = new Thread(DecompilationThread);
@ -59,6 +63,9 @@ namespace ICSharpCode.ILSpyAddIn @@ -59,6 +63,9 @@ namespace ICSharpCode.ILSpyAddIn
BookmarkManager.Removed += BookmarkManager_Removed;
BookmarkManager.Added += BookmarkManager_Added;
// add services
this.Services.AddService(typeof(ITextEditor), this.codeView.TextEditor);
}
#endregion
@ -83,6 +90,10 @@ namespace ICSharpCode.ILSpyAddIn @@ -83,6 +90,10 @@ namespace ICSharpCode.ILSpyAddIn
get; private set;
}
public override object Tag {
get { return MemberReference; }
}
#endregion
#region Dispose
@ -194,9 +205,8 @@ namespace ICSharpCode.ILSpyAddIn @@ -194,9 +205,8 @@ namespace ICSharpCode.ILSpyAddIn
// update UI
UpdateIconMargin(output.ToString());
UpdateDebuggingUI();
// fire event
// fire events
OnDecompilationFinished(EventArgs.Empty);
}
#endregion
@ -207,13 +217,13 @@ namespace ICSharpCode.ILSpyAddIn @@ -207,13 +217,13 @@ namespace ICSharpCode.ILSpyAddIn
codeView.IconBarManager.UpdateClassMemberBookmarks(ParserService.ParseFile(tempFileName, new StringTextBuffer(text)));
// load bookmarks
foreach (SDBookmark bookmark in BookmarkManager.GetBookmarks(codeView.Adapter.FileName)) {
bookmark.Document = codeView.Adapter.Document;
foreach (SDBookmark bookmark in BookmarkManager.GetBookmarks(this.codeView.TextEditor.FileName)) {
bookmark.Document = this.codeView.TextEditor.Document;
codeView.IconBarManager.Bookmarks.Add(bookmark);
}
}
void UpdateDebuggingUI()
public void UpdateDebuggingUI()
{
if (!DebuggerService.IsDebuggerStarted)
return;
@ -223,33 +233,35 @@ namespace ICSharpCode.ILSpyAddIn @@ -223,33 +233,35 @@ namespace ICSharpCode.ILSpyAddIn
int typeToken = MemberReference.MetadataToken.ToInt32();
if (!DebuggerDecompilerService.DebugInformation.ContainsKey(typeToken))
return;
if (DebuggerDecompilerService.Instance == null || DebuggerDecompilerService.Instance.DebugStepInformation == null)
var decompilerService = DebuggerDecompilerService.Instance;
if (decompilerService == null || decompilerService.DebugStepInformation == null)
return;
// get debugging information
DecompileInformation debugInformation = (DecompileInformation)DebuggerDecompilerService.DebugInformation[typeToken];
int token = DebuggerDecompilerService.Instance.DebugStepInformation.Item1;
int ilOffset = DebuggerDecompilerService.Instance.DebugStepInformation.Item2;
int methodToken = decompilerService.DebugStepInformation.Item1;
int ilOffset = decompilerService.DebugStepInformation.Item2;
int line;
MemberReference member;
if (debugInformation.CodeMappings == null || !debugInformation.CodeMappings.ContainsKey(token))
if (debugInformation.CodeMappings == null || !debugInformation.CodeMappings.ContainsKey(methodToken))
return;
debugInformation.CodeMappings[token].GetInstructionByTokenAndOffset(token, ilOffset, out member, out line);
debugInformation.CodeMappings[methodToken].GetInstructionByTokenAndOffset(methodToken, ilOffset, out member, out line);
// HACK : if the codemappings are not built
// if the codemappings are not built
if (line <= 0) {
DebuggerService.CurrentDebugger.StepOver();
return;
}
// update bookmark & marker
codeView.UnfoldAndScroll(line);
CurrentLineBookmark.SetPosition(this, line, 0, line, 0);
// jump to line - scoll and unfold
this.UpdateCurrentLineBookmark(line);
this.JumpToLineNumber(line);
}
public void JumpTo(int lineNumber)
public void JumpToLineNumber(int lineNumber)
{
if (codeView == null)
if (codeView == null || codeView.Document == null)
return;
if (lineNumber <= 0 || lineNumber > codeView.Document.LineCount)
@ -257,6 +269,21 @@ namespace ICSharpCode.ILSpyAddIn @@ -257,6 +269,21 @@ namespace ICSharpCode.ILSpyAddIn
codeView.UnfoldAndScroll(lineNumber);
}
void UpdateCurrentLineBookmark(int lineNumber)
{
if (lineNumber <= 0)
return;
CurrentLineBookmark.SetPosition(codeView.TextEditor.FileName, codeView.TextEditor.Document, lineNumber, 0, lineNumber, 0);
var currentLineBookmark = BookmarkManager.Bookmarks.OfType<CurrentLineBookmark>().FirstOrDefault();
if (currentLineBookmark != null) {
// update bookmark & marker
codeView.IconBarManager.Bookmarks.Add(currentLineBookmark);
currentLineBookmark.Document = this.codeView.TextEditor.Document;
}
}
#endregion
#region Bookmarks
@ -272,14 +299,15 @@ namespace ICSharpCode.ILSpyAddIn @@ -272,14 +299,15 @@ namespace ICSharpCode.ILSpyAddIn
void BookmarkManager_Added(object sender, BookmarkEventArgs e)
{
var mark = e.Bookmark;
if (mark != null && mark is BreakpointBookmark && mark.FileName == codeView.DecompiledFullTypeName) {
if (mark != null && mark is BreakpointBookmark && mark.FileName == this.codeView.TextEditor.FileName) {
codeView.IconBarManager.Bookmarks.Add(mark);
mark.Document = codeView.Adapter.Document;
mark.Document = this.codeView.TextEditor.Document;
}
}
#endregion
#region Events
public event EventHandler DecompilationFinished;
protected virtual void OnDecompilationFinished(EventArgs e)
@ -288,6 +316,7 @@ namespace ICSharpCode.ILSpyAddIn @@ -288,6 +316,7 @@ namespace ICSharpCode.ILSpyAddIn
DecompilationFinished(this, e);
}
}
#endregion
}
}

34
src/Main/Base/Project/Src/Bookmarks/Pad/BookmarkPad.cs

@ -72,14 +72,14 @@ namespace ICSharpCode.SharpDevelop.Bookmarks @@ -72,14 +72,14 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
listView.SetValue(Grid.RowProperty, 1);
myPanel.Children.Add(listView);
BookmarkManager.Added += new BookmarkEventHandler(BookmarkManagerAdded);
BookmarkManager.Removed += new BookmarkEventHandler(BookmarkManagerRemoved);
BookmarkManager.Added += BookmarkManagerAdded;
BookmarkManager.Removed += BookmarkManagerRemoved;
foreach (SDBookmark mark in BookmarkManager.Bookmarks) {
AddMark(mark);
}
listView.ItemActivated += new EventHandler(listView_ItemActivated);
listView.ItemActivated += new EventHandler(OnItemActivated);
}
public IEnumerable<ListViewPadItemModel> AllItems {
@ -120,6 +120,12 @@ namespace ICSharpCode.SharpDevelop.Bookmarks @@ -120,6 +120,12 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
listView.CurrentItem = model;
}
public override void Dispose()
{
BookmarkManager.Added -= BookmarkManagerAdded;
BookmarkManager.Removed -= BookmarkManagerRemoved;
}
void AddMark(SDBookmark mark)
{
if (!ShowBookmarkInThisPad(mark))
@ -133,6 +139,17 @@ namespace ICSharpCode.SharpDevelop.Bookmarks @@ -133,6 +139,17 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
return mark.IsVisibleInBookmarkPad && !(mark is BreakpointBookmark);
}
protected virtual void OnItemActivated(object sender, EventArgs e)
{
var node = CurrentItem;
if (node != null) {
SDBookmark mark = node.Mark as SDBookmark;
if (mark != null) {
FileService.JumpToFilePosition(mark.FileName, mark.LineNumber, 1);
}
}
}
void BookmarkManagerAdded(object sender, BookmarkEventArgs e)
{
AddMark((SDBookmark)e.Bookmark);
@ -143,16 +160,5 @@ namespace ICSharpCode.SharpDevelop.Bookmarks @@ -143,16 +160,5 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
if (ShowBookmarkInThisPad(e.Bookmark))
listView.Remove(new ListViewPadItemModel(e.Bookmark));
}
void listView_ItemActivated(object sender, EventArgs e)
{
var node = CurrentItem;
if (node != null) {
SDBookmark mark = node.Mark as SDBookmark;
if (mark != null) {
FileService.JumpToFilePosition(mark.FileName, mark.LineNumber, 1);
}
}
}
}
}

7
src/Main/Base/Project/Src/Gui/AbstractViewContentWithoutFile.cs

@ -16,6 +16,13 @@ namespace ICSharpCode.SharpDevelop.Gui @@ -16,6 +16,13 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary>
public abstract class AbstractViewContentWithoutFile : AbstractViewContent, ICustomizedCommands
{
/// <summary>
/// Gets specific information (from implementations) regarding this view content.
/// </summary>
public virtual object Tag {
get { return null; }
}
public override bool IsViewOnly {
get { return false; }
}

13
src/Main/Base/Project/Src/Services/Debugger/CurrentLineBookmark.cs

@ -27,19 +27,6 @@ namespace ICSharpCode.SharpDevelop.Debugging @@ -27,19 +27,6 @@ namespace ICSharpCode.SharpDevelop.Debugging
ITextEditorProvider tecp = viewContent as ITextEditorProvider;
if (tecp != null) {
SetPosition(tecp.TextEditor.FileName, tecp.TextEditor.Document, markerStartLine, markerStartColumn, markerEndLine, markerEndColumn);
} else {
lock (syncObject) {
// get the decompiled view if exists
if (viewContent != null && viewContent.Control != null) {
dynamic codeView = viewContent.Control;
var document = codeView.TextEditor.Document as IDocument;
SetPosition(codeView.Adapter.FileName, document, markerStartLine, markerStartColumn, markerEndLine, markerEndColumn);
codeView.IconBarManager.Bookmarks.Add(CurrentLineBookmark.instance);
codeView.UnfoldAndScroll(markerStartLine);
if (document != null)
CurrentLineBookmark.instance.Document = document;
}
}
}
}

7
src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs

@ -479,5 +479,12 @@ namespace ICSharpCode.SharpDevelop.Debugging @@ -479,5 +479,12 @@ namespace ICSharpCode.SharpDevelop.Debugging
/// Gets the local variable index.
/// </summary>
object GetLocalVariableIndex(int typeToken, int memberToken, string name);
/// <summary>
/// Gets an implementation of an assembly resolver.
/// </summary>
/// <param name="assemblyFile">Assembly file path.</param>
/// <returns>An <see cref="IAssemblyResolver"/>.</returns>
IAssemblyResolver GetAssemblyResolver(string assemblyFile);
}
}

49
src/Main/Base/Project/Src/Services/Debugger/DecompiledBreakpointBookmark.cs

@ -10,9 +10,14 @@ namespace ICSharpCode.SharpDevelop.Bookmarks @@ -10,9 +10,14 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
{
public class DecompiledBreakpointBookmark : BreakpointBookmark
{
public const string SEPARATOR = ","; // don't use '.'
MemberReference memberReference;
string assemblyFile;
public DecompiledBreakpointBookmark(MemberReference member, int ilFrom, int ilTo, FileName fileName, Location location, BreakpointAction action, string scriptLanguage, string script) : base(fileName, location, action, scriptLanguage, script)
{
this.MemberReference = member;
this.memberReference = member;
this.ILFrom = ilFrom;
this.ILTo = ILTo;
}
@ -25,10 +30,15 @@ namespace ICSharpCode.SharpDevelop.Bookmarks @@ -25,10 +30,15 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
get; set;
}
MemberReference memberReference;
public MemberReference MemberReference {
get {
get { return memberReference; }
}
public MemberReference GetMemberReference(IAssemblyResolver resolver)
{
if (resolver == null)
throw new ArgumentNullException("resolver");
if (memberReference != null)
return memberReference;
@ -36,21 +46,36 @@ namespace ICSharpCode.SharpDevelop.Bookmarks @@ -36,21 +46,36 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
ReaderParameters readerParameters = new ReaderParameters();
// Use new assembly resolver instance so that the AssemblyDefinitions can be garbage-collected
// once the code is decompiled.
readerParameters.AssemblyResolver = new DefaultAssemblyResolver();
string fileName = FileName.ToString();
int index = fileName.IndexOf(",");
string assemblyFile = fileName.Substring(0, index);
string fullTypeName = fileName.Substring(index + 1, fileName.Length - index - 1);
readerParameters.AssemblyResolver = resolver;
string typeName;
if (GetAssemblyAndType(FileName.ToString(), out assemblyFile, out typeName)) {
ModuleDefinition module = ModuleDefinition.ReadModule(assemblyFile, readerParameters);
TypeDefinition typeDefinition = module.GetType(fullTypeName);
TypeDefinition typeDefinition = module.GetType(typeName);
if (typeDefinition == null)
throw new InvalidOperationException("Could not find type");
memberReference = typeDefinition;
}
return memberReference;
}
private set { memberReference = value; }
/// <summary>
/// Gets the assembly file and the type from the file name.
/// </summary>
/// <returns><c>true</c>, if the operation succeded; <c>false</c>, otherwise.</returns>
public static bool GetAssemblyAndType(string fileName, out string assemblyFile, out string typeName)
{
if (string.IsNullOrEmpty(fileName) || !fileName.Contains(",")) {
assemblyFile = null;
typeName = null;
return false;
}
int index = fileName.IndexOf(SEPARATOR);
assemblyFile = fileName.Substring(0, index);
typeName = fileName.Substring(index + 1, fileName.Length - index - 4);
return true;
}
}
}

9
src/Main/Base/Project/Src/Services/File/FileService.cs

@ -533,15 +533,6 @@ namespace ICSharpCode.SharpDevelop @@ -533,15 +533,6 @@ namespace ICSharpCode.SharpDevelop
bool loggingResumed = false;
try {
// jump to decompiled type from filename
if (fileName.Contains(",")) {
int index = fileName.IndexOf(",");
string assemblyName = fileName.Substring(0, index);
string typeName = fileName.Substring(index + 1, fileName.Length - index - 1);
NavigationService.NavigateTo(assemblyName, typeName, string.Empty, line);
return null;
}
IViewContent content = OpenFile(fileName);
if (content is IPositionable) {
// TODO: enable jumping to a particular view

7
src/Main/Base/Project/Src/Services/NavigationService/NavigationService.cs

@ -6,7 +6,6 @@ using System.Collections.Generic; @@ -6,7 +6,6 @@ using System.Collections.Generic;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project;
using Mono.Cecil;
namespace ICSharpCode.SharpDevelop
{
@ -475,7 +474,7 @@ namespace ICSharpCode.SharpDevelop @@ -475,7 +474,7 @@ namespace ICSharpCode.SharpDevelop
#region Navigate to Member
public static bool NavigateTo(string assemblyFile, string typeName, string entityTag, int lineNumber = 0)
public static bool NavigateTo(string assemblyFile, string typeName, string entityTag, int lineNumber = 0, bool updateMarker = true)
{
if (string.IsNullOrEmpty(assemblyFile))
throw new ArgumentException("assemblyFile is null or empty");
@ -484,7 +483,7 @@ namespace ICSharpCode.SharpDevelop @@ -484,7 +483,7 @@ namespace ICSharpCode.SharpDevelop
throw new ArgumentException("typeName is null or empty");
foreach (var item in AddInTree.BuildItems<INavigateToMemberService>("/SharpDevelop/Services/NavigateToEntityService", null, false)) {
if (item.NavigateToMember(assemblyFile, typeName, entityTag, lineNumber))
if (item.NavigateToMember(assemblyFile, typeName, entityTag, lineNumber, updateMarker))
return true;
}
return false;
@ -512,6 +511,6 @@ namespace ICSharpCode.SharpDevelop @@ -512,6 +511,6 @@ namespace ICSharpCode.SharpDevelop
/// </remarks>
public interface INavigateToMemberService
{
bool NavigateToMember(string assemblyFile, string typeName, string entityTag, int lineNumber);
bool NavigateToMember(string assemblyFile, string typeName, string entityTag, int lineNumber, bool updateMarker);
}
}

Loading…
Cancel
Save