Browse Source

Merge branch 'newNR' into newNRvisualizers

pull/32/merge
Martin Konicek 13 years ago
parent
commit
b79d0c7075
  1. 15
      src/AddIns/Debugger/Debugger.AddIn/Pads/BreakPointsPad.cs
  2. 117
      src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs
  3. 17
      src/AddIns/Debugger/Debugger.AddIn/TreeModel/ValueNode.cs
  4. 43
      src/AddIns/Debugger/Debugger.Core/Breakpoint.cs
  5. 2
      src/AddIns/Debugger/Debugger.Core/Debugger.Core.csproj
  6. 2
      src/AddIns/Debugger/Debugger.Core/Eval.cs
  7. 5
      src/AddIns/Debugger/Debugger.Core/LocalVariable.cs
  8. 4
      src/AddIns/Debugger/Debugger.Core/Module.cs
  9. 7
      src/AddIns/Debugger/Debugger.Core/NDebugger.cs
  10. 11
      src/AddIns/Debugger/Debugger.Core/Options.cs
  11. 42
      src/AddIns/Debugger/Debugger.Core/PdbSymbolSource.cs
  12. 5
      src/AddIns/Debugger/Debugger.Core/Process.cs
  13. 18
      src/AddIns/Debugger/Debugger.Core/StackFrame.cs
  14. 22
      src/AddIns/Debugger/Debugger.Core/Value.cs
  15. 9
      src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs
  16. 204
      src/AddIns/DisplayBindings/ILSpyAddIn/DebuggerDecompilerService.cs
  17. 11
      src/AddIns/DisplayBindings/ILSpyAddIn/DebuggerTextOutput.cs
  18. 4
      src/AddIns/DisplayBindings/ILSpyAddIn/ILSpyAddIn.addin
  19. 8
      src/AddIns/DisplayBindings/ILSpyAddIn/ILSpyAddIn.csproj
  20. 118
      src/AddIns/DisplayBindings/ILSpyAddIn/ILSpySymbolSource.cs
  21. 41
      src/AddIns/DisplayBindings/ILSpyAddIn/NavigateToDecompiledEntityService.cs
  22. 84
      src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/CodeView.cs
  23. 186
      src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/DecompiledViewContent.cs
  24. 14
      src/AddIns/DisplayBindings/SettingsEditor/Project/SettingsEditor.csproj
  25. 121
      src/AddIns/DisplayBindings/SettingsEditor/Project/SettingsView.Designer.cs
  26. 181
      src/AddIns/DisplayBindings/SettingsEditor/Project/SettingsView.cs
  27. 128
      src/AddIns/DisplayBindings/SettingsEditor/Project/SettingsView.resx
  28. 2
      src/AddIns/DisplayBindings/SettingsEditor/Project/SettingsView.xaml
  29. 11
      src/AddIns/DisplayBindings/SettingsEditor/Project/SettingsView.xaml.cs
  30. 21
      src/AddIns/DisplayBindings/SettingsEditor/Project/SettingsViewContent.cs
  31. 6
      src/Libraries/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  32. 46
      src/Libraries/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs
  33. 231
      src/Libraries/ICSharpCode.Decompiler/CodeMappings.cs
  34. 26
      src/Libraries/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs
  35. 11
      src/Libraries/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  36. 2
      src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs
  37. 52
      src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs
  38. 2
      src/Libraries/ICSharpCode.Decompiler/ITextOutput.cs
  39. 2
      src/Libraries/ICSharpCode.Decompiler/PlainTextOutput.cs
  40. 5
      src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs
  41. 1
      src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj
  42. 10
      src/Main/Base/Project/Src/Services/Debugger/CurrentLineBookmark.cs
  43. 51
      src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs
  44. 73
      src/Main/Base/Project/Src/Services/Debugger/DecompiledBreakpointBookmark.cs

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

@ -28,20 +28,5 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -28,20 +28,5 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
{
return mark.IsVisibleInBookmarkPad && mark is BreakpointBookmark;
}
/*
protected override void OnItemActivated(SDBookmark bookmark)
{
if (bookmark is DecompiledBreakpointBookmark) {
// get information from breakpoint and navigate to the decompiled type
string assemblyFile, typeName;
if (DecompiledBreakpointBookmark.GetAssemblyAndType(bookmark.FileName, out assemblyFile, out typeName)) {
NavigationService.NavigateTo(assemblyFile, typeName, string.Empty, bookmark.LineNumber, false);
}
throw new NotImplementedException();
} else {
base.OnItemActivated(bookmark);
}
}*/
}
}

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

@ -2,34 +2,25 @@ @@ -2,34 +2,25 @@
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Windows.Forms;
using Debugger;
using Debugger.AddIn;
using Debugger.AddIn.Tooltips;
using Debugger.AddIn.TreeModel;
using Debugger.Interop.CorPublish;
using Debugger.MetaData;
using ICSharpCode.Core;
using ICSharpCode.Core.WinForms;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.SharpDevelop.Editor.Bookmarks;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Gui.OptionPanels;
using ICSharpCode.SharpDevelop.Project;
using Mono.Cecil;
using Process = Debugger.Process;
using StackFrame = Debugger.StackFrame;
using TreeNode = Debugger.AddIn.TreeModel.TreeNode;
@ -87,7 +78,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -87,7 +78,7 @@ namespace ICSharpCode.SharpDevelop.Services
ICorPublish corPublish;
internal IDebuggerDecompilerService debuggerDecompilerService;
List<ISymbolSource> symbolSources = new List<ISymbolSource>();
/// <inheritdoc/>
public bool BreakAtBeginning { get; set; }
@ -357,8 +348,8 @@ namespace ICSharpCode.SharpDevelop.Services @@ -357,8 +348,8 @@ namespace ICSharpCode.SharpDevelop.Services
public void InitializeService()
{
// get decompiler service
debuggerDecompilerService = SD.GetService<IDebuggerDecompilerService>();
symbolSources.Add(new PdbSymbolSource());
symbolSources.AddRange(AddInTree.BuildItems<ISymbolSource>("/SharpDevelop/Services/DebuggerService/SymbolSource", null, false));
// init NDebugger
CurrentDebugger = new NDebugger();
@ -407,44 +398,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -407,44 +398,7 @@ namespace ICSharpCode.SharpDevelop.Services
void AddBreakpoint(BreakpointBookmark bookmark)
{
Breakpoint breakpoint = null;
#warning decompiler
/*if (bookmark is DecompiledBreakpointBookmark) {
try {
if (debuggerDecompilerService == null) {
LoggingService.Warn("No IDebuggerDecompilerService found!");
return;
}
var dbb = (DecompiledBreakpointBookmark)bookmark;
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);
int[] ilRanges;
int methodToken;
// if (debuggerDecompilerService.GetILAndTokenByLineNumber(token, dbb.LineNumber, out ilRanges, out methodToken)) {
// CurrentDebugger.AddILBreakpoint(memberReference.FullName, dbb.LineNumber, memberReference.MetadataToken.ToInt32(), methodToken, ilRanges[0], dbb.IsEnabled);
// }
} catch (System.Exception ex) {
LoggingService.Error("Error on DecompiledBreakpointBookmark: " + ex.Message);
}
} else {*/
breakpoint = CurrentDebugger.AddBreakpoint(bookmark.FileName, bookmark.LineNumber, 0, bookmark.IsEnabled);
//}
if (breakpoint == null) {
LoggingService.Warn(string.Format("unable to create breakpoint: {0}", bookmark.ToString()));
return;
}
Breakpoint breakpoint = CurrentDebugger.AddBreakpoint(bookmark.FileName, bookmark.LineNumber, 0, bookmark.IsEnabled);
bookmark.InternalBreakpointObject = breakpoint;
bookmark.IsHealthy = (CurrentProcess == null) || breakpoint.IsSet;
bookmark.IsEnabledChanged += delegate { breakpoint.IsEnabled = bookmark.IsEnabled; };
@ -512,6 +466,10 @@ namespace ICSharpCode.SharpDevelop.Services @@ -512,6 +466,10 @@ namespace ICSharpCode.SharpDevelop.Services
CurrentThread = e.Thread;
CurrentStackFrame = CurrentThread != null ? CurrentThread.MostRecentUserStackFrame : null;
// Select the symbol source
var symbolSource = symbolSources.FirstOrDefault(s => CurrentStackFrame == null || s.HasSymbols(CurrentStackFrame.MethodInfo));
CurrentProcess.SymbolSource = symbolSource ?? symbolSources.First();
// We can have several events happening at the same time
bool breakProcess = e.Break;
@ -642,73 +600,14 @@ namespace ICSharpCode.SharpDevelop.Services @@ -642,73 +600,14 @@ namespace ICSharpCode.SharpDevelop.Services
SD.Workbench.MainWindow.Activate();
// if (debuggedProcess.IsSelectedFrameForced()) {
if (CurrentStackFrame.HasSymbols) {
SequencePoint nextStatement = CurrentStackFrame.NextStatement;
if (nextStatement != null) {
DebuggerService.RemoveCurrentLineMarker();
DebuggerService.JumpToCurrentLine(nextStatement.Filename, nextStatement.StartLine, nextStatement.StartColumn, nextStatement.EndLine, nextStatement.EndColumn);
}
} else {
#warning JumpToDecompiledCode(CurrentStackFrame);
}
// } else {
// var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
// // other pause reasons
// if (frame != null && frame.HasSymbols) {
// JumpToSourceCode();
// } else {
// // use most recent stack frame because we don't have the symbols
// JumpToDecompiledCode(debuggedProcess.SelectedThread.MostRecentStackFrame);
// }
// }
}
/*
void JumpToDecompiledCode(Debugger.StackFrame frame)
{
if (frame == null) {
LoggingService.Error("No stack frame!");
return;
}
if (debuggerDecompilerService == null) {
LoggingService.Warn("No IDebuggerDecompilerService found!");
return;
}
// check for options - if these options are enabled, debugging decompiled code should not continue
if (!CurrentProcess.Options.DecompileCodeWithoutSymbols) {
LoggingService.Info("Decompiled code debugging is disabled!");
return;
}
DebuggerService.RemoveCurrentLineMarker();
// 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;
var debugType = (DebugType)frame.MethodInfo.DeclaringType;
debuggerDecompilerService.DebugStepInformation = Tuple.Create(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,
IDStringProvider.GetIDString(frame.MethodInfo),
line);
} else
{
// no line => do decompilation
NavigationService.NavigateTo(debugType.DebugModule.FullPath,
debugType.FullNameWithoutGenericArguments,
IDStringProvider.GetIDString(frame.MethodInfo));
}
}
*/
StopAttachedProcessDialogResult ShowStopAttachedProcessDialog()
{

17
src/AddIns/Debugger/Debugger.AddIn/TreeModel/ValueNode.cs

@ -256,23 +256,6 @@ namespace Debugger.AddIn.TreeModel @@ -256,23 +256,6 @@ namespace Debugger.AddIn.TreeModel
}
} else {
WindowsDebugger debugger = (WindowsDebugger)DebuggerService.CurrentDebugger;
#warning decompiler
/*
if (debugger.debuggerDecompilerService != null) {
int typeToken = stackFrame.MethodInfo.DeclaringType.MetadataToken;
int methodToken = stackFrame.MethodInfo.MetadataToken;
foreach (var localVar in debugger.debuggerDecompilerService.GetLocalVariables(typeToken, methodToken)) {
int index = ((int[])debugger.debuggerDecompilerService.GetLocalVariableIndex(typeToken, methodToken, localVar))[0];
yield return new ValueNode("Icons.16x16.Local", localVar, () => {
var newStackFrame = GetCurrentStackFrame();
if (newStackFrame.MethodInfo != stackFrame.MethodInfo)
throw new GetValueException("Expected stack frame: " + stackFrame.MethodInfo.ToString());
return newStackFrame.GetLocalVariableValue((uint)index);
});
}
}
*/
}
}

43
src/AddIns/Debugger/Debugger.Core/Breakpoint.cs

