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. 25
      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 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // 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) // 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;
using System.Windows.Controls; using System.Windows.Controls;
using Debugger; using Debugger;
using Debugger.AddIn.Pads.Controls; using Debugger.AddIn.Pads.Controls;
using ICSharpCode.Core; using ICSharpCode.Core;
@ -66,5 +68,29 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
{ {
return mark.IsVisibleInBookmarkPad && mark is BreakpointBookmark; 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 @@
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) // This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
@ -755,10 +754,20 @@ namespace ICSharpCode.SharpDevelop.Services
Breakpoint breakpoint = null; Breakpoint breakpoint = null;
if (bookmark is DecompiledBreakpointBookmark) { if (bookmark is DecompiledBreakpointBookmark) {
try {
if (debuggerDecompilerService == null) {
LoggingService.Warn("No IDebuggerDecompilerService found!");
return;
}
var dbb = (DecompiledBreakpointBookmark)bookmark; var dbb = (DecompiledBreakpointBookmark)bookmark;
var memberReference = dbb.MemberReference; MemberReference memberReference = null;
int token = memberReference.MetadataToken.ToInt32();
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)) if (!debuggerDecompilerService.CheckMappings(token))
debuggerDecompilerService.DecompileOnDemand(memberReference as TypeDefinition); debuggerDecompilerService.DecompileOnDemand(memberReference as TypeDefinition);
@ -770,7 +779,7 @@ namespace ICSharpCode.SharpDevelop.Services
// create BP // create BP
breakpoint = new ILBreakpoint( breakpoint = new ILBreakpoint(
debugger, debugger,
dbb.MemberReference.FullName, memberReference.FullName,
dbb.LineNumber, dbb.LineNumber,
memberReference.MetadataToken.ToInt32(), memberReference.MetadataToken.ToInt32(),
methodToken, methodToken,
@ -779,6 +788,9 @@ namespace ICSharpCode.SharpDevelop.Services
debugger.Breakpoints.Add(breakpoint); debugger.Breakpoints.Add(breakpoint);
} }
} catch (System.Exception ex) {
LoggingService.Error("Error on DecompiledBreakpointBookmark: " + ex.Message);
}
} else { } else {
breakpoint = debugger.Breakpoints.Add(bookmark.FileName, null, bookmark.LineNumber, 0, bookmark.IsEnabled); breakpoint = debugger.Breakpoints.Add(bookmark.FileName, null, bookmark.LineNumber, 0, bookmark.IsEnabled);
} }
@ -1038,58 +1050,51 @@ namespace ICSharpCode.SharpDevelop.Services
DebuggerService.JumpToCurrentLine(nextStatement.Filename, nextStatement.StartLine, nextStatement.StartColumn, nextStatement.EndLine, nextStatement.EndColumn); DebuggerService.JumpToCurrentLine(nextStatement.Filename, nextStatement.StartLine, nextStatement.StartColumn, nextStatement.EndLine, nextStatement.EndColumn);
} }
} else { } else {
JumpToDecompiledCode();
}
}
void JumpToDecompiledCode()
{
if (debuggerDecompilerService == null) { if (debuggerDecompilerService == null) {
LoggingService.Warn("No IDebuggerDecompilerService found!"); LoggingService.Warn("No IDebuggerDecompilerService found!");
return; 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 // use most recent stack frame because we don't have the symbols
var frame = debuggedProcess.SelectedThread.MostRecentStackFrame; var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
if (frame == null) Debug.Assert(frame != null);
return;
int typeToken = frame.MethodInfo.DeclaringType.MetadataToken;
// get external data // get external data
int typeToken = frame.MethodInfo.DeclaringType.MetadataToken;
int methodToken = frame.MethodInfo.MetadataToken; int methodToken = frame.MethodInfo.MetadataToken;
int ilOffset = frame.IP; int ilOffset = frame.IP;
int[] ilRanges = null; int[] ilRanges = null;
int line = -1; int line = -1;
bool isMatch = false; 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; var debugType = (DebugType)frame.MethodInfo.DeclaringType;
debuggerDecompilerService.DebugStepInformation = Tuple.Create(methodToken, ilOffset);
foreach (dynamic vc in WorkbenchSingleton.Workbench.ViewContentCollection.OfType<AbstractViewContentWithoutFile>()) { if (debuggerDecompilerService.GetILAndLineNumber(typeToken, methodToken, ilOffset, out ilRanges, out line, out isMatch)) {
if (vc == null || vc.MemberReference == null) // update marker & navigate to line
continue; NavigationService.NavigateTo(debugType.DebugModule.FullPath,
debugType.FullNameWithoutGenericArguments,
if (vc.MemberReference.MetadataToken.ToInt32() == debugType.MetadataToken) { string.Empty,
CurrentLineBookmark.SetPosition(vc, line, 0, line, 0); line);
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);
} else { } 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() StopAttachedProcessDialogResult ShowStopAttachedProcessDialog()
{ {
string caption = StringParser.Parse("${res:XML.MainMenu.DebugMenu.Stop}"); 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
if (provider != null) { if (provider != null) {
editor = provider.TextEditor; editor = provider.TextEditor;
} else { } else {
dynamic codeView = viewContent.Control; editor = viewContent.GetService(typeof(ITextEditor)) as ITextEditor;
editor = codeView.TextEditor as ITextEditor;
} }
if (editor != null) { if (editor != null) {

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

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

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

@ -3,10 +3,12 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Ast; using ICSharpCode.Decompiler.Ast;
using ICSharpCode.Decompiler.ILAst; using ICSharpCode.Decompiler.ILAst;
using ICSharpCode.ILSpyAddIn.LaunchILSpy;
using ICSharpCode.SharpDevelop.Debugging; using ICSharpCode.SharpDevelop.Debugging;
using Mono.Cecil; using Mono.Cecil;
@ -17,6 +19,8 @@ namespace ICSharpCode.ILSpyAddIn
/// </summary> /// </summary>
public class DebuggerDecompilerService : IDebuggerDecompilerService public class DebuggerDecompilerService : IDebuggerDecompilerService
{ {
ILSpyAssemblyResolver resolver;
static DebuggerDecompilerService() static DebuggerDecompilerService()
{ {
DebugInformation = new ConcurrentDictionary<int, DecompileInformation>(); DebugInformation = new ConcurrentDictionary<int, DecompileInformation>();
@ -166,5 +170,20 @@ namespace ICSharpCode.ILSpyAddIn
return null; 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
if (string.IsNullOrEmpty(decompiledAssemblyFolder)) if (string.IsNullOrEmpty(decompiledAssemblyFolder))
throw new ArgumentException("Invalid working folder"); throw new ArgumentException("Invalid working folder");
FolderPath = decompiledAssemblyFolder;
this.directoryInfo = new DirectoryInfo(decompiledAssemblyFolder); this.directoryInfo = new DirectoryInfo(decompiledAssemblyFolder);
this.cache = new Dictionary<string, AssemblyDefinition> (); this.cache = new Dictionary<string, AssemblyDefinition> ();
} }
public string FolderPath {
get; private set;
}
public AssemblyDefinition Resolve(AssemblyNameReference name) public AssemblyDefinition Resolve(AssemblyNameReference name)
{ {
return this.Resolve(name, new ReaderParameters()); return this.Resolve(name, new ReaderParameters());

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

@ -48,29 +48,45 @@ namespace ICSharpCode.ILSpyAddIn
if (string.IsNullOrEmpty(typeName)) if (string.IsNullOrEmpty(typeName))
throw new ArgumentException("typeName is null or empty"); throw new ArgumentException("typeName is null or empty");
foreach (var vc in WorkbenchSingleton.Workbench.ViewContentCollection.OfType<DecompiledViewContent>()) { foreach (var viewContent in WorkbenchSingleton.Workbench.ViewContentCollection.OfType<DecompiledViewContent>()) {
if (string.Equals(vc.AssemblyFile, assemblyFile, StringComparison.OrdinalIgnoreCase) && typeName == vc.FullTypeName) { if (string.Equals(viewContent.AssemblyFile, assemblyFile, StringComparison.OrdinalIgnoreCase) && typeName == viewContent.FullTypeName) {
vc.WorkbenchWindow.SelectWindow(); viewContent.WorkbenchWindow.SelectWindow();
vc.JumpToEntity(entityTag); viewContent.JumpToEntity(entityTag);
return; return;
} }
} }
WorkbenchSingleton.Workbench.ShowView(new DecompiledViewContent(assemblyFile, typeName, entityTag)); 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 if (string.IsNullOrEmpty(assemblyFile))
foreach (var vc in WorkbenchSingleton.Workbench.ViewContentCollection.OfType<DecompiledViewContent>()) { throw new ArgumentException("assemblyFile is null or empty");
if (string.Equals(vc.AssemblyFile, assemblyFile, StringComparison.OrdinalIgnoreCase) && typeName == vc.FullTypeName) {
vc.WorkbenchWindow.CloseWindow(true); if (string.IsNullOrEmpty(typeName))
break; 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); // create a new decompiled view
view.DecompilationFinished += delegate { view.JumpTo(lineNumber); }; var decompiledView = new DecompiledViewContent(assemblyFile, typeName, entityTag);
WorkbenchSingleton.Workbench.ShowView(view); decompiledView.DecompilationFinished += delegate {
if (updateMarker) {
decompiledView.UpdateDebuggingUI();
}
decompiledView.JumpToLineNumber(lineNumber);
};
WorkbenchSingleton.Workbench.ShowView(decompiledView);
return true; return true;
} }
} }

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

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

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

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

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

@ -72,14 +72,14 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
listView.SetValue(Grid.RowProperty, 1); listView.SetValue(Grid.RowProperty, 1);
myPanel.Children.Add(listView); myPanel.Children.Add(listView);
BookmarkManager.Added += new BookmarkEventHandler(BookmarkManagerAdded); BookmarkManager.Added += BookmarkManagerAdded;
BookmarkManager.Removed += new BookmarkEventHandler(BookmarkManagerRemoved); BookmarkManager.Removed += BookmarkManagerRemoved;
foreach (SDBookmark mark in BookmarkManager.Bookmarks) { foreach (SDBookmark mark in BookmarkManager.Bookmarks) {
AddMark(mark); AddMark(mark);
} }
listView.ItemActivated += new EventHandler(listView_ItemActivated); listView.ItemActivated += new EventHandler(OnItemActivated);
} }
public IEnumerable<ListViewPadItemModel> AllItems { public IEnumerable<ListViewPadItemModel> AllItems {
@ -120,6 +120,12 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
listView.CurrentItem = model; listView.CurrentItem = model;
} }
public override void Dispose()
{
BookmarkManager.Added -= BookmarkManagerAdded;
BookmarkManager.Removed -= BookmarkManagerRemoved;
}
void AddMark(SDBookmark mark) void AddMark(SDBookmark mark)
{ {
if (!ShowBookmarkInThisPad(mark)) if (!ShowBookmarkInThisPad(mark))
@ -133,6 +139,17 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
return mark.IsVisibleInBookmarkPad && !(mark is BreakpointBookmark); 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) void BookmarkManagerAdded(object sender, BookmarkEventArgs e)
{ {
AddMark((SDBookmark)e.Bookmark); AddMark((SDBookmark)e.Bookmark);
@ -143,16 +160,5 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
if (ShowBookmarkInThisPad(e.Bookmark)) if (ShowBookmarkInThisPad(e.Bookmark))
listView.Remove(new ListViewPadItemModel(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
/// </summary> /// </summary>
public abstract class AbstractViewContentWithoutFile : AbstractViewContent, ICustomizedCommands 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 { public override bool IsViewOnly {
get { return false; } get { return false; }
} }

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

@ -27,19 +27,6 @@ namespace ICSharpCode.SharpDevelop.Debugging
ITextEditorProvider tecp = viewContent as ITextEditorProvider; ITextEditorProvider tecp = viewContent as ITextEditorProvider;
if (tecp != null) { if (tecp != null) {
SetPosition(tecp.TextEditor.FileName, tecp.TextEditor.Document, markerStartLine, markerStartColumn, markerEndLine, markerEndColumn); 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
/// Gets the local variable index. /// Gets the local variable index.
/// </summary> /// </summary>
object GetLocalVariableIndex(int typeToken, int memberToken, string name); 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
{ {
public class DecompiledBreakpointBookmark : BreakpointBookmark 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) 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.ILFrom = ilFrom;
this.ILTo = ILTo; this.ILTo = ILTo;
} }
@ -25,10 +30,15 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
get; set; get; set;
} }
MemberReference memberReference;
public MemberReference MemberReference { public MemberReference MemberReference {
get { get { return memberReference; }
}
public MemberReference GetMemberReference(IAssemblyResolver resolver)
{
if (resolver == null)
throw new ArgumentNullException("resolver");
if (memberReference != null) if (memberReference != null)
return memberReference; return memberReference;
@ -36,21 +46,36 @@ namespace ICSharpCode.SharpDevelop.Bookmarks
ReaderParameters readerParameters = new ReaderParameters(); ReaderParameters readerParameters = new ReaderParameters();
// Use new assembly resolver instance so that the AssemblyDefinitions can be garbage-collected // Use new assembly resolver instance so that the AssemblyDefinitions can be garbage-collected
// once the code is decompiled. // once the code is decompiled.
readerParameters.AssemblyResolver = new DefaultAssemblyResolver(); readerParameters.AssemblyResolver = resolver;
string fileName = FileName.ToString();
int index = fileName.IndexOf(",");
string assemblyFile = fileName.Substring(0, index);
string fullTypeName = fileName.Substring(index + 1, fileName.Length - index - 1);
string typeName;
if (GetAssemblyAndType(FileName.ToString(), out assemblyFile, out typeName)) {
ModuleDefinition module = ModuleDefinition.ReadModule(assemblyFile, readerParameters); ModuleDefinition module = ModuleDefinition.ReadModule(assemblyFile, readerParameters);
TypeDefinition typeDefinition = module.GetType(fullTypeName); TypeDefinition typeDefinition = module.GetType(typeName);
if (typeDefinition == null) if (typeDefinition == null)
throw new InvalidOperationException("Could not find type"); throw new InvalidOperationException("Could not find type");
memberReference = typeDefinition; memberReference = typeDefinition;
}
return memberReference; 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
bool loggingResumed = false; bool loggingResumed = false;
try { 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); IViewContent content = OpenFile(fileName);
if (content is IPositionable) { if (content is IPositionable) {
// TODO: enable jumping to a particular view // 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;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
using Mono.Cecil;
namespace ICSharpCode.SharpDevelop namespace ICSharpCode.SharpDevelop
{ {
@ -475,7 +474,7 @@ namespace ICSharpCode.SharpDevelop
#region Navigate to Member #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)) if (string.IsNullOrEmpty(assemblyFile))
throw new ArgumentException("assemblyFile is null or empty"); throw new ArgumentException("assemblyFile is null or empty");
@ -484,7 +483,7 @@ namespace ICSharpCode.SharpDevelop
throw new ArgumentException("typeName is null or empty"); throw new ArgumentException("typeName is null or empty");
foreach (var item in AddInTree.BuildItems<INavigateToMemberService>("/SharpDevelop/Services/NavigateToEntityService", null, false)) { 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 true;
} }
return false; return false;
@ -512,6 +511,6 @@ namespace ICSharpCode.SharpDevelop
/// </remarks> /// </remarks>
public interface INavigateToMemberService 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