Browse Source

Add hidden sequence points for unmapped code.

pull/923/head
Daniel Grunwald 8 years ago
parent
commit
9d7fb0627d
  1. 27
      ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs
  2. 17
      ICSharpCode.Decompiler/IL/SequencePoint.cs
  3. 18
      ILSpy/Languages/CSharpILMixedLanguage.cs

27
ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs

@ -18,6 +18,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL;
@ -131,8 +132,12 @@ namespace ICSharpCode.Decompiler.CSharp
void EndSequencePoint(TextLocation startLocation, TextLocation endLocation) void EndSequencePoint(TextLocation startLocation, TextLocation endLocation)
{ {
if (current.Intervals.Count > 0 && current.Function != null) { if (current.Intervals.Count > 0 && current.Function != null) {
// use LongSet to deduplicate and merge the intervals
var longSet = new LongSet(current.Intervals.Select(i => new LongInterval(i.Start, i.End)));
Debug.Assert(!longSet.IsEmpty);
sequencePoints.Add((current.Function, new SequencePoint { sequencePoints.Add((current.Function, new SequencePoint {
Offset = current.Intervals.Select(i => i.Start).Min(), Offset = (int)longSet.Intervals[0].Start,
EndOffset = (int)longSet.Intervals[0].End,
StartLine = startLocation.Line, StartLine = startLocation.Line,
StartColumn = startLocation.Column, StartColumn = startLocation.Column,
EndLine = endLocation.Line, EndLine = endLocation.Line,
@ -183,8 +188,24 @@ namespace ICSharpCode.Decompiler.CSharp
} }
list.Add(sequencePoint); list.Add(sequencePoint);
} }
foreach (var list in dict.Values) { foreach (var (function, list) in dict.ToList()) {
list.Sort((a, b) => a.Offset.CompareTo(b.Offset)); // For each function, sort sequence points
// and insert hidden sequence points in the gaps.
var newList = new List<SequencePoint>();
int pos = 0;
foreach (var sequencePoint in list.OrderBy(sp => sp.Offset)) {
Debug.Assert(sequencePoint.Offset >= pos);
if (sequencePoint.Offset > pos) {
var hidden = new SequencePoint();
hidden.Offset = pos;
hidden.EndOffset = sequencePoint.Offset;
hidden.SetHidden();
newList.Add(hidden);
}
newList.Add(sequencePoint);
pos = sequencePoint.EndOffset;
}
dict[function] = newList;
} }
return dict; return dict;
} }

17
ICSharpCode.Decompiler/IL/SequencePoint.cs

@ -10,10 +10,20 @@ namespace ICSharpCode.Decompiler.IL
public struct SequencePoint public struct SequencePoint
{ {
/// <summary> /// <summary>
/// IL offset. /// IL start offset.
/// </summary> /// </summary>
public int Offset { get; set; } public int Offset { get; set; }
/// <summary>
/// IL end offset.
/// </summary>
/// <remarks>
/// This does not get stored in debug information;
/// it is used internally to create hidden sequence points
/// for the IL fragments not covered by any sequence point.
/// </remarks>
public int EndOffset { get; set; }
public int StartLine { get; set; } public int StartLine { get; set; }
public int StartColumn { get; set; } public int StartColumn { get; set; }
public int EndLine { get; set; } public int EndLine { get; set; }
@ -22,5 +32,10 @@ namespace ICSharpCode.Decompiler.IL
public bool IsHidden { public bool IsHidden {
get { return StartLine == 0xfeefee && StartLine == EndLine; } get { return StartLine == 0xfeefee && StartLine == EndLine; }
} }
internal void SetHidden()
{
StartLine = EndLine = 0xfeefee;
}
} }
} }

18
ILSpy/Languages/CSharpILMixedLanguage.cs

@ -82,9 +82,10 @@ namespace ICSharpCode.ILSpy
int index = sequencePoints.BinarySearch(instruction.Offset, seq => seq.Offset); int index = sequencePoints.BinarySearch(instruction.Offset, seq => seq.Offset);
if (index >= 0) { if (index >= 0) {
var info = sequencePoints[index]; var info = sequencePoints[index];
var highlightingOutput = output as ISmartTextOutput;
if (!info.IsHidden) { if (!info.IsHidden) {
for (int line = info.StartLine; line <= info.EndLine; line++) { for (int line = info.StartLine; line <= info.EndLine; line++) {
if (output is ISmartTextOutput highlightingOutput) { if (highlightingOutput != null) {
string text = codeLines[line - 1]; string text = codeLines[line - 1];
int startColumn = 1; int startColumn = 1;
int endColumn = text.Length + 1; int endColumn = text.Length + 1;
@ -97,25 +98,28 @@ namespace ICSharpCode.ILSpy
WriteCommentLine(output, codeLines[line - 1]); WriteCommentLine(output, codeLines[line - 1]);
} }
} else { } else {
WriteCommentLine(output, "no code"); output.Write("// ");
highlightingOutput?.BeginSpan(gray);
output.WriteLine("(hidden sequence point)");
highlightingOutput?.EndSpan();
} }
} }
base.WriteInstruction(output, instruction); base.WriteInstruction(output, instruction);
} }
HighlightingColor gray = new HighlightingColor { Foreground = new SimpleHighlightingBrush(Colors.DarkGray) }; HighlightingColor gray = new HighlightingColor { Foreground = new SimpleHighlightingBrush(Colors.DarkGray) };
HighlightingColor black = new HighlightingColor { Foreground = new SimpleHighlightingBrush(Colors.Black) };
void WriteHighlightedCommentLine(ISmartTextOutput output, string text, int startColumn, int endColumn, bool isSingleLine) void WriteHighlightedCommentLine(ISmartTextOutput output, string text, int startColumn, int endColumn, bool isSingleLine)
{ {
output.Write("// ");
output.BeginSpan(gray); output.BeginSpan(gray);
if (isSingleLine) if (isSingleLine)
output.Write("// " + text.Substring(0, startColumn).TrimStart()); output.Write(text.Substring(0, startColumn).TrimStart());
else else
output.Write("// " + text.Substring(0, startColumn)); output.Write(text.Substring(0, startColumn));
output.BeginSpan(black);
output.Write(text.Substring(startColumn, endColumn - startColumn));
output.EndSpan(); output.EndSpan();
output.Write(text.Substring(startColumn, endColumn - startColumn));
output.BeginSpan(gray);
output.Write(text.Substring(endColumn)); output.Write(text.Substring(endColumn));
output.EndSpan(); output.EndSpan();
output.WriteLine(); output.WriteLine();

Loading…
Cancel
Save