@ -69,7 +69,7 @@ namespace Debugger @@ -69,7 +69,7 @@ namespace Debugger
public virtual bool SetBreakpoint(Module module)
{
var seq = PDBSymbolSource.GetSequencePoint(module, this.FileName, this.Line, this.Column);
var seq = module.SymbolSource.GetSequencePoint(module, this.FileName, this.Line, this.Column);
if (seq != null) {
ICorDebugFunction corFuction = module.CorModule.GetFunctionFromToken(seq.MethodDefToken);
ICorDebugFunctionBreakpoint corBreakpoint = corFuction.GetILCode().CreateBreakpoint((uint)seq.ILOffset);
@ -80,45 +80,4 @@ namespace Debugger @@ -80,45 +80,4 @@ namespace Debugger
return false;
}
}
/*
public class ILBreakpoint : Breakpoint
{
public ILBreakpoint(string typeName, int line, int metadataToken, int memberToken, int offset, bool enabled)
: base(null, line, 0, enabled)
{
this.TypeName = typeName;
this.MetadataToken = metadataToken;
this.MemberMetadataToken = memberToken;
this.ILOffset = offset;
this.IsEnabled = enabled;
}
public int MetadataToken { get; private set; }
public int MemberMetadataToken { get; private set; }
public int ILOffset { get; private set; }
public override bool SetBreakpoint(Module module)
{
var currentModuleTypes = module.GetNamesOfDefinedTypes();
// set the breakpoint only if the module contains the type
if (!currentModuleTypes.Contains(this.TypeName))
return false;
SourcecodeSegment segment = SourcecodeSegment.CreateForIL(module, this.Line, MemberMetadataToken, ILOffset);
if (segment == null)
return false;
try {
ICorDebugFunctionBreakpoint corBreakpoint = segment.CorFunction.GetILCode().CreateBreakpoint((uint)segment.ILStart);
corBreakpoint.Activate(this.IsEnabled ? 1 : 0);
corBreakpoints.Add(corBreakpoint);
return true;
} catch {
return false;
}
}
}
*/
}

2
src/AddIns/Debugger/Debugger.Core/Debugger.Core.csproj

@ -88,7 +88,7 @@ @@ -88,7 +88,7 @@
<Compile Include="NDebugger.cs" />
<Compile Include="Options.cs" />
<Compile Include="Process.cs" />
<Compile Include="PDBSymbolSource.cs" />
<Compile Include="PdbSymbolSource.cs" />
<Compile Include="StackFrame.cs" />
<Compile Include="Stepper.cs" />
<Compile Include="Thread.cs" />

2
src/AddIns/Debugger/Debugger.Core/Eval.cs

@ -62,7 +62,7 @@ namespace Debugger @@ -62,7 +62,7 @@ namespace Debugger
case EvalState.Evaluating: throw new GetValueException("Evaluating...");
case EvalState.EvaluatedSuccessfully: return result;
case EvalState.EvaluatedException: return result;
case EvalState.EvaluatedNoResult: return null;
case EvalState.EvaluatedNoResult: throw new DebuggerException("Evaluation did not return any value.");
case EvalState.EvaluatedTimeOut: throw new GetValueException("Timeout");
default: throw new DebuggerException("Unknown state");
}

5
src/AddIns/Debugger/Debugger.Core/LocalVariable.cs

