Browse Source

Store debugger member mappings in a simple list in the text output; copy the entries into the DebugInformation only when the output gets displayed.

MemberBookmark: Re-use the GetIcon methods from the TreeNodes.
pull/285/head
Daniel Grunwald 14 years ago
parent
commit
c542648d87
  1. 71
      ICSharpCode.Decompiler/PlainTextOutput.cs
  2. 2
      ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
  3. 111
      ILSpy/Bookmarks/MemberBookmark.cs
  4. 45
      ILSpy/TextView/AvalonEditTextOutput.cs
  5. 35
      ILSpy/TextView/DecompilerTextView.cs

71
ICSharpCode.Decompiler/PlainTextOutput.cs

@ -17,57 +17,12 @@ @@ -17,57 +17,12 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.IO;
using ICSharpCode.NRefactory;
using Mono.Cecil;
namespace ICSharpCode.Decompiler
{
/// <summary>
/// Base text output.
/// <remarks>Provides access to code mappings.</remarks>
/// </summary>
public abstract class BaseTextOutput : ITextOutput
{
#region Code mappings
Dictionary<int, MemberMapping> codeMappings = new Dictionary<int, MemberMapping>();
public Dictionary<int, MemberMapping> CodeMappings {
get { return codeMappings; }
}
public virtual void AddDebuggerMemberMapping(MemberMapping memberMapping)
{
if (memberMapping == null)
throw new ArgumentNullException("memberMapping");
int token = memberMapping.MetadataToken;
codeMappings.Add(token, memberMapping);
}
#endregion
#region ITextOutput members
public abstract TextLocation Location { get; }
public abstract void Indent();
public abstract void Unindent();
public abstract void Write(char ch);
public abstract void Write(string text);
public abstract void WriteLine();
public abstract void WriteDefinition(string text, object definition, bool isLocal);
public abstract void WriteReference(string text, object reference, bool isLocal);
public abstract void MarkFoldStart(string collapsedText, bool defaultCollapsed);
public abstract void MarkFoldEnd();
#endregion
}
/// <summary>
/// Plain text output.
/// <remarks>Can be used when there's no UI.</remarks>
/// </summary>
public sealed class PlainTextOutput : BaseTextOutput
public sealed class PlainTextOutput : ITextOutput
{
readonly TextWriter writer;
int indent;
@ -88,7 +43,7 @@ namespace ICSharpCode.Decompiler @@ -88,7 +43,7 @@ namespace ICSharpCode.Decompiler
this.writer = new StringWriter();
}
public override TextLocation Location {
public TextLocation Location {
get {
return new TextLocation(line, column + (needsIndent ? indent : 0));
}
@ -99,12 +54,12 @@ namespace ICSharpCode.Decompiler @@ -99,12 +54,12 @@ namespace ICSharpCode.Decompiler
return writer.ToString();
}
public override void Indent()
public void Indent()
{
indent++;
}
public override void Unindent()
public void Unindent()
{
indent--;
}
@ -120,21 +75,21 @@ namespace ICSharpCode.Decompiler @@ -120,21 +75,21 @@ namespace ICSharpCode.Decompiler
}
}
public override void Write(char ch)
public void Write(char ch)
{
WriteIndent();
writer.Write(ch);
column++;
}
public override void Write(string text)
public void Write(string text)
{
WriteIndent();
writer.Write(text);
column += text.Length;
}
public override void WriteLine()
public void WriteLine()
{
writer.WriteLine();
needsIndent = true;
@ -142,21 +97,25 @@ namespace ICSharpCode.Decompiler @@ -142,21 +97,25 @@ namespace ICSharpCode.Decompiler
column = 1;
}
public override void WriteDefinition(string text, object definition, bool isLocal)
public void WriteDefinition(string text, object definition, bool isLocal)
{
Write(text);
}
public override void WriteReference(string text, object reference, bool isLocal)
public void WriteReference(string text, object reference, bool isLocal)
{
Write(text);
}
public override void MarkFoldStart(string collapsedText, bool defaultCollapsed)
void ITextOutput.MarkFoldStart(string collapsedText, bool defaultCollapsed)
{
}
void ITextOutput.MarkFoldEnd()
{
}
public override void MarkFoldEnd()
void ITextOutput.AddDebuggerMemberMapping(MemberMapping memberMapping)
{
}
}

2
ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj

@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<CheckForOverflowUnderflow>False</CheckForOverflowUnderflow>
<NoWarn>67,169,1058,728,1720</NoWarn>
<NoWarn>67,169,1058,728,1720,649</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'x86' ">
<PlatformTarget>x86</PlatformTarget>

111
ILSpy/Bookmarks/MemberBookmark.cs

@ -52,19 +52,19 @@ namespace ICSharpCode.ILSpy.Bookmarks @@ -52,19 +52,19 @@ namespace ICSharpCode.ILSpy.Bookmarks
public virtual ImageSource Image {
get {
if (member is FieldDefinition)
return GetOverlayedImage(member as FieldDefinition, MemberIcon.Field);
return TreeNodes.FieldTreeNode.GetIcon((FieldDefinition)member);
if (member is PropertyDefinition)
return GetOverlayedImage(member as PropertyDefinition, MemberIcon.Property);
return TreeNodes.PropertyTreeNode.GetIcon((PropertyDefinition)member);
if (member is EventDefinition)
return GetOverlayedImage(member as EventDefinition, MemberIcon.Event);
return TreeNodes.EventTreeNode.GetIcon((EventDefinition)member);
if (member is MethodDefinition)
return GetOverlayedImage(member as MethodDefinition, MemberIcon.Method);
return TreeNodes.MethodTreeNode.GetIcon((MethodDefinition)member);
if (member is TypeDefinition)
return GetOverlayedImage(member as TypeDefinition);
return TreeNodes.TypeTreeNode.GetIcon((TypeDefinition)member);
return null;
}
@ -94,105 +94,6 @@ namespace ICSharpCode.ILSpy.Bookmarks @@ -94,105 +94,6 @@ namespace ICSharpCode.ILSpy.Bookmarks
{
throw new NotSupportedException();
}
#region Overlayed images
internal ImageSource GetOverlayedImage(TypeDefinition typeDef)
{
TypeIcon icon = TypeIcon.Class;
if (typeDef.IsEnum)
icon = TypeIcon.Enum;
if (typeDef.IsValueType)
icon = TypeIcon.Struct;
if (typeDef.IsInterface)
icon = TypeIcon.Interface;
if (typeDef.BaseType.FullName == "System.MulticastDelegate" || typeDef.BaseType.FullName == "System.Delegate")
icon = TypeIcon.Delegate;
bool isStatic = false;
AccessOverlayIcon overlayIcon = AccessOverlayIcon.Private;
if (typeDef.IsNestedPrivate)
overlayIcon = AccessOverlayIcon.Public;
else if (typeDef.IsNestedAssembly || typeDef.IsNestedFamilyAndAssembly || typeDef.IsNotPublic)
overlayIcon = AccessOverlayIcon.Internal;
else if (typeDef.IsNestedFamily)
overlayIcon = AccessOverlayIcon.Protected;
else if (typeDef.IsNestedFamilyOrAssembly)
overlayIcon = AccessOverlayIcon.ProtectedInternal;
else if (typeDef.IsPublic || typeDef.IsNestedPublic)
overlayIcon = AccessOverlayIcon.Public;
if (typeDef.IsAbstract && typeDef.IsSealed)
isStatic = true;
return Images.GetIcon(icon, overlayIcon, isStatic);
}
ImageSource GetOverlayedImage(FieldDefinition fieldDef, MemberIcon icon)
{
bool isStatic = false;
AccessOverlayIcon overlayIcon = AccessOverlayIcon.Public;
if (fieldDef.IsPrivate)
overlayIcon = AccessOverlayIcon.Private;
else if (fieldDef.IsAssembly || fieldDef.IsFamilyAndAssembly)
overlayIcon = AccessOverlayIcon.Internal;
else if (fieldDef.IsFamily)
overlayIcon = AccessOverlayIcon.Protected;
else if (fieldDef.IsFamilyOrAssembly)
overlayIcon = AccessOverlayIcon.ProtectedInternal;
else if (fieldDef.IsPublic)
overlayIcon = AccessOverlayIcon.Public;
if (fieldDef.IsStatic)
isStatic = true;
return Images.GetIcon(icon, overlayIcon, isStatic);
}
ImageSource GetOverlayedImage(MethodDefinition methodDef, MemberIcon icon)
{
bool isStatic = false;
AccessOverlayIcon overlayIcon = AccessOverlayIcon.Public;
if (methodDef == null)
return Images.GetIcon(icon, overlayIcon, isStatic);;
if (methodDef.IsPrivate)
overlayIcon = AccessOverlayIcon.Private;
else if (methodDef.IsAssembly || methodDef.IsFamilyAndAssembly)
overlayIcon = AccessOverlayIcon.Internal;
else if (methodDef.IsFamily)
overlayIcon = AccessOverlayIcon.Protected;
else if (methodDef.IsFamilyOrAssembly)
overlayIcon = AccessOverlayIcon.ProtectedInternal;
else if (methodDef.IsPublic)
overlayIcon = AccessOverlayIcon.Public;
if (methodDef.IsStatic)
isStatic = true;
return Images.GetIcon(icon, overlayIcon, isStatic);
}
ImageSource GetOverlayedImage(PropertyDefinition propDef, MemberIcon icon)
{
bool isStatic = false;
AccessOverlayIcon overlayIcon = AccessOverlayIcon.Public;
return Images.GetIcon(propDef.IsIndexer() ? MemberIcon.Indexer : icon, overlayIcon, isStatic);
}
ImageSource GetOverlayedImage(EventDefinition eventDef, MemberIcon icon)
{
bool isStatic = false;
AccessOverlayIcon overlayIcon = AccessOverlayIcon.Public;
return Images.GetIcon(icon, overlayIcon, isStatic);
}
#endregion
}
public class TypeBookmark : MemberBookmark
@ -204,7 +105,7 @@ namespace ICSharpCode.ILSpy.Bookmarks @@ -204,7 +105,7 @@ namespace ICSharpCode.ILSpy.Bookmarks
public override ImageSource Image {
get {
if (Member is TypeDefinition) {
return GetOverlayedImage(Member as TypeDefinition);
return TreeNodes.TypeTreeNode.GetIcon((TypeDefinition)Member);
}
return null;

45
ILSpy/TextView/AvalonEditTextOutput.cs

@ -67,7 +67,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -67,7 +67,7 @@ namespace ICSharpCode.ILSpy.TextView
/// <summary>
/// Text output implementation for AvalonEdit.
/// </summary>
public sealed class AvalonEditTextOutput : BaseTextOutput, ISmartTextOutput
public sealed class AvalonEditTextOutput : ISmartTextOutput
{
int lastLineStart = 0;
int lineNumber = 1;
@ -94,6 +94,8 @@ namespace ICSharpCode.ILSpy.TextView @@ -94,6 +94,8 @@ namespace ICSharpCode.ILSpy.TextView
/// <summary>Embedded UIElements, see <see cref="UIElementGenerator"/>.</summary>
internal readonly List<KeyValuePair<int, Lazy<UIElement>>> UIElements = new List<KeyValuePair<int, Lazy<UIElement>>>();
internal readonly List<MemberMapping> DebuggerMemberMappings = new List<MemberMapping>();
public AvalonEditTextOutput()
{
}
@ -121,7 +123,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -121,7 +123,7 @@ namespace ICSharpCode.ILSpy.TextView
get { return b.Length; }
}
public override ICSharpCode.NRefactory.TextLocation Location {
public ICSharpCode.NRefactory.TextLocation Location {
get {
return new ICSharpCode.NRefactory.TextLocation(lineNumber, b.Length - lastLineStart + 1 + (needsIndent ? indent : 0));
}
@ -159,12 +161,12 @@ namespace ICSharpCode.ILSpy.TextView @@ -159,12 +161,12 @@ namespace ICSharpCode.ILSpy.TextView
}
#endregion
public override void Indent()
public void Indent()
{
indent++;
}
public override void Unindent()
public void Unindent()
{
indent--;
}
@ -180,19 +182,19 @@ namespace ICSharpCode.ILSpy.TextView @@ -180,19 +182,19 @@ namespace ICSharpCode.ILSpy.TextView
}
}
public override void Write(char ch)
public void Write(char ch)
{
WriteIndent();
b.Append(ch);
}
public override void Write(string text)
public void Write(string text)
{
WriteIndent();
b.Append(text);
}
public override void WriteLine()
public void WriteLine()
{
Debug.Assert(textDocument == null);
b.AppendLine();
@ -204,7 +206,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -204,7 +206,7 @@ namespace ICSharpCode.ILSpy.TextView
}
}
public override void WriteDefinition(string text, object definition, bool isLocal)
public void WriteDefinition(string text, object definition, bool isLocal)
{
WriteIndent();
int start = this.TextLength;
@ -214,7 +216,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -214,7 +216,7 @@ namespace ICSharpCode.ILSpy.TextView
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = definition, IsLocal = isLocal, IsLocalTarget = true });
}
public override void WriteReference(string text, object reference, bool isLocal)
public void WriteReference(string text, object reference, bool isLocal)
{
WriteIndent();
int start = this.TextLength;
@ -223,7 +225,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -223,7 +225,7 @@ namespace ICSharpCode.ILSpy.TextView
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = reference, IsLocal = isLocal });
}
public override void MarkFoldStart(string collapsedText, bool defaultCollapsed)
public void MarkFoldStart(string collapsedText, bool defaultCollapsed)
{
WriteIndent();
openFoldings.Push(
@ -234,7 +236,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -234,7 +236,7 @@ namespace ICSharpCode.ILSpy.TextView
});
}
public override void MarkFoldEnd()
public void MarkFoldEnd()
{
NewFolding f = openFoldings.Pop();
f.EndOffset = this.TextLength;
@ -249,25 +251,10 @@ namespace ICSharpCode.ILSpy.TextView @@ -249,25 +251,10 @@ namespace ICSharpCode.ILSpy.TextView
this.UIElements.Add(new KeyValuePair<int, Lazy<UIElement>>(this.TextLength, new Lazy<UIElement>(element)));
}
}
}
internal static class Extentions
{
public static Dictionary<MemberReference, int> ToDictionary(this DefinitionLookup definitions, Func<int, int> lineNumber)
public void AddDebuggerMemberMapping(MemberMapping memberMapping)
{
if (definitions == null)
throw new ArgumentNullException("definitions");
var result = new Dictionary<MemberReference, int>();
foreach (var element in definitions.definitions) {
if (!(element.Key is MemberReference))
continue;
result.Add((MemberReference)element.Key, lineNumber(element.Value));
}
return result;
DebuggerMemberMappings.Add(memberMapping);
}
}
}

