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
{ {
return mark.IsVisibleInBookmarkPad && mark is BreakpointBookmark; 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 @@
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt) // This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Windows.Forms; using System.Windows.Forms;
using Debugger; using Debugger;
using Debugger.AddIn; using Debugger.AddIn;
using Debugger.AddIn.Tooltips; using Debugger.AddIn.Tooltips;
using Debugger.AddIn.TreeModel; using Debugger.AddIn.TreeModel;
using Debugger.Interop.CorPublish; using Debugger.Interop.CorPublish;
using Debugger.MetaData;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.Core.WinForms; using ICSharpCode.Core.WinForms;
using ICSharpCode.NRefactory; using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.SharpDevelop.Editor.Bookmarks;
using ICSharpCode.SharpDevelop.Debugging; using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Editor;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.SharpDevelop.Gui.OptionPanels;
using ICSharpCode.SharpDevelop.Project; using ICSharpCode.SharpDevelop.Project;
using Mono.Cecil;
using Process = Debugger.Process; using Process = Debugger.Process;
using StackFrame = Debugger.StackFrame; using StackFrame = Debugger.StackFrame;
using TreeNode = Debugger.AddIn.TreeModel.TreeNode; using TreeNode = Debugger.AddIn.TreeModel.TreeNode;
@ -87,7 +78,7 @@ namespace ICSharpCode.SharpDevelop.Services
ICorPublish corPublish; ICorPublish corPublish;
internal IDebuggerDecompilerService debuggerDecompilerService; List<ISymbolSource> symbolSources = new List<ISymbolSource>();
/// <inheritdoc/> /// <inheritdoc/>
public bool BreakAtBeginning { get; set; } public bool BreakAtBeginning { get; set; }
@ -357,8 +348,8 @@ namespace ICSharpCode.SharpDevelop.Services
public void InitializeService() public void InitializeService()
{ {
// get decompiler service symbolSources.Add(new PdbSymbolSource());
debuggerDecompilerService = SD.GetService<IDebuggerDecompilerService>(); symbolSources.AddRange(AddInTree.BuildItems<ISymbolSource>("/SharpDevelop/Services/DebuggerService/SymbolSource", null, false));
// init NDebugger // init NDebugger
CurrentDebugger = new NDebugger(); CurrentDebugger = new NDebugger();
@ -407,44 +398,7 @@ namespace ICSharpCode.SharpDevelop.Services
void AddBreakpoint(BreakpointBookmark bookmark) void AddBreakpoint(BreakpointBookmark bookmark)
{ {
Breakpoint breakpoint = null; Breakpoint breakpoint = CurrentDebugger.AddBreakpoint(bookmark.FileName, bookmark.LineNumber, 0, bookmark.IsEnabled);
#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;
}
bookmark.InternalBreakpointObject = breakpoint; bookmark.InternalBreakpointObject = breakpoint;
bookmark.IsHealthy = (CurrentProcess == null) || breakpoint.IsSet; bookmark.IsHealthy = (CurrentProcess == null) || breakpoint.IsSet;
bookmark.IsEnabledChanged += delegate { breakpoint.IsEnabled = bookmark.IsEnabled; }; bookmark.IsEnabledChanged += delegate { breakpoint.IsEnabled = bookmark.IsEnabled; };
@ -512,6 +466,10 @@ namespace ICSharpCode.SharpDevelop.Services
CurrentThread = e.Thread; CurrentThread = e.Thread;
CurrentStackFrame = CurrentThread != null ? CurrentThread.MostRecentUserStackFrame : null; 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 // We can have several events happening at the same time
bool breakProcess = e.Break; bool breakProcess = e.Break;
@ -642,73 +600,14 @@ namespace ICSharpCode.SharpDevelop.Services
SD.Workbench.MainWindow.Activate(); SD.Workbench.MainWindow.Activate();
// if (debuggedProcess.IsSelectedFrameForced()) {
if (CurrentStackFrame.HasSymbols) { if (CurrentStackFrame.HasSymbols) {
SequencePoint nextStatement = CurrentStackFrame.NextStatement; SequencePoint nextStatement = CurrentStackFrame.NextStatement;
if (nextStatement != null) { if (nextStatement != null) {
DebuggerService.RemoveCurrentLineMarker(); DebuggerService.RemoveCurrentLineMarker();
DebuggerService.JumpToCurrentLine(nextStatement.Filename, nextStatement.StartLine, nextStatement.StartColumn, nextStatement.EndLine, nextStatement.EndColumn); DebuggerService.JumpToCurrentLine(nextStatement.Filename, nextStatement.StartLine, nextStatement.StartColumn, nextStatement.EndLine, nextStatement.EndColumn);
} }
} else {
#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() StopAttachedProcessDialogResult ShowStopAttachedProcessDialog()
{ {

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

@ -256,23 +256,6 @@ namespace Debugger.AddIn.TreeModel
} }
} else { } else {
WindowsDebugger debugger = (WindowsDebugger)DebuggerService.CurrentDebugger; 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
public virtual bool SetBreakpoint(Module module) 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) { if (seq != null) {
ICorDebugFunction corFuction = module.CorModule.GetFunctionFromToken(seq.MethodDefToken); ICorDebugFunction corFuction = module.CorModule.GetFunctionFromToken(seq.MethodDefToken);
ICorDebugFunctionBreakpoint corBreakpoint = corFuction.GetILCode().CreateBreakpoint((uint)seq.ILOffset); ICorDebugFunctionBreakpoint corBreakpoint = corFuction.GetILCode().CreateBreakpoint((uint)seq.ILOffset);
@ -80,45 +80,4 @@ namespace Debugger
return false; 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 @@
<Compile Include="NDebugger.cs" /> <Compile Include="NDebugger.cs" />
<Compile Include="Options.cs" /> <Compile Include="Options.cs" />
<Compile Include="Process.cs" /> <Compile Include="Process.cs" />
<Compile Include="PDBSymbolSource.cs" /> <Compile Include="PdbSymbolSource.cs" />
<Compile Include="StackFrame.cs" /> <Compile Include="StackFrame.cs" />
<Compile Include="Stepper.cs" /> <Compile Include="Stepper.cs" />
<Compile Include="Thread.cs" /> <Compile Include="Thread.cs" />

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

@ -62,7 +62,7 @@ namespace Debugger
case EvalState.Evaluating: throw new GetValueException("Evaluating..."); case EvalState.Evaluating: throw new GetValueException("Evaluating...");
case EvalState.EvaluatedSuccessfully: return result; case EvalState.EvaluatedSuccessfully: return result;
case EvalState.EvaluatedException: 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"); case EvalState.EvaluatedTimeOut: throw new GetValueException("Timeout");
default: throw new DebuggerException("Unknown state"); default: throw new DebuggerException("Unknown state");
} }

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

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

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

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

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

@ -170,13 +170,6 @@ namespace Debugger
return breakpoint; 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) void AddBreakpoint(Breakpoint breakpoint)
{ {
this.breakpoints.Add(breakpoint); this.breakpoints.Add(breakpoint);

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

@ -6,17 +6,6 @@ namespace Debugger
{ {
public class Options 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 EnableJustMyCode { get; set; }
public virtual bool StepOverNoSymbols { get; set; } public virtual bool StepOverNoSymbols { get; set; }
public virtual bool StepOverDebuggerAttributes { get; set; } public virtual bool StepOverDebuggerAttributes { get; set; }

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

@ -45,6 +45,11 @@ namespace Debugger
this.From = from; this.From = from;
this.To = to; this.To = to;
} }
public override string ToString()
{
return string.Format("{0:X2}-{1:X2}", From, To);
}
} }
public class ILLocalVariable public class ILLocalVariable
@ -56,7 +61,25 @@ namespace Debugger
public ILRange[] ILRanges { get; set; } 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> /// <summary>
/// Get absolute source code path for the specified document. /// Get absolute source code path for the specified document.
@ -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(); var symMethod = method.GetSymMethod();
if (symMethod == null) if (symMethod == null)
@ -149,14 +172,11 @@ namespace Debugger
return sequencePoint; 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 ISymUnmanagedReader.GetDocument! It is broken if two files have the same name
// Do not use ISymUnmanagedMethod.GetOffset! It sometimes returns negative offset // 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; ISymUnmanagedReader symReader = module.SymReader;
if (symReader == null) if (symReader == null)
return null; // No symbols return null; // No symbols
@ -181,9 +201,7 @@ namespace Debugger
int codesize = (int)corFunction.GetILCode().GetSize(); int codesize = (int)corFunction.GetILCode().GetSize();
var seqPoints = symMethod.GetSequencePoints(codesize).Where(s => s.StartLine != 0xFEEFEE); var seqPoints = symMethod.GetSequencePoints(codesize).Where(s => s.StartLine != 0xFEEFEE);
SequencePoint seqPoint = null; SequencePoint seqPoint = null;
if (column == 0) { if (column != 0) {
seqPoint = seqPoints.FirstOrDefault(s => s.StartLine <= line && line <= s.EndLine);
} else {
seqPoint = seqPoints.FirstOrDefault(s => (s.StartLine < line || (s.StartLine == line && s.StartColumn <= column)) && seqPoint = seqPoints.FirstOrDefault(s => (s.StartLine < line || (s.StartLine == line && s.StartColumn <= column)) &&
(line < s.EndLine || (line == s.EndLine && column <= s.EndColumn))); (line < s.EndLine || (line == s.EndLine && column <= s.EndColumn)));
} }
@ -191,12 +209,12 @@ namespace Debugger
return seqPoint; return seqPoint;
} }
public static bool HasSymbols(IMethod method) public bool HasSymbols(IMethod method)
{ {
return method.GetSymMethod() != null; return method.GetSymMethod() != null;
} }
public static IEnumerable<ILRange> GetIgnoredILRanges(IMethod method) public IEnumerable<ILRange> GetIgnoredILRanges(IMethod method)
{ {
var symMethod = method.GetSymMethod(); var symMethod = method.GetSymMethod();
if (symMethod == null) if (symMethod == null)
@ -206,7 +224,7 @@ namespace Debugger
return symMethod.GetSequencePoints(codeSize).Where(p => p.StartLine == 0xFEEFEE).SelectMany(p => p.ILRanges).ToList(); 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(); var symMethod = method.GetSymMethod();
if (symMethod == null) if (symMethod == null)

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

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

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

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

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

@ -14,6 +14,10 @@ namespace Debugger
{ {
public delegate Value ValueGetter(StackFrame context); 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 class GetValueException: DebuggerException
{ {
public GetValueException(string error) : base(error) {} public GetValueException(string error) : base(error) {}
@ -240,13 +244,13 @@ namespace Debugger
} }
/// <summary> Dereferences a pointer type </summary> /// <summary> Dereferences a pointer type </summary>
/// <returns> Returns null for a null pointer </returns>
public Value Dereference() 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; ICorDebugReferenceValue corRef = (ICorDebugReferenceValue)this.CorValue;
if (corRef.GetValue() == 0 || corRef.Dereference() == null) { if (corRef.GetValue() == 0 || corRef.Dereference() == null) {
return null; throw new GetValueException("Null pointer");
} else { } else {
return new Value(this.AppDomain, corRef.Dereference()); return new Value(this.AppDomain, corRef.Dereference());
} }
@ -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> /// <summary> Get the value of given member. </summary>
public Value GetMemberValue(Thread evalThread, IMember memberInfo, params Value[] arguments) 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
testNode.SetAttribute("name", testName); testNode.SetAttribute("name", testName);
shapshotID = 0; 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 = ""; log = "";
lastLogMessage = null; lastLogMessage = null;
process = debugger.Start(exeFilename, Path.GetDirectoryName(exeFilename), testName, false); process = debugger.Start(exeFilename, Path.GetDirectoryName(exeFilename), testName, false);

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

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

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

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

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

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

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

@ -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;
using ICSharpCode.NRefactory.Documentation; using ICSharpCode.NRefactory.Documentation;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Gui;
namespace ICSharpCode.ILSpyAddIn namespace ICSharpCode.ILSpyAddIn
{ {
@ -54,45 +53,5 @@ namespace ICSharpCode.ILSpyAddIn
} }
SD.Workbench.ShowView(new DecompiledViewContent(assemblyFile, typeName, entityIdString)); 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 @@
// 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 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel.Design;
using System.IO; using System.IO;
using System.Linq;
using System.Threading; using System.Threading;
using ICSharpCode.AvalonEdit.AddIn;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Ast; using ICSharpCode.Decompiler.Ast;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.NRefactory.Documentation;
using ICSharpCode.SharpDevelop.Gui;
using ICSharpCode.ILSpyAddIn.LaunchILSpy; using ICSharpCode.ILSpyAddIn.LaunchILSpy;
using ICSharpCode.ILSpyAddIn.ViewContent;
using ICSharpCode.NRefactory; using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem;
using ICSharpCode.SharpDevelop; using ICSharpCode.SharpDevelop;
@ -24,11 +30,15 @@ namespace ICSharpCode.ILSpyAddIn
/// <summary> /// <summary>
/// Hosts a decompiled type. /// Hosts a decompiled type.
/// </summary> /// </summary>
class DecompiledViewContent : AbstractViewContentWithoutFile class DecompiledViewContent : AbstractViewContentWithoutFile, IPositionable
{ {
readonly FileName assemblyFile; readonly FileName assemblyFile;
readonly string fullTypeName; readonly string fullTypeName;
readonly FileName virtualFileName; public FileName VirtualFileName { get; private set; }
public override FileName PrimaryFileName {
get { return this.VirtualFileName; }
}
/// <summary> /// <summary>
/// Entity to jump to once decompilation has finished. /// Entity to jump to once decompilation has finished.
@ -37,16 +47,19 @@ namespace ICSharpCode.ILSpyAddIn
bool decompilationFinished; bool decompilationFinished;
readonly CodeView codeView; readonly CodeEditor codeEditor = new CodeEditor();
readonly CancellationTokenSource cancellation = new CancellationTokenSource(); readonly CancellationTokenSource cancellation = new CancellationTokenSource();
Dictionary<string, TextLocation> memberLocations; Dictionary<string, TextLocation> memberLocations;
public Dictionary<string, MethodDebugSymbols> DebugSymbols { get; private set; }
#region Constructor #region Constructor
public DecompiledViewContent(FileName assemblyFile, string fullTypeName, string entityTag) public DecompiledViewContent(FileName assemblyFile, string fullTypeName, string entityTag)
{ {
this.virtualFileName = FileName.Create("ilspy://" + assemblyFile + "/" + fullTypeName); this.VirtualFileName = FileName.Create("ilspy://" + assemblyFile + "/" + fullTypeName + ".cs");
this.codeView = new CodeView();
this.Services = codeEditor.PrimaryTextEditor.GetRequiredService<IServiceContainer>();
this.Services.AddService(typeof(IPositionable), this);
this.assemblyFile = assemblyFile; this.assemblyFile = assemblyFile;
this.fullTypeName = fullTypeName; this.fullTypeName = fullTypeName;
@ -55,15 +68,68 @@ namespace ICSharpCode.ILSpyAddIn
string shortTypeName = fullTypeName.Substring(fullTypeName.LastIndexOf('.') + 1); string shortTypeName = fullTypeName.Substring(fullTypeName.LastIndexOf('.') + 1);
this.TitleName = "[" + ReflectionHelper.SplitTypeParameterCountFromReflectionName(shortTypeName) + "]"; this.TitleName = "[" + ReflectionHelper.SplitTypeParameterCountFromReflectionName(shortTypeName) + "]";
Thread thread = new Thread(DecompilationThread); DecompilationThread();
thread.Name = "Decompiler (" + shortTypeName + ")"; // Thread thread = new Thread(DecompilationThread);
thread.Start(); // thread.Name = "Decompiler (" + shortTypeName + ")";
// thread.Start();
// thread.Join();
SD.BookmarkManager.BookmarkRemoved += BookmarkManager_Removed; SD.BookmarkManager.BookmarkRemoved += BookmarkManager_Removed;
SD.BookmarkManager.BookmarkAdded += BookmarkManager_Added; SD.BookmarkManager.BookmarkAdded += BookmarkManager_Added;
this.codeEditor.FileName = this.VirtualFileName;
this.codeEditor.ActiveTextEditor.IsReadOnly = true;
this.codeEditor.ActiveTextEditor.SyntaxHighlighting = HighlightingManager.Instance.GetDefinition("C#");
} }
#endregion #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 #region Properties
public FileName AssemblyFile { public FileName AssemblyFile {
get { return assemblyFile; } get { return assemblyFile; }
@ -77,7 +143,7 @@ namespace ICSharpCode.ILSpyAddIn
} }
public override object Control { public override object Control {
get { return codeView; } get { return codeEditor; }
} }
public override bool IsReadOnly { public override bool IsReadOnly {
@ -90,7 +156,7 @@ namespace ICSharpCode.ILSpyAddIn
public override void Dispose() public override void Dispose()
{ {
cancellation.Cancel(); cancellation.Cancel();
codeView.Dispose(); codeEditor.Dispose();
SD.BookmarkManager.BookmarkAdded -= BookmarkManager_Added; SD.BookmarkManager.BookmarkAdded -= BookmarkManager_Added;
SD.BookmarkManager.BookmarkRemoved -= BookmarkManager_Removed; SD.BookmarkManager.BookmarkRemoved -= BookmarkManager_Removed;
// DecompileInformation data; // DecompileInformation data;
@ -112,7 +178,7 @@ namespace ICSharpCode.ILSpyAddIn
// TODO: show Save As dialog to allow the user to save the decompiled file // TODO: show Save As dialog to allow the user to save the decompiled file
} }
#endregion #endregion
#region JumpToEntity #region JumpToEntity
public void JumpToEntity(string entityIdString) public void JumpToEntity(string entityIdString)
{ {
@ -121,8 +187,8 @@ namespace ICSharpCode.ILSpyAddIn
return; return;
} }
TextLocation location; TextLocation location;
if (memberLocations != null && memberLocations.TryGetValue(entityIdString, out location)) if (entityIdString != null && memberLocations != null && memberLocations.TryGetValue(entityIdString, out location))
codeView.JumpTo(location.Line, location.Column); this.JumpTo(location.Line, location.Column);
} }
#endregion #endregion
@ -132,9 +198,10 @@ namespace ICSharpCode.ILSpyAddIn
try { try {
StringWriter writer = new StringWriter(); StringWriter writer = new StringWriter();
RunDecompiler(assemblyFile, fullTypeName, new DebuggerTextOutput(new PlainTextOutput(writer)), cancellation.Token); RunDecompiler(assemblyFile, fullTypeName, new DebuggerTextOutput(new PlainTextOutput(writer)), cancellation.Token);
if (!cancellation.IsCancellationRequested) { // if (!cancellation.IsCancellationRequested) {
SD.MainThread.InvokeAsyncAndForget(() => OnDecompilationFinished(writer)); // SD.MainThread.InvokeAsyncAndForget(() => OnDecompilationFinished(writer));
} // }
OnDecompilationFinished(writer);
} catch (OperationCanceledException) { } catch (OperationCanceledException) {
// ignore cancellation // ignore cancellation
} catch (Exception ex) { } catch (Exception ex) {
@ -169,16 +236,20 @@ namespace ICSharpCode.ILSpyAddIn
astBuilder.AddType(typeDefinition); astBuilder.AddType(typeDefinition);
astBuilder.GenerateCode(textOutput); astBuilder.GenerateCode(textOutput);
// ReflectionDisassembler disasm = new ReflectionDisassembler(textOutput, true, cancellationToken);
// disasm.DisassembleType(typeDefinition);
// save decompilation data // save decompilation data
memberLocations = textOutput.MemberLocations; memberLocations = textOutput.MemberLocations;
this.DebugSymbols = textOutput.DebugSymbols;
} }
void OnDecompilationFinished(StringWriter output) void OnDecompilationFinished(StringWriter output)
{ {
if (cancellation.IsCancellationRequested) if (cancellation.IsCancellationRequested)
return; return;
codeView.Document.Text = output.ToString(); codeEditor.Document.Text = output.ToString();
codeView.Document.UndoStack.ClearAll(); codeEditor.Document.UndoStack.ClearAll();
this.decompilationFinished = true; this.decompilationFinished = true;
JumpToEntity(this.jumpToEntityIdStringWhenDecompilationFinished); JumpToEntity(this.jumpToEntityIdStringWhenDecompilationFinished);
@ -205,65 +276,15 @@ namespace ICSharpCode.ILSpyAddIn
codeView.IconBarManager.Bookmarks.Add(bookmark); 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 #endregion
#region Bookmarks #region Bookmarks
void BookmarkManager_Removed(object sender, BookmarkEventArgs e) void BookmarkManager_Removed(object sender, BookmarkEventArgs e)
{ {
var mark = e.Bookmark; var mark = e.Bookmark;
if (mark != null && codeView.IconBarManager.Bookmarks.Contains(mark)) { if (mark != null && codeEditor.IconBarManager.Bookmarks.Contains(mark)) {
codeView.IconBarManager.Bookmarks.Remove(mark); codeEditor.IconBarManager.Bookmarks.Remove(mark);
mark.Document = null; mark.Document = null;
} }
} }
@ -271,13 +292,28 @@ namespace ICSharpCode.ILSpyAddIn
void BookmarkManager_Added(object sender, BookmarkEventArgs e) void BookmarkManager_Added(object sender, BookmarkEventArgs e)
{ {
var mark = e.Bookmark; var mark = e.Bookmark;
if (mark != null && mark is BreakpointBookmark && mark.FileName == virtualFileName) { if (mark != null && mark.FileName == VirtualFileName) {
codeView.IconBarManager.Bookmarks.Add(mark); codeEditor.IconBarManager.Bookmarks.Add(mark);
mark.Document = this.codeView.Document; mark.Document = this.codeEditor.Document;
} }
} }
#endregion #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 #region Events
public event EventHandler DecompilationFinished; public event EventHandler DecompilationFinished;

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

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

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

@ -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 @@
// 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 @@
<?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 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<UserControl <UserControl
x:Class="ICSharpCode.SettingsEditor.SettingsViewXaml" x:Class="ICSharpCode.SettingsEditor.SettingsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sd="clr-namespace:ICSharpCode.SharpDevelop;assembly=ICSharpCode.SharpDevelop" 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 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Text;
using System.Windows;
using System.Windows.Controls; 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;
using ICSharpCode.NRefactory.TypeSystem.Implementation; using ICSharpCode.NRefactory.TypeSystem.Implementation;
@ -28,7 +21,7 @@ namespace ICSharpCode.SettingsEditor
/// <summary> /// <summary>
/// Interaction logic for SettingsViewXaml.xaml /// Interaction logic for SettingsViewXaml.xaml
/// </summary> /// </summary>
public partial class SettingsViewXaml : UserControl,ISettingsEntryHost public partial class SettingsView : UserControl,ISettingsEntryHost
{ {
public event EventHandler SettingsChanged; public event EventHandler SettingsChanged;
public event EventHandler SelectionChanged; public event EventHandler SelectionChanged;
@ -65,7 +58,7 @@ namespace ICSharpCode.SettingsEditor
IAmbience ambience; IAmbience ambience;
ICompilation compilation; ICompilation compilation;
public SettingsViewXaml() public SettingsView()
{ {
InitializeComponent(); InitializeComponent();

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

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

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

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

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

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

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

@ -17,240 +17,41 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using ICSharpCode.Decompiler.Ast;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.ILAst; using ICSharpCode.Decompiler.ILAst;
using ICSharpCode.NRefactory; using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.CSharp;
using Mono.Cecil; using Mono.Cecil;
namespace ICSharpCode.Decompiler namespace ICSharpCode.Decompiler
{ {
/// <summary> /// <summary> Maps method's source code to IL </summary>
/// Maps the source code to IL. public class MethodDebugSymbols
/// </summary>
public sealed class SourceCodeMapping
{ {
/// <summary> public MethodDefinition CecilMethod { get; set; }
/// Gets or sets the start location of the instruction. public List<ILVariable> LocalVariables { get; set; }
/// </summary> public List<SequencePoint> SequencePoints { get; set; }
public TextLocation StartLocation { get; set; } public TextLocation StartLocation { get; set; }
/// <summary>
/// Gets or sets the end location of the instruction.
/// </summary>
public TextLocation EndLocation { get; set; } public TextLocation EndLocation { get; set; }
/// <summary> public MethodDebugSymbols(MethodDefinition methodDef)
/// 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
{ {
get { this.CecilMethod = methodDef;
if (invertedList == null) { this.LocalVariables = new List<ILVariable>();
var list = MemberCodeMappings.ConvertAll<ILRange>( this.SequencePoints = new List<SequencePoint>();
s => new ILRange { From = s.ILInstructionOffset.From, To = s.ILInstructionOffset.To });
invertedList = ILRange.OrderAndJoint(ILRange.Invert(list, CodeSize));
}
return invertedList;
}
} }
} }
/// <summary> public class SequencePoint
/// Code mappings helper class.
/// </summary>
public static class CodeMappings
{ {
/// <summary> public ILRange[] ILRanges { get; set; }
/// Gets source code mapping and metadata token based on type name and line number. public TextLocation StartLocation { get; set; }
/// </summary> public TextLocation EndLocation { get; set; }
/// <param name="codeMappings">Code mappings storage.</param> public int ILOffset { get { return this.ILRanges[0].From; } }
/// <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;
}
/// <summary> public override string ToString()
/// 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)
{ {
member = null; return string.Join(" ", this.ILRanges) + " " + this.StartLocation + "-" + this.EndLocation;
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;
} }
} }
} }

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

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

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

@ -22,6 +22,7 @@ using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using ICSharpCode.NRefactory;
using Mono.Cecil; using Mono.Cecil;
using Mono.Collections.Generic; using Mono.Collections.Generic;
@ -114,6 +115,8 @@ namespace ICSharpCode.Decompiler.Disassembler
// instance default class [mscorlib]System.IO.TextWriter get_BaseWriter () cil managed // instance default class [mscorlib]System.IO.TextWriter get_BaseWriter () cil managed
// //
TextLocation startLocation = output.Location;
//emit flags //emit flags
WriteEnum(method.Attributes & MethodAttributes.MemberAccessMask, methodVisibility); WriteEnum(method.Attributes & MethodAttributes.MemberAccessMask, methodVisibility);
WriteFlags(method.Attributes & ~MethodAttributes.MemberAccessMask, methodAttributeFlags); WriteFlags(method.Attributes & ~MethodAttributes.MemberAccessMask, methodAttributeFlags);
@ -217,9 +220,11 @@ namespace ICSharpCode.Decompiler.Disassembler
if (method.HasBody) { if (method.HasBody) {
// create IL code mappings - used in debugger // create IL code mappings - used in debugger
MemberMapping methodMapping = new MemberMapping(method); MethodDebugSymbols debugSymbols = new MethodDebugSymbols(method);
methodBodyDisassembler.Disassemble(method.Body, methodMapping); debugSymbols.StartLocation = startLocation;
output.AddDebuggerMemberMapping(methodMapping); 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)); 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
// Convert stack-based IL code to ILAst tree // Convert stack-based IL code to ILAst tree
foreach(ByteCode byteCode in body) { 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) { if (byteCode.StackBefore == null) {
// Unreachable code // Unreachable code

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

@ -221,37 +221,43 @@ namespace ICSharpCode.Decompiler.ILAst
} }
} }
public class ILRange public struct ILRange
{ {
public int From; public readonly int From;
public int To; // Exlusive public readonly int To; // Exlusive
public ILRange(int @from, int to)
{
this.From = @from;
this.To = to;
}
public override string ToString() 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) if (input == null)
throw new ArgumentNullException("Input is null!"); throw new ArgumentNullException("Input is null!");
List<ILRange> ranges = input.Where(r => r != null).OrderBy(r => r.From).ToList(); List<ILRange> result = new List<ILRange>();
for (int i = 0; i < ranges.Count - 1;) { foreach(ILRange curr in input.OrderBy(r => r.From)) {
ILRange curr = ranges[i]; if (result.Count > 0) {
ILRange next = ranges[i + 1]; // Merge consequtive ranges if possible
// Merge consequtive ranges if they intersect ILRange last = result[result.Count - 1];
if (curr.From <= next.From && next.From <= curr.To) { if (curr.From <= last.To) {
curr.To = Math.Max(curr.To, next.To); result[result.Count - 1] = new ILRange(last.From, Math.Max(last.To, curr.To));
ranges.RemoveAt(i + 1); continue;
} else { }
i++;
} }
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) if (input == null)
throw new ArgumentNullException("Input is null!"); throw new ArgumentNullException("Input is null!");
@ -259,23 +265,25 @@ namespace ICSharpCode.Decompiler.ILAst
if (codeSize <= 0) if (codeSize <= 0)
throw new ArgumentException("Code size must be grater than 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) { if (ordered.Count == 0) {
yield return new ILRange() { From = 0, To = codeSize }; result.Add(new ILRange(0, codeSize));
} else { } else {
// Gap before the first element // Gap before the first element
if (ordered.First().From != 0) 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 // Gaps between elements
for (int i = 0; i < ordered.Count - 1; i++) 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 // Gap after the last element
Debug.Assert(ordered.Last().To <= codeSize); Debug.Assert(ordered.Last().To <= codeSize);
if (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
void WriteDefinition(string text, object definition, bool isLocal = true); void WriteDefinition(string text, object definition, bool isLocal = true);
void WriteReference(string text, object reference, bool isLocal = false); 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 MarkFoldStart(string collapsedText = "...", bool defaultCollapsed = false);
void MarkFoldEnd(); void MarkFoldEnd();

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

@ -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
set { throw new NotSupportedException(); } 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 { public override string ReflectionName {
get { return cecilTypeDef.FullName; } get { return cecilTypeDef.FullName; }
} }

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

@ -515,7 +515,6 @@
<Compile Include="Src\Services\ClassBrowserIcons\ImageSourceImage.cs" /> <Compile Include="Src\Services\ClassBrowserIcons\ImageSourceImage.cs" />
<Compile Include="Src\Services\Debugger\BreakpointBookmark.cs" /> <Compile Include="Src\Services\Debugger\BreakpointBookmark.cs" />
<Compile Include="Src\Services\Debugger\BreakpointBookmarkEventArgs.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\IFileService.cs" />
<Compile Include="Workbench\File\OpenedFile.cs" /> <Compile Include="Workbench\File\OpenedFile.cs" />
<Compile Include="Src\Services\LanguageBinding\AggregatedLanguageBinding.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
if (startColumn < 1) if (startColumn < 1)
startColumn = 1; startColumn = 1;
IDocumentLine line = document.GetLineByNumber(startLine);
if (endColumn < 1 || endColumn > line.Length)
endColumn = line.Length;
instance = new CurrentLineBookmark(); instance = new CurrentLineBookmark();
instance.Location = new TextLocation(startLine, startColumn); instance.Location = new TextLocation(startLine, startColumn);
instance.FileName = fileName; instance.FileName = fileName;
@ -96,8 +93,11 @@ namespace ICSharpCode.SharpDevelop.Debugging
protected override ITextMarker CreateMarker(ITextMarkerService markerService) protected override ITextMarker CreateMarker(ITextMarkerService markerService)
{ {
IDocumentLine line = this.Document.GetLineByNumber(startLine); IDocumentLine sLine = this.Document.GetLineByNumber(startLine);
ITextMarker marker = markerService.Create(line.Offset + startColumn - 1, Math.Max(endColumn - startColumn, 1)); 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; IHighlighter highlighter = this.Document.GetService(typeof(IHighlighter)) as IHighlighter;
marker.BackgroundColor = DefaultBackground; marker.BackgroundColor = DefaultBackground;
marker.ForegroundColor = DefaultForeground; marker.ForegroundColor = DefaultForeground;

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

@ -231,55 +231,4 @@ namespace ICSharpCode.SharpDevelop.Debugging
DebuggerService.CurrentDebugger.HandleToolTipRequest(e); 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 @@
// 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