@ -51,12 +51,13 @@ namespace Debugger.MetaData @@ -51,12 +51,13 @@ namespace Debugger.MetaData
public static List<LocalVariable> GetLocalVariables(IMethod method)
{
if (!PDBSymbolSource.HasSymbols(method))
var module = method.ParentAssembly.GetModule();
if (!module.SymbolSource.HasSymbols(method))
return null;
List<LocalVariable> localVariables = new List<LocalVariable>();
foreach (ILLocalVariable ilvar in PDBSymbolSource.GetLocalVariables(method)) {
foreach (ILLocalVariable ilvar in module.SymbolSource.GetLocalVariables(method)) {
int index = ilvar.Index;
// NB: Display class does not have the compiler-generated flag
if (ilvar.IsCompilerGenerated || ilvar.Name.StartsWith("CS$")) {

4
src/AddIns/Debugger/Debugger.Core/Module.cs

@ -46,6 +46,10 @@ namespace Debugger @@ -46,6 +46,10 @@ namespace Debugger
get { return process; }
}
public ISymbolSource SymbolSource {
get { return this.Process.SymbolSource; }
}
NDebugger Debugger {
get { return this.AppDomain.Process.Debugger; }
}

7
src/AddIns/Debugger/Debugger.Core/NDebugger.cs

@ -170,13 +170,6 @@ namespace Debugger @@ -170,13 +170,6 @@ namespace Debugger
return breakpoint;
}
// public ILBreakpoint AddILBreakpoint(string typeName, int line, int metadataToken, int memberToken, int offset, bool enabled)
// {
// ILBreakpoint breakpoint = new ILBreakpoint(typeName, line, metadataToken, memberToken, offset, enabled);
// AddBreakpoint(breakpoint);
// return breakpoint;
// }
void AddBreakpoint(Breakpoint breakpoint)
{
this.breakpoints.Add(breakpoint);

11
src/AddIns/Debugger/Debugger.Core/Options.cs

@ -6,17 +6,6 @@ namespace Debugger @@ -6,17 +6,6 @@ namespace Debugger
{
public class Options
{
public Options()
{
EnableJustMyCode = true;
StepOverNoSymbols = true;
StepOverDebuggerAttributes = true;
StepOverAllProperties = false;
StepOverFieldAccessProperties = true;
SymbolsSearchPaths = new string[0];
PauseOnHandledExceptions = false;
}
public virtual bool EnableJustMyCode { get; set; }
public virtual bool StepOverNoSymbols { get; set; }
public virtual bool StepOverDebuggerAttributes { get; set; }

42
src/AddIns/Debugger/Debugger.Core/PdbSymbolSource.cs

@ -45,6 +45,11 @@ namespace Debugger @@ -45,6 +45,11 @@ namespace Debugger
this.From = from;
this.To = to;
}
public override string ToString()
{
return string.Format("{0:X2}-{1:X2}", From, To);
}
}
public class ILLocalVariable
@ -56,7 +61,25 @@ namespace Debugger @@ -56,7 +61,25 @@ namespace Debugger
public ILRange[] ILRanges { get; set; }
}
public class PDBSymbolSource
public interface ISymbolSource
{
/// <summary> Find sequence point by IL offset </summary>
SequencePoint GetSequencePoint(IMethod method, int iloffset);
/// <summary> Find sequence point by source code location </summary>
SequencePoint GetSequencePoint(Module module, string filename, int line, int column);
/// <summary> Determine whether the method is debugable </summary>
bool HasSymbols(IMethod method);
/// <summary> Get IL ranges that should be always stepped over by the debugger </summary>
IEnumerable<ILRange> GetIgnoredILRanges(IMethod method);
/// <summary> Get local variable metadata </summary>
IEnumerable<ILLocalVariable> GetLocalVariables(IMethod method);
}
public class PdbSymbolSource : ISymbolSource
{
/// <summary>
/// Get absolute source code path for the specified document.
@ -118,7 +141,7 @@ namespace Debugger @@ -118,7 +141,7 @@ namespace Debugger
}
}
public static SequencePoint GetSequencePoint(IMethod method, int iloffset)
public SequencePoint GetSequencePoint(IMethod method, int iloffset)
{
var symMethod = method.GetSymMethod();
if (symMethod == null)
@ -149,14 +172,11 @@ namespace Debugger @@ -149,14 +172,11 @@ namespace Debugger
return sequencePoint;
}
public static SequencePoint GetSequencePoint(Module module, string filename, int line, int column)
public SequencePoint GetSequencePoint(Module module, string filename, int line, int column)
{
// Do not use ISymUnmanagedReader.GetDocument! It is broken if two files have the same name
// Do not use ISymUnmanagedMethod.GetOffset! It sometimes returns negative offset
if (filename == null || !Path.IsPathRooted(filename))
throw new DebuggerException("Invalid filename. Absolute path is required.");
ISymUnmanagedReader symReader = module.SymReader;
if (symReader == null)
return null; // No symbols
@ -181,9 +201,7 @@ namespace Debugger @@ -181,9 +201,7 @@ namespace Debugger
int codesize = (int)corFunction.GetILCode().GetSize();
var seqPoints = symMethod.GetSequencePoints(codesize).Where(s => s.StartLine != 0xFEEFEE);
SequencePoint seqPoint = null;
if (column == 0) {
seqPoint = seqPoints.FirstOrDefault(s => s.StartLine <= line && line <= s.EndLine);
} else {
if (column != 0) {
seqPoint = seqPoints.FirstOrDefault(s => (s.StartLine < line || (s.StartLine == line && s.StartColumn <= column)) &&
(line < s.EndLine || (line == s.EndLine && column <= s.EndColumn)));
}
@ -191,12 +209,12 @@ namespace Debugger @@ -191,12 +209,12 @@ namespace Debugger
return seqPoint;
}
public static bool HasSymbols(IMethod method)
public bool HasSymbols(IMethod method)
{
return method.GetSymMethod() != null;
}
public static IEnumerable<ILRange> GetIgnoredILRanges(IMethod method)
public IEnumerable<ILRange> GetIgnoredILRanges(IMethod method)
{
var symMethod = method.GetSymMethod();
if (symMethod == null)
@ -206,7 +224,7 @@ namespace Debugger @@ -206,7 +224,7 @@ namespace Debugger
return symMethod.GetSequencePoints(codeSize).Where(p => p.StartLine == 0xFEEFEE).SelectMany(p => p.ILRanges).ToList();
}
public static IEnumerable<ILLocalVariable> GetLocalVariables(IMethod method)
public IEnumerable<ILLocalVariable> GetLocalVariables(IMethod method)
{
var symMethod = method.GetSymMethod();
if (symMethod == null)

5
src/AddIns/Debugger/Debugger.Core/Process.cs

@ -107,6 +107,8 @@ namespace Debugger @@ -107,6 +107,8 @@ namespace Debugger
public string Filename { get; private set; }
public ISymbolSource SymbolSource { get; set; }
public static DebugModeFlag DebugMode { get; set; }
internal Process(NDebugger debugger, ICorDebugProcess corProcess, string filename, string workingDirectory)
@ -115,6 +117,7 @@ namespace Debugger @@ -115,6 +117,7 @@ namespace Debugger
this.corProcess = corProcess;
this.workingDirectory = workingDirectory;
this.Filename = System.IO.Path.GetFullPath(filename); // normalize path
this.SymbolSource = new PdbSymbolSource();
this.callbackInterface = new ManagedCallback(this);
}
@ -452,7 +455,7 @@ namespace Debugger @@ -452,7 +455,7 @@ namespace Debugger
public void RunTo(string fileName, int line, int column)
{
foreach(Module module in this.Modules) {
SequencePoint seq = PDBSymbolSource.GetSequencePoint(module, fileName, line, column);
SequencePoint seq = this.SymbolSource.GetSequencePoint(module, fileName, line, column);
if (seq != null) {
ICorDebugFunction corFunction = module.CorModule.GetFunctionFromToken(seq.MethodDefToken);
ICorDebugFunctionBreakpoint corBreakpoint = corFunction.GetILCode().CreateBreakpoint((uint)seq.ILOffset);

18
src/AddIns/Debugger/Debugger.Core/StackFrame.cs

@ -46,7 +46,7 @@ namespace Debugger @@ -46,7 +46,7 @@ namespace Debugger
/// <summary> True if the stack frame has symbols defined. </summary>
public bool HasSymbols {
get {
return PDBSymbolSource.HasSymbols(this.MethodInfo);
return this.Module.SymbolSource.HasSymbols(this.MethodInfo);
}
}
@ -154,10 +154,11 @@ namespace Debugger @@ -154,10 +154,11 @@ namespace Debugger
void AsyncStep(bool stepIn)
{
List<ILRange> stepRanges = new List<ILRange>();
var seq = PDBSymbolSource.GetSequencePoint(this.MethodInfo, this.IP);
var seq = this.Module.SymbolSource.GetSequencePoint(this.MethodInfo, this.IP);
if (seq != null) {
Process.TraceMessage("Step over: {0} IL:{1}", seq, string.Join(" ", seq.ILRanges));
stepRanges.AddRange(seq.ILRanges);
stepRanges.AddRange(PDBSymbolSource.GetIgnoredILRanges(this.MethodInfo));
stepRanges.AddRange(this.Module.SymbolSource.GetIgnoredILRanges(this.MethodInfo));
}
// Remove overlapping and connected ranges
@ -195,7 +196,7 @@ namespace Debugger @@ -195,7 +196,7 @@ namespace Debugger
/// </summary>
public SequencePoint NextStatement {
get {
return PDBSymbolSource.GetSequencePoint(this.MethodInfo, this.IP);
return this.Module.SymbolSource.GetSequencePoint(this.MethodInfo, this.IP);
}
}
@ -203,7 +204,7 @@ namespace Debugger @@ -203,7 +204,7 @@ namespace Debugger
{
this.Process.AssertPaused();
var seq = PDBSymbolSource.GetSequencePoint(this.Module, filename, line, column);
var seq = this.Module.SymbolSource.GetSequencePoint(this.Module, filename, line, column);
if (seq != null && seq.MethodDefToken == this.MethodInfo.GetMetadataToken()) {
try {
if (dryRun) {
@ -232,7 +233,7 @@ namespace Debugger @@ -232,7 +233,7 @@ namespace Debugger
if (loc.IsThis)
return loc.GetValue(this);
}
return null;
throw new GetValueException("The current method does not have 'this'.");
} else {
return new Value(this.AppDomain, GetThisCorValue());
}
@ -240,7 +241,8 @@ namespace Debugger @@ -240,7 +241,8 @@ namespace Debugger
ICorDebugValue GetThisCorValue()
{
if (this.MethodInfo.IsStatic) throw new GetValueException("Static method does not have 'this'.");
if (this.MethodInfo.IsStatic)
throw new GetValueException("Static method does not have 'this'.");
ICorDebugValue corValue;
try {
corValue = CorILFrame.GetArgument(0);
@ -347,7 +349,7 @@ namespace Debugger @@ -347,7 +349,7 @@ namespace Debugger
Options opt = this.Process.Options;
if (opt.StepOverNoSymbols) {
if (!PDBSymbolSource.HasSymbols(this.MethodInfo)) return true;
if (!this.Module.SymbolSource.HasSymbols(this.MethodInfo)) return true;
}
if (opt.StepOverDebuggerAttributes) {
string[] debuggerAttributes = {

22
src/AddIns/Debugger/Debugger.Core/Value.cs

@ -14,6 +14,10 @@ namespace Debugger @@ -14,6 +14,10 @@ namespace Debugger
{
public delegate Value ValueGetter(StackFrame context);
/// <summary>
/// Thrown when Value can not be obtained.
/// Methods should throw this exception instead of returning null.
/// </summary>
public class GetValueException: DebuggerException
{
public GetValueException(string error) : base(error) {}
@ -240,13 +244,13 @@ namespace Debugger @@ -240,13 +244,13 @@ namespace Debugger
}
/// <summary> Dereferences a pointer type </summary>
/// <returns> Returns null for a null pointer </returns>
public Value Dereference()
{
if (this.Type.Kind != TypeKind.Pointer) throw new DebuggerException("Not a pointer");
if (this.Type.Kind != TypeKind.Pointer)
throw new DebuggerException("Not a pointer");
ICorDebugReferenceValue corRef = (ICorDebugReferenceValue)this.CorValue;
if (corRef.GetValue() == 0 || corRef.Dereference() == null) {
return null;
throw new GetValueException("Null pointer");
} else {
return new Value(this.AppDomain, corRef.Dereference());
}
@ -394,18 +398,6 @@ namespace Debugger @@ -394,18 +398,6 @@ namespace Debugger
}
}
/*
/// <summary> Get a field or property of an object with a given name. </summary>
/// <returns> Null if not found </returns>
public Value GetMemberValue(Thread evalThread, string name)
{
MemberInfo memberInfo = this.Type.GetMembers(m => m.Name == name && (m.IsFieldOrNonIndexedProperty), GetMemberOptions.None);
if (memberInfo == null)
return null;
return GetMemberValue(evalThread, memberInfo);
}
*/
/// <summary> Get the value of given member. </summary>
public Value GetMemberValue(Thread evalThread, IMember memberInfo, params Value[] arguments)
{

9
src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs

@ -200,6 +200,15 @@ namespace Debugger.Tests @@ -200,6 +200,15 @@ namespace Debugger.Tests
testNode.SetAttribute("name", testName);
shapshotID = 0;
debugger.Options = new Options();
debugger.Options.EnableJustMyCode = true;
debugger.Options.StepOverNoSymbols = true;
debugger.Options.StepOverDebuggerAttributes = true;
debugger.Options.StepOverAllProperties = false;
debugger.Options.StepOverFieldAccessProperties = true;
debugger.Options.SymbolsSearchPaths = new string[0];
debugger.Options.PauseOnHandledExceptions = false;
log = "";
lastLogMessage = null;
process = debugger.Start(exeFilename, Path.GetDirectoryName(exeFilename), testName, false);

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

@ -1,204 +0,0 @@ @@ -1,204 +0,0 @@
// 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.IO;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.Decompiler.ILAst;
using ICSharpCode.ILSpyAddIn.LaunchILSpy;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Project;
using Mono.Cecil;
namespace ICSharpCode.ILSpyAddIn
{
/*
// Dummy class to avoid the build errors after updating the ICSharpCode.Decompiler version.
// TODO: get rid of this & fix debugging decompiled files
public class DecompileInformation {
public dynamic LocalVariables;
public dynamic CodeMappings;
}
/// <summary>
/// Stores the decompilation information.
/// </summary>
public class DebuggerDecompilerService : IDebuggerDecompilerService
{
ILSpyAssemblyResolver resolver;
static DebuggerDecompilerService()
{
DebugInformation = new ConcurrentDictionary<int, DecompileInformation>();
ProjectService.SolutionClosed += delegate {
DebugInformation.Clear();
GC.Collect();
};
}
internal static IDebuggerDecompilerService Instance { get; private set; }
/// <summary>
/// Gets or sets the external debug information.
/// <summary>This constains the code mappings and local variables.</summary>
/// </summary>
internal static ConcurrentDictionary<int, DecompileInformation> DebugInformation { get; private set; }
public DebuggerDecompilerService()
{
Instance = this;
}
public Tuple<int, int> DebugStepInformation { get; set; }
public bool CheckMappings(int typeToken)
{
DecompileInformation data = null;
DebugInformation.TryGetValue(typeToken, out data);
DecompileInformation information = data as DecompileInformation;
if (information == null)
return false;
if (information.CodeMappings == null)
return false;
return true;
}
public void DecompileOnDemand(TypeDefinition type)
{
if (type == null)
return;
if (CheckMappings(type.MetadataToken.ToInt32()))
return;
try {
DecompilerContext context = new DecompilerContext(type.Module);
AstBuilder astBuilder = new AstBuilder(context);
astBuilder.AddType(type);
DebuggerTextOutput output = new DebuggerTextOutput(new PlainTextOutput());
astBuilder.GenerateCode(output);
// int token = type.MetadataToken.ToInt32();
// var info = new DecompileInformation {
// CodeMappings = astBuilder.CodeMappings,
// LocalVariables = astBuilder.LocalVariables,
// DecompiledMemberReferences = astBuilder.DecompiledMemberReferences
// };
//
// // save the data
// DebugInformation.AddOrUpdate(token, info, (k, v) => info);
} catch {
return;
}
}
public bool GetILAndTokenByLineNumber(int typeToken, int lineNumber, out int[] ilRanges, out int memberToken)
{
ilRanges = null;
memberToken = -1;
if (!CheckMappings(typeToken))
return false;
var data = (DecompileInformation)DebugInformation[typeToken];
var mappings = data.CodeMappings;
foreach (var key in mappings.Keys) {
var list = mappings[key];
var instruction = list.GetInstructionByLineNumber(lineNumber, out memberToken);
if (instruction == null)
continue;
ilRanges = new int[] { instruction.ILInstructionOffset.From, instruction.ILInstructionOffset.To };
memberToken = instruction.MemberMapping.MetadataToken;
return true;
}
return false;
}
public bool GetILAndLineNumber(int typeToken, int memberToken, int ilOffset, out int[] ilRange, out int line, out bool isMatch)
{
ilRange = null;
line = -1;
isMatch = false;
if (!CheckMappings(typeToken))
return false;
var data = (DecompileInformation)DebugInformation[typeToken];
var mappings = data.CodeMappings;
if (!mappings.ContainsKey(memberToken))
return false;
var map = mappings[memberToken].GetInstructionByTokenAndOffset(memberToken, ilOffset, out isMatch);
if (map != null) {
ilRange = map.ToArray(isMatch);
line = map.SourceCodeLine;
return true;
}
return false;
}
public IEnumerable<string> GetLocalVariables(int typeToken, int memberToken)
{
if (DebugInformation == null || !DebugInformation.ContainsKey(typeToken))
yield break;
var externalData = DebugInformation[typeToken];
IEnumerable<ILVariable> list;
if (externalData.LocalVariables.TryGetValue(memberToken, out list)) {
foreach (var local in list) {
if (local.IsParameter)
continue;
if (string.IsNullOrEmpty(local.Name))
continue;
yield return local.Name;
}
}
}
public object GetLocalVariableIndex(int typeToken, int memberToken, string name)
{
if (DebugInformation == null || !DebugInformation.ContainsKey(typeToken))
return null;
var externalData = DebugInformation[typeToken];
IEnumerable<ILVariable> list;
if (externalData.LocalVariables.TryGetValue(memberToken, out list)) {
foreach (var local in list) {
if (local.IsParameter)
continue;
if (local.Name == name)
return new[] { local.OriginalVariable.Index };
}
}
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;
}
}
*/
}

11
src/AddIns/DisplayBindings/ILSpyAddIn/DebuggerTextOutput.cs

@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.Core;
using ICSharpCode.Decompiler;
using Mono.Cecil;
@ -13,7 +14,7 @@ namespace ICSharpCode.ILSpyAddIn @@ -13,7 +14,7 @@ namespace ICSharpCode.ILSpyAddIn
{
readonly ITextOutput output;
public readonly List<MemberMapping> DebuggerMemberMappings = new List<MemberMapping>();
public readonly Dictionary<string, MethodDebugSymbols> DebugSymbols = new Dictionary<string, MethodDebugSymbols>();
public readonly Dictionary<string, ICSharpCode.NRefactory.TextLocation> MemberLocations = new Dictionary<string, ICSharpCode.NRefactory.TextLocation>();
public DebuggerTextOutput(ITextOutput output)
@ -63,10 +64,12 @@ namespace ICSharpCode.ILSpyAddIn @@ -63,10 +64,12 @@ namespace ICSharpCode.ILSpyAddIn
output.WriteReference(text, reference, isLocal);
}
public void AddDebuggerMemberMapping(MemberMapping memberMapping)
public void AddDebugSymbols(MethodDebugSymbols methodDebugSymbols)
{
DebuggerMemberMappings.Add(memberMapping);
output.AddDebuggerMemberMapping(memberMapping);
var id = XmlDocKeyProvider.GetKey(methodDebugSymbols.CecilMethod);
methodDebugSymbols.SequencePoints = methodDebugSymbols.SequencePoints.OrderBy(s => s.ILOffset).ToList();
this.DebugSymbols.Add(id, methodDebugSymbols);
output.AddDebugSymbols(methodDebugSymbols);
}
public void MarkFoldStart(string collapsedText, bool defaultCollapsed)

4
src/AddIns/DisplayBindings/ILSpyAddIn/ILSpyAddIn.addin

@ -12,6 +12,10 @@ @@ -12,6 +12,10 @@
<Import assembly = "ILSpyAddIn.dll"/>
</Runtime>
<Path name="/SharpDevelop/Services/DebuggerService/SymbolSource">
<Class id="ILSpy" class="ICSharpCode.ILSpyAddIn.ILSpySymbolSource"/>
</Path>
<Path name="/SharpDevelop/Services/NavigateToEntityService">
<Class id="ILSpy" class="ICSharpCode.ILSpyAddIn.NavigateToDecompiledEntityService"/>
</Path>

8
src/AddIns/DisplayBindings/ILSpyAddIn/ILSpyAddIn.csproj

@ -52,6 +52,7 @@ @@ -52,6 +52,7 @@
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Linq" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
@ -64,8 +65,8 @@ @@ -64,8 +65,8 @@
<Compile Include="..\..\..\Main\GlobalAssemblyInfo.cs">
<Link>Properties\GlobalAssemblyInfo.cs</Link>
</Compile>
<Compile Include="DebuggerDecompilerService.cs" />
<Compile Include="DebuggerTextOutput.cs" />
<Compile Include="ILSpySymbolSource.cs" />
<Compile Include="LaunchILSpy\ILSpyAssemblyResolver.cs" />
<Compile Include="NavigateToDecompiledEntityService.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
@ -75,7 +76,6 @@ @@ -75,7 +76,6 @@
<DependentUpon>SetILSpyPathDialog.cs</DependentUpon>
</Compile>
<Compile Include="LaunchILSpy\OpenInILSpyCommand.cs" />
<Compile Include="ViewContent\CodeView.cs" />
<Compile Include="ViewContent\DecompiledViewContent.cs" />
<EmbeddedResource Include="LaunchILSpy\SetILSpyPathDialog.resx">
<DependentUpon>SetILSpyPathDialog.cs</DependentUpon>
@ -119,6 +119,10 @@ @@ -119,6 +119,10 @@
<Name>ICSharpCode.Core</Name>
<Private>False</Private>
</ProjectReference>
<ProjectReference Include="..\..\Debugger\Debugger.Core\Debugger.Core.csproj">
<Project>{1D18D788-F7EE-4585-A23B-34DC8EC63CB8}</Project>
<Name>Debugger.Core</Name>
</ProjectReference>
<ProjectReference Include="..\AvalonEdit.AddIn\AvalonEdit.AddIn.csproj">
<Project>{0162E499-42D0-409B-AA25-EED21F75336B}</Project>
<Name>AvalonEdit.AddIn</Name>

118
src/AddIns/DisplayBindings/ILSpyAddIn/ILSpySymbolSource.cs

@ -0,0 +1,118 @@ @@ -0,0 +1,118 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Debugger;
using ICSharpCode.Core;
using ICSharpCode.Decompiler;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Documentation;
using ICSharpCode.NRefactory.TypeSystem;
namespace ICSharpCode.ILSpyAddIn
{
public class ILSpySymbolSource : ISymbolSource
{
public static MethodDebugSymbols GetSymbols(IMethod method)
{
// Use the non-specialised method definition to look up decompiled symbols
var id = IdStringProvider.GetIdString(method.MemberDefinition);
var content = DecompiledViewContent.Get(method);
if (content != null && content.DebugSymbols.ContainsKey(id)) {
return content.DebugSymbols[id];
}
return null;
}
public Debugger.SequencePoint GetSequencePoint(IMethod method, int iloffset)
{
var symbols = GetSymbols(method);
if (symbols == null)
return null;
var content = DecompiledViewContent.Get(method);
var seqs = symbols.SequencePoints;
var seq = seqs.FirstOrDefault(p => p.ILRanges.Any(r => r.From <= iloffset && iloffset < r.To));
if (seq == null)
seq = seqs.FirstOrDefault(p => iloffset <= p.ILOffset);
if (seq != null) {
// Use the widest sequence point containing the IL offset
iloffset = seq.ILOffset;
seq = seqs.Where(p => p.ILRanges.Any(r => r.From <= iloffset && iloffset < r.To))
.OrderByDescending(p => p.ILRanges.Last().To - p.ILRanges.First().From)
.FirstOrDefault();
return seq.ToDebugger(symbols, content.VirtualFileName);
}
return null;
}
public Debugger.SequencePoint GetSequencePoint(Module module, string filename, int line, int column)
{
var content = DecompiledViewContent.Get(new FileName(filename));
if (content == null)
return null;
if (!FileUtility.IsEqualFileName(module.FullPath, content.AssemblyFile))
return null;
TextLocation loc = new TextLocation(line, column);
foreach(var symbols in content.DebugSymbols.Values.Where(s => s.StartLocation <= loc && loc <= s.EndLocation)) {
Decompiler.SequencePoint seq = null;
if (column != 0)
seq = symbols.SequencePoints.FirstOrDefault(p => p.StartLocation <= loc && loc <= p.EndLocation);
if (seq == null)
seq = symbols.SequencePoints.FirstOrDefault(p => line <= p.StartLocation.Line);
if (seq != null)
return seq.ToDebugger(symbols, content.VirtualFileName);
}
return null;
}
public bool HasSymbols(IMethod method)
{
var symbols = GetSymbols(method);
return symbols != null && symbols.SequencePoints.Any();
}
public IEnumerable<ILRange> GetIgnoredILRanges(IMethod method)
{
var symbols = GetSymbols(method);
if (symbols == null)
return new ILRange[] { };
int codesize = symbols.CecilMethod.Body.CodeSize;
var inv = ICSharpCode.Decompiler.ILAst.ILRange.Invert(symbols.SequencePoints.SelectMany(s => s.ILRanges), codesize);
return inv.Select(r => new ILRange(r.From, r.To));
}
public IEnumerable<ILLocalVariable> GetLocalVariables(IMethod method)
{
var symbols = GetSymbols(method);
if (symbols == null)
return null;
return symbols.LocalVariables.Select(v => new Debugger.ILLocalVariable() {
Index = v.OriginalVariable.Index,
Type = method.Compilation.FindType(KnownTypeCode.Object), // TODO
Name = v.Name,
IsCompilerGenerated = false,
ILRanges = new [] { new Debugger.ILRange(0, int.MaxValue) }
});
}
}
static class ILSpySymbolSourceExtensions
{
public static Debugger.SequencePoint ToDebugger(this ICSharpCode.Decompiler.SequencePoint seq, ICSharpCode.Decompiler.MethodDebugSymbols symbols, string filename)
{
return new Debugger.SequencePoint() {
MethodDefToken = symbols.CecilMethod.MetadataToken.ToUInt32(),
ILRanges = seq.ILRanges.Select(r => new ILRange(r.From, r.To)).ToArray(),
Filename = filename,
StartLine = seq.StartLocation.Line,
StartColumn = seq.StartLocation.Column,
EndLine = seq.EndLocation.Line,
EndColumn = seq.EndLocation.Column,
};
}
}
}

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

@ -8,7 +8,6 @@ using ICSharpCode.Core; @@ -8,7 +8,6 @@ using ICSharpCode.Core;
using ICSharpCode.NRefactory.Documentation;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.ILSpyAddIn
{
@ -54,45 +53,5 @@ namespace ICSharpCode.ILSpyAddIn @@ -54,45 +53,5 @@ namespace ICSharpCode.ILSpyAddIn
}
SD.Workbench.ShowView(new DecompiledViewContent(assemblyFile, typeName, entityIdString));
}
/*
public bool NavigateToMember(FileName assemblyFile, string typeName, string entityTag, int lineNumber, bool updateMarker)
{
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 exists - 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();
}
if (lineNumber > 0)
viewContent.JumpToLineNumber(lineNumber);
else
viewContent.JumpToEntity(entityTag);
viewContent.WorkbenchWindow.SelectWindow();
return true;
}
}
// create a new decompiled view
var decompiledView = new DecompiledViewContent(assemblyFile, typeName, entityTag);
decompiledView.DecompilationFinished += delegate {
if (updateMarker) {
decompiledView.UpdateDebuggingUI();
}
if (lineNumber > 0)
decompiledView.JumpToLineNumber(lineNumber);
else
decompiledView.JumpToEntity(entityTag);
};
WorkbenchSingleton.Workbench.ShowView(decompiledView);
return true;
}
*/
}
}

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

@ -1,84 +0,0 @@ @@ -1,84 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
using System.ComponentModel.Design;
using System.Windows.Controls;
using ICSharpCode.AvalonEdit.AddIn;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.AvalonEdit.Search;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Editor.Bookmarks;
using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.ILSpyAddIn.ViewContent
{
/// <summary>
/// Equivalent to AE.AddIn CodeEditor, but without editing capabilities.
/// </summary>
class CodeView : Grid, IDisposable, IPositionable
{
readonly SharpDevelopTextEditor textEditor;
readonly IconBarManager iconBarManager;
readonly IconBarMargin iconMargin;
readonly TextMarkerService textMarkerService;
readonly AvalonEditTextEditorAdapter adapter;
public CodeView()
{
textEditor = new SharpDevelopTextEditor();
textEditor.IsReadOnly = true;
this.Children.Add(textEditor);
adapter = new AvalonEditTextEditorAdapter(textEditor);
textEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition("C#");
// add margin
this.iconMargin = new IconBarMargin(iconBarManager = new IconBarManager());
textEditor.TextArea.LeftMargins.Insert(0, iconMargin);
textEditor.TextArea.TextView.VisualLinesChanged += delegate { iconMargin.InvalidateVisual(); };
// add marker service
this.textMarkerService = new TextMarkerService(textEditor.Document);
textEditor.TextArea.TextView.BackgroundRenderers.Add(textMarkerService);
textEditor.TextArea.TextView.LineTransformers.Add(textMarkerService);
var documentServiceContainer = textEditor.Document.GetRequiredService<ServiceContainer>();
documentServiceContainer.AddService(typeof(ITextMarkerService), textMarkerService);
documentServiceContainer.AddService(typeof(IBookmarkMargin), iconBarManager);
textEditor.TextArea.DefaultInputHandler.NestedInputHandlers.Add(new SearchInputHandler(textEditor.TextArea));
}
public TextDocument Document {
get { return textEditor.Document; }
}
public IconBarManager IconBarManager {
get { return iconBarManager; }
}
public void Dispose()
{
}
public int Line {
get {
return textEditor.TextArea.Caret.Line;
}
}
public int Column {
get {
return textEditor.TextArea.Caret.Column;
}
}
public void JumpTo(int line, int column)
{
adapter.JumpTo(line, column);
}
}
}

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

@ -3,14 +3,20 @@ @@ -3,14 +3,20 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.IO;
using System.Linq;
using System.Threading;
using ICSharpCode.AvalonEdit.AddIn;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.Core;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.NRefactory.Documentation;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.ILSpyAddIn.LaunchILSpy;
using ICSharpCode.ILSpyAddIn.ViewContent;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop;
@ -24,11 +30,15 @@ namespace ICSharpCode.ILSpyAddIn @@ -24,11 +30,15 @@ namespace ICSharpCode.ILSpyAddIn
/// <summary>
/// Hosts a decompiled type.
/// </summary>
class DecompiledViewContent : AbstractViewContentWithoutFile
class DecompiledViewContent : AbstractViewContentWithoutFile, IPositionable
{
readonly FileName assemblyFile;
readonly string fullTypeName;
readonly FileName virtualFileName;
public FileName VirtualFileName { get; private set; }
public override FileName PrimaryFileName {
get { return this.VirtualFileName; }
}
/// <summary>
/// Entity to jump to once decompilation has finished.
@ -37,16 +47,19 @@ namespace ICSharpCode.ILSpyAddIn @@ -37,16 +47,19 @@ namespace ICSharpCode.ILSpyAddIn
bool decompilationFinished;
readonly CodeView codeView;
readonly CodeEditor codeEditor = new CodeEditor();
readonly CancellationTokenSource cancellation = new CancellationTokenSource();
Dictionary<string, TextLocation> memberLocations;
public Dictionary<string, MethodDebugSymbols> DebugSymbols { get; private set; }
#region Constructor
public DecompiledViewContent(FileName assemblyFile, string fullTypeName, string entityTag)
{
this.virtualFileName = FileName.Create("ilspy://" + assemblyFile + "/" + fullTypeName);
this.codeView = new CodeView();
this.VirtualFileName = FileName.Create("ilspy://" + assemblyFile + "/" + fullTypeName + ".cs");
this.Services = codeEditor.PrimaryTextEditor.GetRequiredService<IServiceContainer>();
this.Services.AddService(typeof(IPositionable), this);
this.assemblyFile = assemblyFile;
this.fullTypeName = fullTypeName;
@ -55,15 +68,68 @@ namespace ICSharpCode.ILSpyAddIn @@ -55,15 +68,68 @@ namespace ICSharpCode.ILSpyAddIn
string shortTypeName = fullTypeName.Substring(fullTypeName.LastIndexOf('.') + 1);
this.TitleName = "[" + ReflectionHelper.SplitTypeParameterCountFromReflectionName(shortTypeName) + "]";
Thread thread = new Thread(DecompilationThread);
thread.Name = "Decompiler (" + shortTypeName + ")";
thread.Start();
DecompilationThread();
// Thread thread = new Thread(DecompilationThread);
// thread.Name = "Decompiler (" + shortTypeName + ")";
// thread.Start();
// thread.Join();
SD.BookmarkManager.BookmarkRemoved += BookmarkManager_Removed;
SD.BookmarkManager.BookmarkAdded += BookmarkManager_Added;
this.codeEditor.FileName = this.VirtualFileName;
this.codeEditor.ActiveTextEditor.IsReadOnly = true;
this.codeEditor.ActiveTextEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition("C#");
}
#endregion
public static DecompiledViewContent Get(FileName virtualFileName)
{
var viewContents = SD.Workbench.ViewContentCollection.OfType<DecompiledViewContent>();
return viewContents.FirstOrDefault(c => c.VirtualFileName == virtualFileName);
}
public static DecompiledViewContent Get(IEntity entity)
{
if (entity == null)
throw new ArgumentNullException("entity");
// Get the underlying entity for generic instance members
if (entity is IMember)
entity = ((IMember)entity).MemberDefinition;
ITypeDefinition declaringType = (entity as ITypeDefinition) ?? entity.DeclaringTypeDefinition;
if (declaringType == null)
return null;
// get the top-level type
while (declaringType.DeclaringTypeDefinition != null)
declaringType = declaringType.DeclaringTypeDefinition;
FileName assemblyLocation = declaringType.ParentAssembly.GetRuntimeAssemblyLocation();
if (assemblyLocation != null && File.Exists(assemblyLocation)) {
return Get(assemblyLocation, declaringType.ReflectionName);
}
return null;
}
public static DecompiledViewContent Get(FileName assemblyFile, string typeName)
{
if (assemblyFile == null)
throw new ArgumentNullException("assemblyFile");
if (string.IsNullOrEmpty(typeName))
throw new ArgumentException("typeName is null or empty");
foreach (var viewContent in SD.Workbench.ViewContentCollection.OfType<DecompiledViewContent>()) {
if (viewContent.AssemblyFile == assemblyFile && typeName == viewContent.FullTypeName) {
return viewContent;
}
}
var newViewContent = new DecompiledViewContent(assemblyFile, typeName, null);
SD.Workbench.ShowView(newViewContent);
return newViewContent;
}
#region Properties
public FileName AssemblyFile {
get { return assemblyFile; }
@ -77,7 +143,7 @@ namespace ICSharpCode.ILSpyAddIn @@ -77,7 +143,7 @@ namespace ICSharpCode.ILSpyAddIn
}
public override object Control {
get { return codeView; }
get { return codeEditor; }
}
public override bool IsReadOnly {
@ -90,7 +156,7 @@ namespace ICSharpCode.ILSpyAddIn @@ -90,7 +156,7 @@ namespace ICSharpCode.ILSpyAddIn
public override void Dispose()
{
cancellation.Cancel();
codeView.Dispose();
codeEditor.Dispose();
SD.BookmarkManager.BookmarkAdded -= BookmarkManager_Added;
SD.BookmarkManager.BookmarkRemoved -= BookmarkManager_Removed;
// DecompileInformation data;
@ -112,7 +178,7 @@ namespace ICSharpCode.ILSpyAddIn @@ -112,7 +178,7 @@ namespace ICSharpCode.ILSpyAddIn
// TODO: show Save As dialog to allow the user to save the decompiled file
}
#endregion
#region JumpToEntity
public void JumpToEntity(string entityIdString)
{
@ -121,8 +187,8 @@ namespace ICSharpCode.ILSpyAddIn @@ -121,8 +187,8 @@ namespace ICSharpCode.ILSpyAddIn
return;
}
TextLocation location;
if (memberLocations != null && memberLocations.TryGetValue(entityIdString, out location))
codeView.JumpTo(location.Line, location.Column);
if (entityIdString != null && memberLocations != null && memberLocations.TryGetValue(entityIdString, out location))
this.JumpTo(location.Line, location.Column);
}
#endregion
@ -132,9 +198,10 @@ namespace ICSharpCode.ILSpyAddIn @@ -132,9 +198,10 @@ namespace ICSharpCode.ILSpyAddIn
try {
StringWriter writer = new StringWriter();
RunDecompiler(assemblyFile, fullTypeName, new DebuggerTextOutput(new PlainTextOutput(writer)), cancellation.Token);
if (!cancellation.IsCancellationRequested) {
SD.MainThread.InvokeAsyncAndForget(() => OnDecompilationFinished(writer));
}
// if (!cancellation.IsCancellationRequested) {
// SD.MainThread.InvokeAsyncAndForget(() => OnDecompilationFinished(writer));
// }
OnDecompilationFinished(writer);
} catch (OperationCanceledException) {
// ignore cancellation
} catch (Exception ex) {
@ -169,16 +236,20 @@ namespace ICSharpCode.ILSpyAddIn @@ -169,16 +236,20 @@ namespace ICSharpCode.ILSpyAddIn
astBuilder.AddType(typeDefinition);
astBuilder.GenerateCode(textOutput);
// ReflectionDisassembler disasm = new ReflectionDisassembler(textOutput, true, cancellationToken);
// disasm.DisassembleType(typeDefinition);
// save decompilation data
memberLocations = textOutput.MemberLocations;
this.DebugSymbols = textOutput.DebugSymbols;
}
void OnDecompilationFinished(StringWriter output)
{
if (cancellation.IsCancellationRequested)
return;
codeView.Document.Text = output.ToString();
codeView.Document.UndoStack.ClearAll();
codeEditor.Document.Text = output.ToString();
codeEditor.Document.UndoStack.ClearAll();
this.decompilationFinished = true;
JumpToEntity(this.jumpToEntityIdStringWhenDecompilationFinished);
@ -205,65 +276,15 @@ namespace ICSharpCode.ILSpyAddIn @@ -205,65 +276,15 @@ namespace ICSharpCode.ILSpyAddIn
codeView.IconBarManager.Bookmarks.Add(bookmark);
}
}
public void UpdateDebuggingUI()
{
if (!DebuggerService.IsDebuggerStarted)
return;
if (decompiledType == null || decompiledType.MetadataToken == null)
return;
int typeToken = decompiledType.MetadataToken.ToInt32();
if (!DebuggerDecompilerService.DebugInformation.ContainsKey(typeToken))
return;
var decompilerService = DebuggerDecompilerService.Instance;
if (decompilerService == null || decompilerService.DebugStepInformation == null)
return;
// get debugging information
DecompileInformation debugInformation = (DecompileInformation)DebuggerDecompilerService.DebugInformation[typeToken];
int methodToken = decompilerService.DebugStepInformation.Item1;
int ilOffset = decompilerService.DebugStepInformation.Item2;
int line;
MemberReference member;
if (debugInformation.CodeMappings == null || !debugInformation.CodeMappings.ContainsKey(methodToken))
return;
debugInformation.CodeMappings[methodToken].GetInstructionByTokenAndOffset(methodToken, ilOffset, out member, out line);
// if the codemappings are not built
if (line <= 0) {
DebuggerService.CurrentDebugger.StepOver();
return;
}
// jump to line - scoll and unfold
this.UpdateCurrentLineBookmark(line);
this.JumpToLineNumber(line);
}
void UpdateCurrentLineBookmark(int lineNumber)
{
if (lineNumber <= 0)
return;
CurrentLineBookmark.SetPosition(uri, codeView.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
void BookmarkManager_Removed(object sender, BookmarkEventArgs e)
{
var mark = e.Bookmark;
if (mark != null && codeView.IconBarManager.Bookmarks.Contains(mark)) {
codeView.IconBarManager.Bookmarks.Remove(mark);
if (mark != null && codeEditor.IconBarManager.Bookmarks.Contains(mark)) {
codeEditor.IconBarManager.Bookmarks.Remove(mark);
mark.Document = null;
}
}
@ -271,13 +292,28 @@ namespace ICSharpCode.ILSpyAddIn @@ -271,13 +292,28 @@ namespace ICSharpCode.ILSpyAddIn
void BookmarkManager_Added(object sender, BookmarkEventArgs e)
{
var mark = e.Bookmark;
if (mark != null && mark is BreakpointBookmark && mark.FileName == virtualFileName) {
codeView.IconBarManager.Bookmarks.Add(mark);
mark.Document = this.codeView.Document;
if (mark != null && mark.FileName == VirtualFileName) {
codeEditor.IconBarManager.Bookmarks.Add(mark);
mark.Document = this.codeEditor.Document;
}
}
#endregion
#region IPositionable
public int Line {
get { return codeEditor.ActiveTextEditorAdapter.Caret.Line; }
}
public int Column {
get { return codeEditor.ActiveTextEditorAdapter.Caret.Column; }
}
public void JumpTo(int line, int column)
{
codeEditor.ActiveTextEditor.JumpTo(line, column);
}
#endregion
#region Events
public event EventHandler DecompilationFinished;

14
src/AddIns/DisplayBindings/SettingsEditor/Project/SettingsEditor.csproj

@ -46,7 +46,6 @@ @@ -46,7 +46,6 @@
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
@ -70,19 +69,12 @@ @@ -70,19 +69,12 @@
</Compile>
<Compile Include="SettingsDisplayBinding.cs" />
<Compile Include="SettingsViewContent.cs" />
<Compile Include="SettingsView.Designer.cs">
<DependentUpon>SettingsView.cs</DependentUpon>
</Compile>
<Compile Include="SettingsView.cs" />
<Compile Include="SettingsEntry.cs" />
<EmbeddedResource Include="SettingsView.resx">
<DependentUpon>SettingsView.cs</DependentUpon>
</EmbeddedResource>
<Compile Include="ProxyPropertyDescriptor.cs" />
<Compile Include="SettingsEntryPropertyGridWrapper.cs" />
<Compile Include="ISettingsEntryHost.cs" />
<Compile Include="SettingsViewXaml.xaml.cs">
<DependentUpon>SettingsViewXaml.xaml</DependentUpon>
<Compile Include="SettingsView.xaml.cs">
<DependentUpon>SettingsView.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="SpecialTypes.cs" />
@ -111,7 +103,7 @@ @@ -111,7 +103,7 @@
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Page Include="SettingsViewXaml.xaml" />
<Page Include="SettingsView.xaml" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
</Project>

121
src/AddIns/DisplayBindings/SettingsEditor/Project/SettingsView.Designer.cs generated

@ -1,121 +0,0 @@ @@ -1,121 +0,0 @@
// 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)
namespace ICSharpCode.SettingsEditor
{
partial class SettingsView
{
/// <summary>
/// Designer variable used to keep track of non-visual components.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Disposes resources used by the control.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing) {
if (components != null) {
components.Dispose();
}
}
base.Dispose(disposing);
}
/// <summary>
/// This method is required for Windows Forms designer support.
/// Do not change the method contents inside the source code editor. The Forms designer might
/// not be able to load this method if it was changed manually.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.grid = new System.Windows.Forms.DataGridView();
this.NameColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.TypeColumn = new System.Windows.Forms.DataGridViewComboBoxColumn();
this.ScopeColumn = new System.Windows.Forms.DataGridViewComboBoxColumn();
this.ValueColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
this.bindingSource = new System.Windows.Forms.BindingSource(this.components);
((System.ComponentModel.ISupportInitialize)(this.grid)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.bindingSource)).BeginInit();
this.SuspendLayout();
//
// grid
//
this.grid.AutoGenerateColumns = false;
this.grid.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
this.grid.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
this.NameColumn,
this.TypeColumn,
this.ScopeColumn,
this.ValueColumn});
this.grid.DataSource = this.bindingSource;
this.grid.Dock = System.Windows.Forms.DockStyle.Fill;
this.grid.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnKeystroke;
this.grid.Location = new System.Drawing.Point(0, 0);
this.grid.Name = "grid";
this.grid.Size = new System.Drawing.Size(486, 362);
this.grid.TabIndex = 0;
this.grid.DataError += new System.Windows.Forms.DataGridViewDataErrorEventHandler(this.GridDataError);
this.grid.SelectionChanged += new System.EventHandler(this.GridSelectionChanged);
this.grid.UserDeletingRow += new System.Windows.Forms.DataGridViewRowCancelEventHandler(this.GridUserDeletingRow);
//
// NameColumn
//
this.NameColumn.DataPropertyName = "Name";
this.NameColumn.HeaderText = "Name";
this.NameColumn.MinimumWidth = 50;
this.NameColumn.Name = "NameColumn";
//
// TypeColumn
//
this.TypeColumn.DataPropertyName = "WrappedSettingType";
this.TypeColumn.DropDownWidth = 255;
this.TypeColumn.HeaderText = "Type";
this.TypeColumn.MinimumWidth = 50;
this.TypeColumn.Name = "TypeColumn";
this.TypeColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic;
//
// ScopeColumn
//
this.ScopeColumn.DataPropertyName = "Scope";
this.ScopeColumn.DropDownWidth = 80;
this.ScopeColumn.HeaderText = "Scope";
this.ScopeColumn.MinimumWidth = 30;
this.ScopeColumn.Name = "ScopeColumn";
this.ScopeColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.Automatic;
//
// ValueColumn
//
this.ValueColumn.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.Fill;
this.ValueColumn.DataPropertyName = "SerializedValue";
this.ValueColumn.HeaderText = "Value";
this.ValueColumn.MinimumWidth = 50;
this.ValueColumn.Name = "ValueColumn";
//
// bindingSource
//
this.bindingSource.DataSource = typeof(ICSharpCode.SettingsEditor.SettingsEntry);
this.bindingSource.AddingNew += new System.ComponentModel.AddingNewEventHandler(this.BindingSourceAddingNew);
//
// SettingsView
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.grid);
this.Name = "SettingsView";
this.Size = new System.Drawing.Size(486, 362);
((System.ComponentModel.ISupportInitialize)(this.grid)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.bindingSource)).EndInit();
this.ResumeLayout(false);
}
private System.Windows.Forms.DataGridViewComboBoxColumn TypeColumn;
private System.Windows.Forms.DataGridViewComboBoxColumn ScopeColumn;
private System.Windows.Forms.DataGridViewTextBoxColumn ValueColumn;
private System.Windows.Forms.DataGridViewTextBoxColumn NameColumn;
private System.Windows.Forms.BindingSource bindingSource;
private System.Windows.Forms.DataGridView grid;
}
}

181
src/AddIns/DisplayBindings/SettingsEditor/Project/SettingsView.cs

@ -1,181 +0,0 @@ @@ -1,181 +0,0 @@
// 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.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Collections.Generic;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Dom;
using ICSharpCode.SharpDevelop;
namespace ICSharpCode.SettingsEditor
{
public partial class SettingsView : UserControl, ISettingsEntryHost
{
public event EventHandler SelectionChanged;
public event EventHandler SettingsChanged;
static readonly Type[] defaultAvailableTypes = new Type[] {
typeof(bool),
typeof(byte),
typeof(char),
typeof(decimal),
typeof(double),
typeof(float),
typeof(int),
typeof(long),
typeof(sbyte),
typeof(short),
typeof(string),
typeof(System.Collections.Specialized.StringCollection),
typeof(System.DateTime),
typeof(System.Drawing.Color),
typeof(System.Drawing.Font),
typeof(System.Drawing.Point),
typeof(System.Drawing.Size),
typeof(System.Guid),
typeof(System.TimeSpan),
typeof(uint),
typeof(ulong),
typeof(ushort)
};
List<string> typeNames = new List<string>();
List<Type> types = new List<Type>();
IAmbience ambience;
ICompilation compilation;
public SettingsView()
{
InitializeComponent();
ambience = AmbienceService.GetCurrentAmbience();
compilation = MinimalCorlib.Instance.CreateCompilation();
foreach (Type type in defaultAvailableTypes) {
types.Add(type);
typeNames.Add(ambience.ConvertType(type.ToTypeReference().Resolve(compilation)));
}
foreach (SpecialTypeDescriptor d in SpecialTypeDescriptor.Descriptors) {
types.Add(d.type);
typeNames.Add(d.name);
}
ScopeColumn.DataSource = Enum.GetValues(typeof(SettingScope));
TypeColumn.DataSource = typeNames;
}
public void ShowEntries(IList<SettingsEntry> list)
{
bindingSource.Clear();
foreach (SettingsEntry entry in list) {
bindingSource.Add(entry);
}
bindingSource.ListChanged += delegate(object sender, ListChangedEventArgs e) {
if (e.NewIndex >= 0 && e.NewIndex < bindingSource.Count) {
if (((SettingsEntry)bindingSource[e.NewIndex]).Name != null) {
OnSettingsChanged(e);
}
}
};
}
void GridSelectionChanged(object sender, EventArgs e)
{
if (SelectionChanged != null)
SelectionChanged(this, e);
}
public IEnumerable<SettingsEntry> GetAllEntries()
{
List<SettingsEntry> l = new List<SettingsEntry>();
foreach (SettingsEntry entry in bindingSource) {
if (!string.IsNullOrEmpty(entry.Name)) {
l.Add(entry);
}
}
l.Sort(delegate(SettingsEntry a, SettingsEntry b) {
return a.Name.CompareTo(b.Name);
});
return l;
}
public List<SettingsEntryPropertyGridWrapper> GetSelectedEntriesForPropertyGrid()
{
List<SettingsEntryPropertyGridWrapper> l
= new List<SettingsEntryPropertyGridWrapper>();
if (grid.SelectedRows.Count > 0) {
foreach (DataGridViewRow row in grid.SelectedRows) {
if (row.DataBoundItem != null) {
l.Add(new SettingsEntryPropertyGridWrapper((SettingsEntry)row.DataBoundItem));
}
}
} else {
bool[] rowAdded = new bool[grid.Rows.Count];
foreach (DataGridViewCell cell in grid.SelectedCells) {
if (rowAdded[cell.RowIndex] == false) {
rowAdded[cell.RowIndex] = true;
if (cell.OwningRow.DataBoundItem != null) {
l.Add(new SettingsEntryPropertyGridWrapper((SettingsEntry)cell.OwningRow.DataBoundItem));
}
}
}
}
return l;
}
void BindingSourceAddingNew(object sender, AddingNewEventArgs e)
{
SettingsEntry entry = new SettingsEntry(this);
entry.Type = typeof(string);
e.NewObject = entry;
}
void GridDataError(object sender, DataGridViewDataErrorEventArgs e)
{
LoggingService.Debug("Row " + e.RowIndex + ", column " + e.ColumnIndex + ", error " + e.Exception.ToString());
if (e.Exception != null) {
MessageBox.Show("Error in data entry: " + e.Exception.Message);
} else {
MessageBox.Show("Error in data entry");
}
}
string ISettingsEntryHost.GetDisplayNameForType(Type type)
{
foreach (SpecialTypeDescriptor d in SpecialTypeDescriptor.Descriptors) {
if (type == d.type)
return d.name;
}
return ambience.ConvertType(type.ToTypeReference().Resolve(compilation));
}
Type ISettingsEntryHost.GetTypeByDisplayName(string displayName)
{
for (int i = 0; i < typeNames.Count; i++) {
if (typeNames[i] == displayName)
return types[i];
}
return null;
}
void GridUserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
{
if (e.Row != null && !e.Cancel) {
OnSettingsChanged(EventArgs.Empty);
}
}
protected virtual void OnSettingsChanged(EventArgs e)
{
if (SettingsChanged != null) {
SettingsChanged(this, e);
}
}
}
}

128
src/AddIns/DisplayBindings/SettingsEditor/Project/SettingsView.resx

@ -1,128 +0,0 @@ @@ -1,128 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="mscorlib" name="mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="TypeColumn.UserAddedColumn" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="bindingSource.TrayLocation" type="System.Drawing.Point, System.Drawing">
<value>28, 18</value>
</data>
</root>

2
src/AddIns/DisplayBindings/SettingsEditor/Project/SettingsViewXaml.xaml → src/AddIns/DisplayBindings/SettingsEditor/Project/SettingsView.xaml

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<UserControl
x:Class="ICSharpCode.SettingsEditor.SettingsViewXaml"
x:Class="ICSharpCode.SettingsEditor.SettingsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sd="clr-namespace:ICSharpCode.SharpDevelop;assembly=ICSharpCode.SharpDevelop"

11
src/AddIns/DisplayBindings/SettingsEditor/Project/SettingsViewXaml.xaml.cs → src/AddIns/DisplayBindings/SettingsEditor/Project/SettingsView.xaml.cs

@ -9,14 +9,7 @@ @@ -9,14 +9,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
@ -28,7 +21,7 @@ namespace ICSharpCode.SettingsEditor @@ -28,7 +21,7 @@ namespace ICSharpCode.SettingsEditor
/// <summary>
/// Interaction logic for SettingsViewXaml.xaml
/// </summary>
public partial class SettingsViewXaml : UserControl,ISettingsEntryHost
public partial class SettingsView : UserControl,ISettingsEntryHost
{
public event EventHandler SettingsChanged;
public event EventHandler SelectionChanged;
@ -65,7 +58,7 @@ namespace ICSharpCode.SettingsEditor @@ -65,7 +58,7 @@ namespace ICSharpCode.SettingsEditor
IAmbience ambience;
ICompilation compilation;
public SettingsViewXaml()
public SettingsView()
{
InitializeComponent();

21
src/AddIns/DisplayBindings/SettingsEditor/Project/SettingsViewContent.cs

@ -19,8 +19,7 @@ namespace ICSharpCode.SettingsEditor @@ -19,8 +19,7 @@ namespace ICSharpCode.SettingsEditor
{
public class SettingsViewContent : AbstractViewContentHandlingLoadErrors, IHasPropertyContainer
{
// SettingsView view = new SettingsView();
SettingsViewXaml view = new SettingsViewXaml();
SettingsView view = new SettingsView();
PropertyContainer propertyContainer = new PropertyContainer();
SettingsDocument setDoc = new SettingsDocument();
MemoryStream appConfigStream;
@ -29,30 +28,17 @@ namespace ICSharpCode.SettingsEditor @@ -29,30 +28,17 @@ namespace ICSharpCode.SettingsEditor
public SettingsViewContent(OpenedFile file) : base(file)
{
TryOpenAppConfig(false);
/*
view.SelectionChanged += delegate {
propertyContainer.SelectedObjects = view.GetSelectedEntriesForPropertyGrid().ToArray();
};
view.SettingsChanged += delegate {
if (this.PrimaryFile != null)
this.PrimaryFile.MakeDirty();
if (appConfigFile != null)
appConfigFile.MakeDirty();
};
*/
this.UserContent = view;
view.SelectionChanged += ((s,e) =>
{
Console.WriteLine("SettingsViewContent.SelectionChanged");
propertyContainer.SelectedObjects = view.GetSelectedEntriesForPropertyGrid().ToArray();
});
view.SettingsChanged += ((s,e) =>
{
Console.WriteLine("SettingsViewContent.SettingsChanged");
if (this.PrimaryFile != null)
this.PrimaryFile.MakeDirty();
if (appConfigFile != null)
@ -61,6 +47,7 @@ namespace ICSharpCode.SettingsEditor @@ -61,6 +47,7 @@ namespace ICSharpCode.SettingsEditor
}
void TryOpenAppConfig(bool createIfNotExists)
{
if (appConfigFile != null) // already open
@ -80,6 +67,7 @@ namespace ICSharpCode.SettingsEditor @@ -80,6 +67,7 @@ namespace ICSharpCode.SettingsEditor
}
}
protected override void LoadInternal(OpenedFile file, Stream stream)
{
Console.WriteLine ("LoadInternal");
@ -101,6 +89,7 @@ namespace ICSharpCode.SettingsEditor @@ -101,6 +89,7 @@ namespace ICSharpCode.SettingsEditor
}
void ShowLoadError(string message)
{
MessageService.ShowMessage(message);

6
src/Libraries/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -126,7 +126,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -126,7 +126,7 @@ namespace ICSharpCode.Decompiler.Ast
astBlock.Statements.InsertBefore(insertionPoint, newVarDecl);
}
astBlock.AddAnnotation(new MemberMapping(methodDef) { LocalVariables = localVariables });
astBlock.AddAnnotation(new MethodDebugSymbols(methodDef) { LocalVariables = localVariables.ToList() });
return astBlock;
}
@ -147,7 +147,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -147,7 +147,7 @@ namespace ICSharpCode.Decompiler.Ast
if (node is ILLabel) {
yield return new Ast.LabelStatement { Label = ((ILLabel)node).Name };
} else if (node is ILExpression) {
List<ILRange> ilRanges = ILRange.OrderAndJoint(node.GetSelfAndChildrenRecursive<ILExpression>().SelectMany(e => e.ILRanges));
List<ILRange> ilRanges = ILRange.OrderAndJoin(node.GetSelfAndChildrenRecursive<ILExpression>().SelectMany(e => e.ILRanges));
AstNode codeExpr = TransformExpression((ILExpression)node);
if (codeExpr != null) {
codeExpr = codeExpr.WithAnnotation(ilRanges);
@ -253,7 +253,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -253,7 +253,7 @@ namespace ICSharpCode.Decompiler.Ast
Expression astExpr = node as Expression;
// get IL ranges - used in debugger
List<ILRange> ilRanges = ILRange.OrderAndJoint(expr.GetSelfAndChildrenRecursive<ILExpression>().SelectMany(e => e.ILRanges));
List<ILRange> ilRanges = ILRange.OrderAndJoin(expr.GetSelfAndChildrenRecursive<ILExpression>().SelectMany(e => e.ILRanges));
AstNode result;
if (astExpr != null)

46
src/Libraries/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs

@ -36,6 +36,8 @@ namespace ICSharpCode.Decompiler.Ast @@ -36,6 +36,8 @@ namespace ICSharpCode.Decompiler.Ast
bool firstUsingDeclaration;
bool lastUsingDeclaration;
TextLocation? lastEndOfLine;
public bool FoldBraces = false;
public TextOutputFormatter(ITextOutput output)
@ -217,6 +219,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -217,6 +219,7 @@ namespace ICSharpCode.Decompiler.Ast
output.MarkFoldEnd();
lastUsingDeclaration = false;
}
lastEndOfLine = output.Location;
output.WriteLine();
}
@ -265,8 +268,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -265,8 +268,7 @@ namespace ICSharpCode.Decompiler.Ast
}
Stack<TextLocation> startLocations = new Stack<TextLocation>();
MemberMapping currentMemberMapping;
Stack<MemberMapping> parentMemberMappings = new Stack<MemberMapping>();
Stack<MethodDebugSymbols> symbolsStack = new Stack<MethodDebugSymbols>();
public void StartNode(AstNode node)
{
@ -284,11 +286,10 @@ namespace ICSharpCode.Decompiler.Ast @@ -284,11 +286,10 @@ namespace ICSharpCode.Decompiler.Ast
if (node is EntityDeclaration && node.Annotation<MemberReference>() != null && node.GetChildByRole(Roles.Identifier).IsNull)
output.WriteDefinition("", node.Annotation<MemberReference>(), false);
MemberMapping mapping = node.Annotation<MemberMapping>();
if (mapping != null) {
parentMemberMappings.Push(currentMemberMapping);
currentMemberMapping = mapping;
if (node.Annotation<MethodDebugSymbols>() != null) {
symbolsStack.Push(node.Annotation<MethodDebugSymbols>());
symbolsStack.Peek().StartLocation = startLocations.Peek();
}
}
@ -305,26 +306,21 @@ namespace ICSharpCode.Decompiler.Ast @@ -305,26 +306,21 @@ namespace ICSharpCode.Decompiler.Ast
var startLocation = startLocations.Pop();
// code mappings
if (currentMemberMapping != null) {
var ranges = node.Annotation<List<ILRange>>();
if (ranges != null && ranges.Count > 0) {
// add all ranges
foreach (var range in ranges) {
currentMemberMapping.MemberCodeMappings.Add(
new SourceCodeMapping {
ILInstructionOffset = range,
StartLocation = startLocation,
EndLocation = output.Location,
MemberMapping = currentMemberMapping
});
}
}
var ranges = node.Annotation<List<ILRange>>();
if (symbolsStack.Count > 0 && ranges != null && ranges.Count > 0) {
// Ignore the newline which was printed at the end of the statement
TextLocation endLocation = (node is Statement) ? (lastEndOfLine ?? output.Location) : output.Location;
symbolsStack.Peek().SequencePoints.Add(
new SequencePoint() {
ILRanges = ILRange.OrderAndJoin(ranges).ToArray(),
StartLocation = startLocation,
EndLocation = endLocation
});
}
if (node.Annotation<MemberMapping>() != null) {
output.AddDebuggerMemberMapping(currentMemberMapping);
currentMemberMapping = parentMemberMappings.Pop();
if (node.Annotation<MethodDebugSymbols>() != null) {
symbolsStack.Peek().EndLocation = output.Location;
output.AddDebugSymbols(symbolsStack.Pop());
}
}

231
src/Libraries/ICSharpCode.Decompiler/CodeMappings.cs

@ -17,240 +17,41 @@ @@ -17,240 +17,41 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.ILAst;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.CSharp;
using Mono.Cecil;
namespace ICSharpCode.Decompiler
{
/// <summary>
/// Maps the source code to IL.
/// </summary>
public sealed class SourceCodeMapping
/// <summary> Maps method's source code to IL </summary>
public class MethodDebugSymbols
{
/// <summary>
/// Gets or sets the start location of the instruction.
/// </summary>
public MethodDefinition CecilMethod { get; set; }
public List<ILVariable> LocalVariables { get; set; }
public List<SequencePoint> SequencePoints { get; set; }
public TextLocation StartLocation { get; set; }
/// <summary>
/// Gets or sets the end location of the instruction.
/// </summary>
public TextLocation EndLocation { get; set; }
/// <summary>
/// Gets or sets IL Range offset for the source code line. E.g.: 13-19 &lt;-&gt; 135.
/// </summary>
public ILRange ILInstructionOffset { get; set; }
/// <summary>
/// Gets or sets the member mapping this source code mapping belongs to.
/// </summary>
public MemberMapping MemberMapping { get; set; }
/// <summary>
/// Retrieves the array that contains the IL range and the missing gaps between ranges.
/// </summary>
/// <returns>The array representation of the step aranges.</returns>
public int[] ToArray(bool isMatch)
{
var currentList = new List<ILRange>();
// add list for the current source code line
currentList.AddRange(ILRange.OrderAndJoint(MemberMapping.MemberCodeMappings
.FindAll(m => m.StartLocation.Line == this.StartLocation.Line)
.ConvertAll<ILRange>(m => m.ILInstructionOffset)));
if (!isMatch) {
// add inverted
currentList.AddRange(MemberMapping.InvertedList);
} else {
// if the current list contains the last mapping, add also the last gap
var lastInverted = MemberMapping.InvertedList.LastOrDefault();
if (lastInverted != null && lastInverted.From == currentList[currentList.Count - 1].To)
currentList.Add(lastInverted);
}
// set the output
var resultList = new List<int>();
foreach (var element in ILRange.OrderAndJoint(currentList)) {
resultList.Add(element.From);
resultList.Add(element.To);
}
return resultList.ToArray();
}
}
/// <summary>
/// Stores the member information and its source code mappings.
/// </summary>
public sealed class MemberMapping
{
IEnumerable<ILRange> invertedList;
internal MemberMapping()
{
}
public MemberMapping(MethodDefinition method)
{
this.MetadataToken = method.MetadataToken.ToInt32();
this.MemberCodeMappings = new List<SourceCodeMapping>();
this.MemberReference = method;
this.CodeSize = method.Body.CodeSize;
}
/// <summary>
/// Gets or sets the type of the mapping.
/// </summary>
public MemberReference MemberReference { get; internal set; }
/// <summary>
/// Metadata token of the member.
/// </summary>
public int MetadataToken { get; internal set; }
/// <summary>
/// Gets or sets the code size for the member mapping.
/// </summary>
public int CodeSize { get; internal set; }
/// <summary>
/// Gets or sets the source code mappings.
/// </summary>
public List<SourceCodeMapping> MemberCodeMappings { get; internal set; }
/// <summary>
/// Gets or sets the local variables.
/// </summary>
public IEnumerable<ILVariable> LocalVariables { get; internal set; }
/// <summary>
/// Gets the inverted IL Ranges.<br/>
/// E.g.: for (0-9, 11-14, 14-18, 21-25) => (9-11,18-21).
/// </summary>
/// <returns>IL Range inverted list.</returns>
public IEnumerable<ILRange> InvertedList
public MethodDebugSymbols(MethodDefinition methodDef)
{
get {
if (invertedList == null) {
var list = MemberCodeMappings.ConvertAll<ILRange>(
s => new ILRange { From = s.ILInstructionOffset.From, To = s.ILInstructionOffset.To });
invertedList = ILRange.OrderAndJoint(ILRange.Invert(list, CodeSize));
}
return invertedList;
}
this.CecilMethod = methodDef;
this.LocalVariables = new List<ILVariable>();
this.SequencePoints = new List<SequencePoint>();
}
}
/// <summary>
/// Code mappings helper class.
/// </summary>
public static class CodeMappings
public class SequencePoint
{
/// <summary>
/// Gets source code mapping and metadata token based on type name and line number.
/// </summary>
/// <param name="codeMappings">Code mappings storage.</param>
/// <param name="typeName">Member reference name.</param>
/// <param name="lineNumber">Line number.</param>
/// <param name="metadataToken">Metadata token.</param>
/// <returns></returns>
public static SourceCodeMapping GetInstructionByLineNumber(
this MemberMapping codeMapping,
int lineNumber,
out int metadataToken)
{
if (codeMapping == null)
throw new ArgumentException("CodeMappings storage must be valid!");
var map = codeMapping.MemberCodeMappings.Find(m => m.StartLocation.Line == lineNumber);
if (map != null) {
metadataToken = codeMapping.MetadataToken;
return map;
}
metadataToken = 0;
return null;
}
/// <summary>
/// Gets a mapping given a type, a token and an IL offset.
/// </summary>
/// <param name="codeMappings">Code mappings storage.</param>
/// <param name="token">Token.</param>
/// <param name="ilOffset">IL offset.</param>
/// <param name="isMatch">True, if perfect match.</param>
/// <returns>A code mapping.</returns>
public static SourceCodeMapping GetInstructionByTokenAndOffset(
this MemberMapping codeMapping,
int ilOffset,
out bool isMatch)
{
isMatch = false;
if (codeMapping == null)
throw new ArgumentNullException("CodeMappings storage must be valid!");
// try find an exact match
var map = codeMapping.MemberCodeMappings.Find(m => m.ILInstructionOffset.From <= ilOffset && ilOffset < m.ILInstructionOffset.To);
if (map == null) {
// get the immediate next one
map = codeMapping.MemberCodeMappings.Find(m => m.ILInstructionOffset.From > ilOffset);
isMatch = false;
if (map == null)
map = codeMapping.MemberCodeMappings.LastOrDefault(); // get the last
return map;
}
isMatch = true;
return map;
}
public ILRange[] ILRanges { get; set; }
public TextLocation StartLocation { get; set; }
public TextLocation EndLocation { get; set; }
public int ILOffset { get { return this.ILRanges[0].From; } }
/// <summary>
/// Gets the source code and type name from metadata token and offset.
/// </summary>
/// <param name="codeMappings">Code mapping storage.</param>
/// <param name="token">Metadata token.</param>
/// <param name="ilOffset">IL offset.</param>
/// <param name="typeName">Type definition.</param>
/// <param name="line">Line number.</param>
/// <remarks>It is possible to exist to different types from different assemblies with the same metadata token.</remarks>
public static bool GetInstructionByTokenAndOffset(
this MemberMapping mapping,
int ilOffset,
out MemberReference member,
out int line)
public override string ToString()
{
member = null;
line = 0;
if (mapping == null)
throw new ArgumentException("CodeMappings storage must be valid!");
var codeMapping = mapping.MemberCodeMappings.Find(
cm => cm.ILInstructionOffset.From <= ilOffset && ilOffset <= cm.ILInstructionOffset.To - 1);
if (codeMapping == null) {
codeMapping = mapping.MemberCodeMappings.Find(cm => cm.ILInstructionOffset.From > ilOffset);
if (codeMapping == null) {
codeMapping = mapping.MemberCodeMappings.LastOrDefault();
if (codeMapping == null)
return false;
}
}
member = mapping.MemberReference;
line = codeMapping.StartLocation.Line;
return true;
return string.Join(" ", this.ILRanges) + " " + this.StartLocation + "-" + this.EndLocation;
}
}
}

26
src/Libraries/ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs

@ -47,7 +47,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -47,7 +47,7 @@ namespace ICSharpCode.Decompiler.Disassembler
this.cancellationToken = cancellationToken;
}
public void Disassemble(MethodBody body, MemberMapping methodMapping)
public void Disassemble(MethodBody body, MethodDebugSymbols debugSymbols)
{
// start writing IL code
MethodDefinition method = body.Method;
@ -82,20 +82,19 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -82,20 +82,19 @@ namespace ICSharpCode.Decompiler.Disassembler
if (detectControlStructure && body.Instructions.Count > 0) {
Instruction inst = body.Instructions[0];
HashSet<int> branchTargets = GetBranchTargets(body.Instructions);
WriteStructureBody(new ILStructure(body), branchTargets, ref inst, methodMapping, method.Body.CodeSize);
WriteStructureBody(new ILStructure(body), branchTargets, ref inst, debugSymbols, method.Body.CodeSize);
} else {
foreach (var inst in method.Body.Instructions) {
var startLocation = output.Location;
inst.WriteTo(output);
if (methodMapping != null) {
if (debugSymbols != null) {
// add IL code mappings - used in debugger
methodMapping.MemberCodeMappings.Add(
new SourceCodeMapping() {
debugSymbols.SequencePoints.Add(
new SequencePoint() {
StartLocation = output.Location,
EndLocation = output.Location,
ILInstructionOffset = new ILRange { From = inst.Offset, To = inst.Next == null ? method.Body.CodeSize : inst.Next.Offset },
MemberMapping = methodMapping
ILRanges = new ILRange[] { new ILRange(inst.Offset, inst.Next == null ? method.Body.CodeSize : inst.Next.Offset) }
});
}
@ -174,7 +173,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -174,7 +173,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Indent();
}
void WriteStructureBody(ILStructure s, HashSet<int> branchTargets, ref Instruction inst, MemberMapping currentMethodMapping, int codeSize)
void WriteStructureBody(ILStructure s, HashSet<int> branchTargets, ref Instruction inst, MethodDebugSymbols debugSymbols, int codeSize)
{
bool isFirstInstructionInStructure = true;
bool prevInstructionWasBranch = false;
@ -184,7 +183,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -184,7 +183,7 @@ namespace ICSharpCode.Decompiler.Disassembler
if (childIndex < s.Children.Count && s.Children[childIndex].StartOffset <= offset && offset < s.Children[childIndex].EndOffset) {
ILStructure child = s.Children[childIndex++];
WriteStructureHeader(child);
WriteStructureBody(child, branchTargets, ref inst, currentMethodMapping, codeSize);
WriteStructureBody(child, branchTargets, ref inst, debugSymbols, codeSize);
WriteStructureFooter(child);
} else {
if (!isFirstInstructionInStructure && (prevInstructionWasBranch || branchTargets.Contains(offset))) {
@ -194,13 +193,12 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -194,13 +193,12 @@ namespace ICSharpCode.Decompiler.Disassembler
inst.WriteTo(output);
// add IL code mappings - used in debugger
if (currentMethodMapping != null) {
currentMethodMapping.MemberCodeMappings.Add(
new SourceCodeMapping() {
if (debugSymbols != null) {
debugSymbols.SequencePoints.Add(
new SequencePoint() {
StartLocation = startLocation,
EndLocation = output.Location,
ILInstructionOffset = new ILRange { From = inst.Offset, To = inst.Next == null ? codeSize : inst.Next.Offset },
MemberMapping = currentMethodMapping
ILRanges = new ILRange[] { new ILRange(inst.Offset, inst.Next == null ? codeSize : inst.Next.Offset) }
});
}

11
src/Libraries/ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -22,6 +22,7 @@ using System.Diagnostics; @@ -22,6 +22,7 @@ using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using ICSharpCode.NRefactory;
using Mono.Cecil;
using Mono.Collections.Generic;
@ -114,6 +115,8 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -114,6 +115,8 @@ namespace ICSharpCode.Decompiler.Disassembler
// instance default class [mscorlib]System.IO.TextWriter get_BaseWriter () cil managed
//
TextLocation startLocation = output.Location;
//emit flags
WriteEnum(method.Attributes & MethodAttributes.MemberAccessMask, methodVisibility);
WriteFlags(method.Attributes & ~MethodAttributes.MemberAccessMask, methodAttributeFlags);
@ -217,9 +220,11 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -217,9 +220,11 @@ namespace ICSharpCode.Decompiler.Disassembler
if (method.HasBody) {
// create IL code mappings - used in debugger
MemberMapping methodMapping = new MemberMapping(method);
methodBodyDisassembler.Disassemble(method.Body, methodMapping);
output.AddDebuggerMemberMapping(methodMapping);
MethodDebugSymbols debugSymbols = new MethodDebugSymbols(method);
debugSymbols.StartLocation = startLocation;
methodBodyDisassembler.Disassemble(method.Body, debugSymbols);
debugSymbols.EndLocation = output.Location;
output.AddDebugSymbols(debugSymbols);
}
CloseBlock("end of method " + DisassemblerHelpers.Escape(method.DeclaringType.Name) + "::" + DisassemblerHelpers.Escape(method.Name));

2
src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs

@ -743,7 +743,7 @@ namespace ICSharpCode.Decompiler.ILAst @@ -743,7 +743,7 @@ namespace ICSharpCode.Decompiler.ILAst
// Convert stack-based IL code to ILAst tree
foreach(ByteCode byteCode in body) {
ILRange ilRange = new ILRange() { From = byteCode.Offset, To = byteCode.EndOffset };
ILRange ilRange = new ILRange(byteCode.Offset, byteCode.EndOffset);
if (byteCode.StackBefore == null) {
// Unreachable code

52
src/Libraries/ICSharpCode.Decompiler/ILAst/ILAstTypes.cs

@ -221,37 +221,43 @@ namespace ICSharpCode.Decompiler.ILAst @@ -221,37 +221,43 @@ namespace ICSharpCode.Decompiler.ILAst
}
}
public class ILRange
public struct ILRange
{
public int From;
public int To; // Exlusive
public readonly int From;
public readonly int To; // Exlusive
public ILRange(int @from, int to)
{
this.From = @from;
this.To = to;
}
public override string ToString()
{
return string.Format("{0}-{1}", From.ToString("X"), To.ToString("X"));
return string.Format("{0:X2}-{1:X2}", From, To);
}
public static List<ILRange> OrderAndJoint(IEnumerable<ILRange> input)
public static List<ILRange> OrderAndJoin(IEnumerable<ILRange> input)
{
if (input == null)
throw new ArgumentNullException("Input is null!");
List<ILRange> ranges = input.Where(r => r != null).OrderBy(r => r.From).ToList();
for (int i = 0; i < ranges.Count - 1;) {
ILRange curr = ranges[i];
ILRange next = ranges[i + 1];
// Merge consequtive ranges if they intersect
if (curr.From <= next.From && next.From <= curr.To) {
curr.To = Math.Max(curr.To, next.To);
ranges.RemoveAt(i + 1);
} else {
i++;
List<ILRange> result = new List<ILRange>();
foreach(ILRange curr in input.OrderBy(r => r.From)) {
if (result.Count > 0) {
// Merge consequtive ranges if possible
ILRange last = result[result.Count - 1];
if (curr.From <= last.To) {
result[result.Count - 1] = new ILRange(last.From, Math.Max(last.To, curr.To));
continue;
}
}
result.Add(curr);
}
return ranges;
return result;
}
public static IEnumerable<ILRange> Invert(IEnumerable<ILRange> input, int codeSize)
public static List<ILRange> Invert(IEnumerable<ILRange> input, int codeSize)
{
if (input == null)
throw new ArgumentNullException("Input is null!");
@ -259,23 +265,25 @@ namespace ICSharpCode.Decompiler.ILAst @@ -259,23 +265,25 @@ namespace ICSharpCode.Decompiler.ILAst
if (codeSize <= 0)
throw new ArgumentException("Code size must be grater than 0");
var ordered = OrderAndJoint(input);
List<ILRange> ordered = OrderAndJoin(input);
List<ILRange> result = new List<ILRange>(ordered.Count + 1);
if (ordered.Count == 0) {
yield return new ILRange() { From = 0, To = codeSize };
result.Add(new ILRange(0, codeSize));
} else {
// Gap before the first element
if (ordered.First().From != 0)
yield return new ILRange() { From = 0, To = ordered.First().From };
result.Add(new ILRange(0, ordered.First().From));
// Gaps between elements
for (int i = 0; i < ordered.Count - 1; i++)
yield return new ILRange() { From = ordered[i].To, To = ordered[i + 1].From };
result.Add(new ILRange(ordered[i].To, ordered[i + 1].From));
// Gap after the last element
Debug.Assert(ordered.Last().To <= codeSize);
if (ordered.Last().To != codeSize)
yield return new ILRange() { From = ordered.Last().To, To = codeSize };
result.Add(new ILRange(ordered.Last().To, codeSize));
}
return result;
}
}

2
src/Libraries/ICSharpCode.Decompiler/ITextOutput.cs

@ -35,7 +35,7 @@ namespace ICSharpCode.Decompiler @@ -35,7 +35,7 @@ namespace ICSharpCode.Decompiler
void WriteDefinition(string text, object definition, bool isLocal = true);
void WriteReference(string text, object reference, bool isLocal = false);
void AddDebuggerMemberMapping(MemberMapping memberMapping);
void AddDebugSymbols(MethodDebugSymbols methodDebugSymbols);
void MarkFoldStart(string collapsedText = "...", bool defaultCollapsed = false);
void MarkFoldEnd();

2
src/Libraries/ICSharpCode.Decompiler/PlainTextOutput.cs

@ -115,7 +115,7 @@ namespace ICSharpCode.Decompiler @@ -115,7 +115,7 @@ namespace ICSharpCode.Decompiler
{
}
void ITextOutput.AddDebuggerMemberMapping(MemberMapping memberMapping)
void ITextOutput.AddDebugSymbols(MethodDebugSymbols methodDebugSymbols)
{
}
}

5
src/Libraries/NRefactory/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs

@ -1786,11 +1786,6 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -1786,11 +1786,6 @@ namespace ICSharpCode.NRefactory.TypeSystem
set { throw new NotSupportedException(); }
}
public override string FullName {
// This works because LazyCecilTypeDefinition is only used for top-level types
get { return cecilTypeDef.FullName; }
}
public override string ReflectionName {
get { return cecilTypeDef.FullName; }
}

1
src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj

@ -515,7 +515,6 @@ @@ -515,7 +515,6 @@
<Compile Include="Src\Services\ClassBrowserIcons\ImageSourceImage.cs" />
<Compile Include="Src\Services\Debugger\BreakpointBookmark.cs" />
<Compile Include="Src\Services\Debugger\BreakpointBookmarkEventArgs.cs" />
<Compile Include="Src\Services\Debugger\DecompiledBreakpointBookmark.cs" />
<Compile Include="Workbench\File\IFileService.cs" />
<Compile Include="Workbench\File\OpenedFile.cs" />
<Compile Include="Src\Services\LanguageBinding\AggregatedLanguageBinding.cs" />

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

@ -52,9 +52,6 @@ namespace ICSharpCode.SharpDevelop.Debugging @@ -52,9 +52,6 @@ namespace ICSharpCode.SharpDevelop.Debugging
if (startColumn < 1)
startColumn = 1;
IDocumentLine line = document.GetLineByNumber(startLine);
if (endColumn < 1 || endColumn > line.Length)
endColumn = line.Length;
instance = new CurrentLineBookmark();
instance.Location = new TextLocation(startLine, startColumn);
instance.FileName = fileName;
@ -96,8 +93,11 @@ namespace ICSharpCode.SharpDevelop.Debugging @@ -96,8 +93,11 @@ namespace ICSharpCode.SharpDevelop.Debugging
protected override ITextMarker CreateMarker(ITextMarkerService markerService)
{
IDocumentLine line = this.Document.GetLineByNumber(startLine);
ITextMarker marker = markerService.Create(line.Offset + startColumn - 1, Math.Max(endColumn - startColumn, 1));
IDocumentLine sLine = this.Document.GetLineByNumber(startLine);
IDocumentLine eLine = this.Document.GetLineByNumber(endLine);
int sOffset = Math.Min(sLine.Offset + startColumn - 1, sLine.EndOffset);
int eOffset = Math.Min(eLine.Offset + endColumn - 1, eLine.EndOffset);
ITextMarker marker = markerService.Create(sOffset, Math.Max(eOffset - sOffset, 1));
IHighlighter highlighter = this.Document.GetService(typeof(IHighlighter)) as IHighlighter;
marker.BackgroundColor = DefaultBackground;
marker.ForegroundColor = DefaultForeground;

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

@ -231,55 +231,4 @@ namespace ICSharpCode.SharpDevelop.Debugging @@ -231,55 +231,4 @@ namespace ICSharpCode.SharpDevelop.Debugging
DebuggerService.CurrentDebugger.HandleToolTipRequest(e);
}
}
/// <summary>
/// Interface for common debugger-decompiler mapping operations.
/// </summary>
[SDService]
public interface IDebuggerDecompilerService
{
/*
/// <summary>
/// Gets or sets the current method token and IL offset. Used for step in/out.
/// </summary>
Tuple<int, int> DebugStepInformation { get; set; }
/// <summary>
/// Checks the code mappings.
/// </summary>
bool CheckMappings(int typeToken);
/// <summary>
/// Decompiles on demand a type.
/// </summary>
void DecompileOnDemand(TypeDefinition type);
/// <summary>
/// Gets the IL from and IL to.
/// </summary>
bool GetILAndTokenByLineNumber(int typeToken, int lineNumber, out int[] ilRanges, out int memberToken);
/// <summary>
/// Gets the ILRange and source code line number.
/// </summary>
bool GetILAndLineNumber(int typeToken, int memberToken, int ilOffset, out int[] ilRange, out int line, out bool isMatch);
/// <summary>
/// Gets the local variables of a type and a member.
/// </summary>
IEnumerable<string> GetLocalVariables(int typeToken, int memberToken);
/// <summary>
/// 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);
*/
}
}

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

@ -1,73 +0,0 @@ @@ -1,73 +0,0 @@
// 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 ICSharpCode.Core;
using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop.Debugging;
namespace ICSharpCode.SharpDevelop.Editor.Bookmarks
{
/*
public class DecompiledBreakpointBookmark : BreakpointBookmark
{
public const string SEPARATOR = ","; // don't use '.'
MemberReference memberReference;
string assemblyFile;
public DecompiledBreakpointBookmark(FileName fileName, TextLocation location)
: base(fileName, location)
{
}
public MemberReference MemberReference {
get { return memberReference; }
}
public MemberReference GetMemberReference(IAssemblyResolver resolver)
{
if (resolver == null)
throw new ArgumentNullException("resolver");
if (memberReference != null)
return memberReference;
// reload from filename
ReaderParameters readerParameters = new ReaderParameters();
// Use new assembly resolver instance so that the AssemblyDefinitions can be garbage-collected
// once the code is decompiled.
readerParameters.AssemblyResolver = resolver;
string typeName;
if (GetAssemblyAndType(FileName.ToString(), out assemblyFile, out typeName)) {
ModuleDefinition module = ModuleDefinition.ReadModule(assemblyFile, readerParameters);
TypeDefinition typeDefinition = module.GetType(typeName);
if (typeDefinition == null)
throw new InvalidOperationException("Could not find type");
memberReference = typeDefinition;
}
return memberReference;
}
/// <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;
}
}
*/
}
Loading…
Cancel
Save