35
ILSpy/TextView/DecompilerTextView.cs

@ -358,11 +358,23 @@ namespace ICSharpCode.ILSpy.TextView @@ -358,11 +358,23 @@ namespace ICSharpCode.ILSpy.TextView
Debug.WriteLine(" Updating folding: {0}", w.Elapsed); w.Restart();
}
// update debugger info
DebugInformation.CodeMappings = textOutput.DebuggerMemberMappings.ToDictionary(m => m.MetadataToken);
// update class bookmarks
var document = textEditor.Document;
manager.UpdateClassMemberBookmarks(textOutput.DefinitionLookup.ToDictionary(line => document.GetLineByOffset(line).LineNumber),
typeof(TypeBookmark),
typeof(MemberBookmark));
manager.Bookmarks.Clear();
foreach (var pair in textOutput.DefinitionLookup.definitions) {
MemberReference member = pair.Key as MemberReference;
int offset = pair.Value;
if (member != null) {
int line = document.GetLocation(offset).Line;
if (member is TypeDefinition)
manager.Bookmarks.Add(new TypeBookmark(member, line));
else
manager.Bookmarks.Add(new MemberBookmark(member, line));
}
}
}
#endregion
@ -535,9 +547,6 @@ namespace ICSharpCode.ILSpy.TextView @@ -535,9 +547,6 @@ namespace ICSharpCode.ILSpy.TextView
void DecompileNodes(DecompilationContext context, ITextOutput textOutput)
{
// reset debug information
DebugInformation.CodeMappings = null;
var nodes = context.TreeNodes;
for (int i = 0; i < nodes.Length; i++) {
if (i > 0)
@ -546,21 +555,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -546,21 +555,7 @@ namespace ICSharpCode.ILSpy.TextView
context.Options.CancellationToken.ThrowIfCancellationRequested();
nodes[i].Decompile(context.Language, textOutput, context.Options);
}
OnDecompilationFinished(textOutput);
}
void OnDecompilationFinished(ITextOutput textOutput)
{
if (!(textOutput is AvalonEditTextOutput))
return;
var output = textOutput as AvalonEditTextOutput;
// update debug inforomation
DebugInformation.CodeMappings = output.CodeMappings;
}
#endregion
#region WriteOutputLengthExceededMessage

Loading…
Cancel
Save