diff --git a/ICSharpCode.Decompiler/PlainTextOutput.cs b/ICSharpCode.Decompiler/PlainTextOutput.cs index e7c6c9a47..f2d709cdd 100644 --- a/ICSharpCode.Decompiler/PlainTextOutput.cs +++ b/ICSharpCode.Decompiler/PlainTextOutput.cs @@ -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 { - /// - /// Base text output. - /// Provides access to code mappings. - /// - public abstract class BaseTextOutput : ITextOutput - { - #region Code mappings - Dictionary codeMappings = new Dictionary(); - - public Dictionary 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 - } - - /// - /// Plain text output. - /// Can be used when there's no UI. - /// - public sealed class PlainTextOutput : BaseTextOutput + public sealed class PlainTextOutput : ITextOutput { readonly TextWriter writer; int indent; @@ -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 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 } } - 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 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) { } } diff --git a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj index 0244a2d23..c42f04339 100644 --- a/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj @@ -14,7 +14,7 @@ 4 false False - 67,169,1058,728,1720 + 67,169,1058,728,1720,649 x86 diff --git a/ILSpy/Bookmarks/MemberBookmark.cs b/ILSpy/Bookmarks/MemberBookmark.cs index be51e4f5b..5731a518f 100644 --- a/ILSpy/Bookmarks/MemberBookmark.cs +++ b/ILSpy/Bookmarks/MemberBookmark.cs @@ -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 { 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 public override ImageSource Image { get { if (Member is TypeDefinition) { - return GetOverlayedImage(Member as TypeDefinition); + return TreeNodes.TypeTreeNode.GetIcon((TypeDefinition)Member); } return null; diff --git a/ILSpy/TextView/AvalonEditTextOutput.cs b/ILSpy/TextView/AvalonEditTextOutput.cs index 18cc09cda..12ec58488 100644 --- a/ILSpy/TextView/AvalonEditTextOutput.cs +++ b/ILSpy/TextView/AvalonEditTextOutput.cs @@ -67,7 +67,7 @@ namespace ICSharpCode.ILSpy.TextView /// /// Text output implementation for AvalonEdit. /// - 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 /// Embedded UIElements, see . internal readonly List>> UIElements = new List>>(); + internal readonly List DebuggerMemberMappings = new List(); + public AvalonEditTextOutput() { } @@ -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 } #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 } } - 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 } } - 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 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 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 }); } - public override void MarkFoldEnd() + public void MarkFoldEnd() { NewFolding f = openFoldings.Pop(); f.EndOffset = this.TextLength; @@ -249,25 +251,10 @@ namespace ICSharpCode.ILSpy.TextView this.UIElements.Add(new KeyValuePair>(this.TextLength, new Lazy(element))); } } - } - - internal static class Extentions - { - public static Dictionary ToDictionary(this DefinitionLookup definitions, Func lineNumber) + + public void AddDebuggerMemberMapping(MemberMapping memberMapping) { - if (definitions == null) - throw new ArgumentNullException("definitions"); - - var result = new Dictionary(); - - 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); } } } diff --git a/ILSpy/TextView/DecompilerTextView.cs b/ILSpy/TextView/DecompilerTextView.cs index ba6697784..45b3711b4 100644 --- a/ILSpy/TextView/DecompilerTextView.cs +++ b/ILSpy/TextView/DecompilerTextView.cs @@ -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 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 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