Browse Source

Now elements other than methods can be disassembled as well.

pull/1/head
Daniel Grunwald 15 years ago
parent
commit
3d93236b28
  1. 38
      ILSpy/Disassembler/DisassemblerHelpers.cs
  2. 31
      ILSpy/Disassembler/ILLanguage.cs
  3. 235
      ILSpy/Disassembler/ReflectionDisassembler.cs
  4. 6
      ILSpy/EventTreeNode.cs
  5. 24
      ILSpy/ExtensionMethods.cs
  6. 6
      ILSpy/FieldTreeNode.cs
  7. 2
      ILSpy/ILSpy.csproj
  8. 78
      ILSpy/ITextOutput.cs
  9. 2
      ILSpy/Language.cs
  10. 6
      ILSpy/PropertyTreeNode.cs
  11. 21
      ILSpy/TextView/DecompilerTextView.cs
  12. 15
      ILSpy/TextView/SmartTextOutput.cs
  13. 21
      ILSpy/TypeTreeNode.cs

38
ILSpy/Disassembler/DisassemblerHelpers.cs

@ -114,61 +114,61 @@ namespace ICSharpCode.ILSpy.Disassembler @@ -114,61 +114,61 @@ namespace ICSharpCode.ILSpy.Disassembler
return identifier;
}
public static void WriteTo(this TypeReference type, ITextOutput writer, bool onlyName = false, bool convertPrimitive = true)
public static void WriteTo(this TypeReference type, ITextOutput writer, bool onlyName = false, bool shortName = false)
{
if (type is PinnedType) {
writer.Write("pinned ");
type.GetElementType().WriteTo(writer, onlyName, convertPrimitive);
type.GetElementType().WriteTo(writer, onlyName, shortName);
} else if (type is ArrayType) {
ArrayType at = (ArrayType)type;
at.ElementType.WriteTo(writer, onlyName, convertPrimitive);
at.ElementType.WriteTo(writer, onlyName, shortName);
writer.Write('[');
writer.Write(string.Join(", ", at.Dimensions));
writer.Write(']');
} else if (type is GenericParameter) {
writer.WriteReference(type.Name, type);
} else if (type is ByReferenceType) {
type.GetElementType().WriteTo(writer, onlyName, convertPrimitive);
type.GetElementType().WriteTo(writer, onlyName, shortName);
writer.Write('&');
} else if (type is PointerType) {
type.GetElementType().WriteTo(writer, onlyName, convertPrimitive);
type.GetElementType().WriteTo(writer, onlyName, shortName);
writer.Write('*');
} else if (type is GenericInstanceType) {
type.GetElementType().WriteTo(writer, onlyName, convertPrimitive);
type.GetElementType().WriteTo(writer, onlyName, shortName);
writer.Write('<');
var arguments = ((GenericInstanceType)type).GenericArguments;
for (int i = 0; i < arguments.Count; i++) {
if (i > 0)
writer.Write(", ");
arguments[i].WriteTo(writer, onlyName, convertPrimitive);
arguments[i].WriteTo(writer, onlyName, shortName);
}
writer.Write('>');
} else if (type is OptionalModifierType) {
writer.Write("modopt(");
((OptionalModifierType)type).ModifierType.WriteTo(writer, true, false);
((OptionalModifierType)type).ModifierType.WriteTo(writer, true, shortName);
writer.Write(") ");
type.GetElementType().WriteTo(writer, onlyName, convertPrimitive);
type.GetElementType().WriteTo(writer, onlyName, shortName);
} else if (type is RequiredModifierType) {
writer.Write("modreq(");
((RequiredModifierType)type).ModifierType.WriteTo(writer, true, false);
((RequiredModifierType)type).ModifierType.WriteTo(writer, true, shortName);
writer.Write(") ");
type.GetElementType().WriteTo(writer, onlyName, convertPrimitive);
type.GetElementType().WriteTo(writer, onlyName, shortName);
} else {
string name = PrimitiveTypeName(type);
if (name != null) {
writer.Write(name);
} else {
if (!onlyName)
writer.Write(type.IsValueType ? "valuetype " : "class ");
if (type.DeclaringType != null) {
type.DeclaringType.WriteTo(writer, true, false);
type.DeclaringType.WriteTo(writer, true, shortName);
writer.Write('/');
writer.WriteReference(Escape(type.Name), type);
} else {
string name = ShortTypeName(type);
if (name != null) {
writer.Write(name);
} else {
if (!type.IsDefinition && type.Scope != null && !(type is TypeSpecification))
if (!type.IsDefinition && type.Scope != null && !shortName && !(type is TypeSpecification))
writer.Write("[{0}]", Escape(type.Scope.Name));
writer.WriteReference(type.FullName, type);
writer.WriteReference(shortName ? type.Name : type.FullName, type);
}
}
}
@ -225,7 +225,7 @@ namespace ICSharpCode.ILSpy.Disassembler @@ -225,7 +225,7 @@ namespace ICSharpCode.ILSpy.Disassembler
writer.Write(s);
}
public static string ShortTypeName(this TypeReference type)
public static string PrimitiveTypeName(this TypeReference type)
{
switch (type.FullName) {
case "System.SByte":

31
ILSpy/Disassembler/ILLanguage.cs

@ -41,9 +41,40 @@ namespace ICSharpCode.ILSpy.Disassembler @@ -41,9 +41,40 @@ namespace ICSharpCode.ILSpy.Disassembler
get { return detectControlStructure ? "IL (structured)" : "IL"; }
}
public override ICSharpCode.AvalonEdit.Highlighting.IHighlightingDefinition SyntaxHighlighting {
get { return ICSharpCode.AvalonEdit.Highlighting.HighlightingManager.Instance.GetDefinition("ILAsm"); }
}
public override void Decompile(MethodDefinition method, ITextOutput output, CancellationToken cancellationToken)
{
new ReflectionDisassembler(output, detectControlStructure, cancellationToken).DisassembleMethod(method);
}
public override void Decompile(FieldDefinition field, ITextOutput output, CancellationToken cancellationToken)
{
new ReflectionDisassembler(output, detectControlStructure, cancellationToken).DisassembleField(field);
}
public override void Decompile(PropertyDefinition property, ITextOutput output, CancellationToken cancellationToken)
{
new ReflectionDisassembler(output, detectControlStructure, cancellationToken).DisassembleProperty(property);
}
public override void Decompile(EventDefinition ev, ITextOutput output, CancellationToken cancellationToken)
{
new ReflectionDisassembler(output, detectControlStructure, cancellationToken).DisassembleEvent(ev);
}
public override void Decompile(TypeDefinition type, ITextOutput output, CancellationToken cancellationToken)
{
new ReflectionDisassembler(output, detectControlStructure, cancellationToken).DisassembleType(type);
}
public override string TypeToString(TypeReference t)
{
PlainTextOutput output = new PlainTextOutput();
t.WriteTo(output, true, true);
return output.ToString();
}
}
}

235
ILSpy/Disassembler/ReflectionDisassembler.cs

@ -17,6 +17,7 @@ namespace ICSharpCode.ILSpy.Disassembler @@ -17,6 +17,7 @@ namespace ICSharpCode.ILSpy.Disassembler
{
ITextOutput output;
CancellationToken cancellationToken;
bool detectControlStructure;
MethodBodyDisassembler methodBodyDisassembler;
public ReflectionDisassembler(ITextOutput output, bool detectControlStructure, CancellationToken cancellationToken)
@ -25,9 +26,11 @@ namespace ICSharpCode.ILSpy.Disassembler @@ -25,9 +26,11 @@ namespace ICSharpCode.ILSpy.Disassembler
throw new ArgumentNullException("output");
this.output = output;
this.cancellationToken = cancellationToken;
this.detectControlStructure = detectControlStructure;
this.methodBodyDisassembler = new MethodBodyDisassembler(output, detectControlStructure, cancellationToken);
}
#region Disassemble Method
EnumNameCollection<MethodAttributes> methodAttributeFlags = new EnumNameCollection<MethodAttributes>() {
{ MethodAttributes.Static, "static" },
{ MethodAttributes.Final, "final" },
@ -72,14 +75,18 @@ namespace ICSharpCode.ILSpy.Disassembler @@ -72,14 +75,18 @@ namespace ICSharpCode.ILSpy.Disassembler
};
public void DisassembleMethod(MethodDefinition method)
{
// write method header
output.WriteDefinition(".method ", method);
DisassembleMethodInternal(method);
}
void DisassembleMethodInternal(MethodDefinition method)
{
// .method public hidebysig specialname
// instance default class [mscorlib]System.IO.TextWriter get_BaseWriter () cil managed
//
// write method header
output.WriteDefinition(".method ", method);
//emit flags
WriteEnum(method.Attributes & MethodAttributes.MemberAccessMask, methodVisibility);
WriteFlags(method.Attributes & ~MethodAttributes.MemberAccessMask, methodAttributeFlags);
@ -95,7 +102,7 @@ namespace ICSharpCode.ILSpy.Disassembler @@ -95,7 +102,7 @@ namespace ICSharpCode.ILSpy.Disassembler
//return type
method.ReturnType.WriteTo(output, false, true);
method.ReturnType.WriteTo(output);
output.Write(' ');
output.Write(DisassemblerHelpers.Escape(method.Name));
@ -139,7 +146,221 @@ namespace ICSharpCode.ILSpy.Disassembler @@ -139,7 +146,221 @@ namespace ICSharpCode.ILSpy.Disassembler
output.WriteLine();
}
}
#endregion
#region Disassemble Field
EnumNameCollection<FieldAttributes> fieldVisibility = new EnumNameCollection<FieldAttributes>() {
{ FieldAttributes.Private, "private" },
{ FieldAttributes.FamANDAssem, "famandassem" },
{ FieldAttributes.Assembly, "assembly" },
{ FieldAttributes.Family, "family" },
{ FieldAttributes.FamORAssem, "famorassem" },
{ FieldAttributes.Public, "public" },
};
EnumNameCollection<FieldAttributes> fieldAttributes = new EnumNameCollection<FieldAttributes>() {
{ FieldAttributes.Static, "static" },
{ FieldAttributes.Literal, "literal" },
{ FieldAttributes.InitOnly, "initonly" },
{ FieldAttributes.SpecialName, "specialname" },
{ FieldAttributes.RTSpecialName, "rtspecialname" },
};
public void DisassembleField(FieldDefinition field)
{
output.WriteDefinition(".field ", field);
WriteEnum(field.Attributes & FieldAttributes.FieldAccessMask, fieldVisibility);
WriteFlags(field.Attributes & ~(FieldAttributes.FieldAccessMask | FieldAttributes.HasDefault), fieldAttributes);
field.FieldType.WriteTo(output);
output.Write(' ');
output.Write(DisassemblerHelpers.Escape(field.Name));
if (field.HasConstant) {
output.Write(" = ");
DisassemblerHelpers.WriteOperand(output, field.Constant);
}
output.WriteLine();
}
#endregion
#region Disassemble Property
EnumNameCollection<PropertyAttributes> propertyAttributes = new EnumNameCollection<PropertyAttributes>() {
{ PropertyAttributes.SpecialName, "specialname" },
{ PropertyAttributes.RTSpecialName, "rtspecialname" },
{ PropertyAttributes.HasDefault, "hasdefault" },
};
public void DisassembleProperty(PropertyDefinition property)
{
output.WriteDefinition(".property ", property);
WriteFlags(property.Attributes, propertyAttributes);
property.PropertyType.WriteTo(output);
output.Write(' ');
output.WriteLine(DisassemblerHelpers.Escape(property.Name));
OpenBlock();
WriteAttributes(property.CustomAttributes);
WriteNestedMethod(".get", property.GetMethod);
WriteNestedMethod(".set", property.SetMethod);
foreach (var method in property.OtherMethods) {
WriteNestedMethod(".method", method);
}
CloseBlock();
}
void WriteNestedMethod(string keyword, MethodDefinition method)
{
if (method == null)
return;
if (detectControlStructure) {
output.WriteDefinition(keyword, method);
output.Write(' ');
DisassembleMethodInternal(method);
} else {
output.Write(keyword);
output.Write(' ');
method.WriteTo(output);
output.WriteLine();
}
}
#endregion
#region Disassemble Event
EnumNameCollection<EventAttributes> eventAttributes = new EnumNameCollection<EventAttributes>() {
{ EventAttributes.SpecialName, "specialname" },
{ EventAttributes.RTSpecialName, "rtspecialname" },
};
public void DisassembleEvent(EventDefinition ev)
{
output.WriteDefinition(".event ", ev);
WriteFlags(ev.Attributes, eventAttributes);
ev.EventType.WriteTo(output);
output.Write(' ');
output.WriteLine(DisassemblerHelpers.Escape(ev.Name));
OpenBlock();
WriteAttributes(ev.CustomAttributes);
WriteNestedMethod(".add", ev.AddMethod);
WriteNestedMethod(".remove", ev.RemoveMethod);
WriteNestedMethod(".invoke", ev.InvokeMethod);
foreach (var method in ev.OtherMethods) {
WriteNestedMethod(".method", method);
}
CloseBlock();
}
#endregion
#region Disassembly Type
EnumNameCollection<TypeAttributes> typeVisibility = new EnumNameCollection<TypeAttributes>() {
{ TypeAttributes.Public, "public" },
{ TypeAttributes.NotPublic, "private" },
{ TypeAttributes.NestedPublic, "nested public" },
{ TypeAttributes.NestedPrivate, "nested private" },
{ TypeAttributes.NestedAssembly, "nested assembly" },
{ TypeAttributes.NestedFamily, "nested family" },
{ TypeAttributes.NestedFamANDAssem, "nested famandassem" },
{ TypeAttributes.NestedFamORAssem, "nested famorassem" },
};
EnumNameCollection<TypeAttributes> typeLayout = new EnumNameCollection<TypeAttributes>() {
{ TypeAttributes.AutoLayout, "auto" },
{ TypeAttributes.SequentialLayout, "sequential" },
{ TypeAttributes.ExplicitLayout, "explicit" },
};
EnumNameCollection<TypeAttributes> typeStringFormat = new EnumNameCollection<TypeAttributes>() {
{ TypeAttributes.AutoClass, "auto" },
{ TypeAttributes.AnsiClass, "ansi" },
{ TypeAttributes.UnicodeClass, "unicode" },
};
EnumNameCollection<TypeAttributes> typeAttributes = new EnumNameCollection<TypeAttributes>() {
{ TypeAttributes.Abstract, "abstract" },
{ TypeAttributes.Sealed, "sealed" },
{ TypeAttributes.SpecialName, "specialname" },
{ TypeAttributes.Import, "import" },
{ TypeAttributes.Serializable, "serializable" },
{ TypeAttributes.BeforeFieldInit, "beforefieldinit" },
};
public void DisassembleType(TypeDefinition type)
{
output.WriteDefinition(".class ", type);
if ((type.Attributes & TypeAttributes.ClassSemanticMask) == TypeAttributes.Interface)
output.Write("interface ");
WriteEnum(type.Attributes & TypeAttributes.VisibilityMask, typeVisibility);
WriteEnum(type.Attributes & TypeAttributes.LayoutMask, typeLayout);
WriteEnum(type.Attributes & TypeAttributes.StringFormatMask, typeStringFormat);
const TypeAttributes masks = TypeAttributes.ClassSemanticMask | TypeAttributes.VisibilityMask | TypeAttributes.LayoutMask | TypeAttributes.StringFormatMask;
WriteFlags(type.Attributes & ~masks, typeAttributes);
output.WriteLine(DisassemblerHelpers.Escape(type.Name));
if (type.BaseType != null) {
output.Indent();
output.Write("extends ");
type.BaseType.WriteTo(output);
output.Unindent();
output.WriteLine();
}
OpenBlock();
WriteAttributes(type.CustomAttributes);
if (type.HasLayoutInfo) {
output.WriteLine(".pack {0}", type.PackingSize);
output.WriteLine(".size {0}", type.ClassSize);
output.WriteLine();
}
if (type.HasNestedTypes) {
output.WriteCommentLine("// Nested Types");
foreach (var nestedType in type.NestedTypes) {
cancellationToken.ThrowIfCancellationRequested();
DisassembleType(nestedType);
}
output.WriteLine();
}
if (type.HasFields) {
output.WriteCommentLine("// Fields");
foreach (var field in type.Fields) {
cancellationToken.ThrowIfCancellationRequested();
DisassembleField(field);
}
output.WriteLine();
}
if (type.HasProperties) {
output.WriteCommentLine("// Properties");
foreach (var prop in type.Properties) {
cancellationToken.ThrowIfCancellationRequested();
DisassembleProperty(prop);
output.WriteLine();
}
output.WriteLine();
}
if (type.HasEvents) {
output.WriteCommentLine("// Events");
foreach (var ev in type.Events) {
cancellationToken.ThrowIfCancellationRequested();
DisassembleEvent(ev);
output.WriteLine();
}
output.WriteLine();
}
if (type.HasMethods) {
output.WriteCommentLine("// Methods");
var accessorMethods = type.GetAccessorMethods();
foreach (var m in type.Methods) {
cancellationToken.ThrowIfCancellationRequested();
if (!(detectControlStructure && accessorMethods.Contains(m))) {
DisassembleMethod(m);
output.WriteLine();
}
}
output.WriteLine();
}
CloseBlock();
}
#endregion
#region Helper methods
void WriteAttributes(Collection<CustomAttribute> attributes)
{
foreach (CustomAttribute a in attributes) {
@ -175,6 +396,7 @@ namespace ICSharpCode.ILSpy.Disassembler @@ -175,6 +396,7 @@ namespace ICSharpCode.ILSpy.Disassembler
void OpenBlock()
{
output.MarkFoldStart();
output.WriteLine("{");
output.Indent();
}
@ -182,7 +404,9 @@ namespace ICSharpCode.ILSpy.Disassembler @@ -182,7 +404,9 @@ namespace ICSharpCode.ILSpy.Disassembler
void CloseBlock()
{
output.Unindent();
output.WriteLine("}");
output.Write("}");
output.MarkFoldEnd();
output.WriteLine();
}
void WriteFlags<T>(T flags, EnumNameCollection<T> flagNames) where T : struct
@ -236,5 +460,6 @@ namespace ICSharpCode.ILSpy.Disassembler @@ -236,5 +460,6 @@ namespace ICSharpCode.ILSpy.Disassembler
return names.GetEnumerator();
}
}
#endregion
}
}

6
ILSpy/EventTreeNode.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Threading;
using ICSharpCode.TreeView;
using Mono.Cecil;
@ -72,5 +73,10 @@ namespace ICSharpCode.ILSpy @@ -72,5 +73,10 @@ namespace ICSharpCode.ILSpy
else
return FilterResult.Hidden;
}
public override void Decompile(Language language, ITextOutput output, CancellationToken cancellationToken)
{
language.Decompile(ev, output, cancellationToken);
}
}
}

24
ILSpy/ExtensionMethods.cs

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Markup;
using Mono.Cecil;
namespace ICSharpCode.ILSpy
{
@ -55,6 +56,29 @@ namespace ICSharpCode.ILSpy @@ -55,6 +56,29 @@ namespace ICSharpCode.ILSpy
output.WriteCommentLine(string.Format(format, args));
}
public static HashSet<MethodDefinition> GetAccessorMethods(this TypeDefinition type)
{
HashSet<MethodDefinition> accessorMethods = new HashSet<MethodDefinition>();
foreach (var property in type.Properties) {
accessorMethods.Add(property.GetMethod);
accessorMethods.Add(property.SetMethod);
if (property.HasOtherMethods) {
foreach (var m in property.OtherMethods)
accessorMethods.Add(m);
}
}
foreach (EventDefinition ev in type.Events) {
accessorMethods.Add(ev.AddMethod);
accessorMethods.Add(ev.RemoveMethod);
accessorMethods.Add(ev.InvokeMethod);
if (ev.HasOtherMethods) {
foreach (var m in ev.OtherMethods)
accessorMethods.Add(m);
}
}
return accessorMethods;
}
/// <summary>
/// Sets the value of a dependency property on <paramref name="targetObject"/> using a markup extension.
/// </summary>

6
ILSpy/FieldTreeNode.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Threading;
using ICSharpCode.TreeView;
using Mono.Cecil;
@ -60,5 +61,10 @@ namespace ICSharpCode.ILSpy @@ -60,5 +61,10 @@ namespace ICSharpCode.ILSpy
else
return FilterResult.Hidden;
}
public override void Decompile(Language language, ITextOutput output, CancellationToken cancellationToken)
{
language.Decompile(field, output, cancellationToken);
}
}
}

2
ILSpy/ILSpy.csproj

@ -126,7 +126,7 @@ @@ -126,7 +126,7 @@
<Compile Include="TextView\SmartTextOutput.cs" />
<Compile Include="TreeTraversal.cs" />
<Compile Include="TypeTreeNode.cs" />
<None Include="TextView\ILAsm-Mode.xshd" />
<EmbeddedResource Include="TextView\ILAsm-Mode.xshd" />
</ItemGroup>
<ItemGroup>
<Page Include="AboutDialog.xaml" />

78
ILSpy/ITextOutput.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Text;
namespace ICSharpCode.ILSpy
{
@ -30,5 +31,82 @@ namespace ICSharpCode.ILSpy @@ -30,5 +31,82 @@ namespace ICSharpCode.ILSpy
void WriteLine();
void WriteDefinition(string text, object definition);
void WriteReference(string text, object reference);
void MarkFoldStart(string collapsedText = "...", bool defaultClosed = false);
void MarkFoldEnd();
}
public class PlainTextOutput : ITextOutput
{
readonly StringBuilder b = new StringBuilder();
int indent;
bool needsIndent;
public override string ToString()
{
return b.ToString();
}
public void Indent()
{
indent++;
}
public void Unindent()
{
indent--;
}
void WriteIndent()
{
if (needsIndent) {
needsIndent = false;
for (int i = 0; i < indent; i++) {
b.Append('\t');
}
}
}
public void Write(char ch)
{
WriteIndent();
b.Append(ch);
}
public void Write(string text)
{
WriteIndent();
b.Append(text);
}
public void WriteCommentLine(string comment)
{
Write(comment);
WriteLine();
}
public void WriteLine()
{
b.AppendLine();
needsIndent = true;
}
public void WriteDefinition(string text, object definition)
{
Write(text);
}
public void WriteReference(string text, object reference)
{
Write(text);
}
void ITextOutput.MarkFoldStart(string collapsedText, bool defaultClosed)
{
}
void ITextOutput.MarkFoldEnd()
{
}
}
}

2
ILSpy/Language.cs

@ -55,7 +55,7 @@ namespace ICSharpCode.ILSpy @@ -55,7 +55,7 @@ namespace ICSharpCode.ILSpy
{
}
public string TypeToString(TypeReference t)
public virtual string TypeToString(TypeReference t)
{
return t.Name;
}

6
ILSpy/PropertyTreeNode.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Threading;
using ICSharpCode.TreeView;
using Mono.Cecil;
@ -72,5 +73,10 @@ namespace ICSharpCode.ILSpy @@ -72,5 +73,10 @@ namespace ICSharpCode.ILSpy
else
return FilterResult.Hidden;
}
public override void Decompile(Language language, ITextOutput output, CancellationToken cancellationToken)
{
language.Decompile(property, output, cancellationToken);
}
}
}

21
ILSpy/TextView/DecompilerTextView.cs

@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@ -10,7 +11,10 @@ using System.Windows; @@ -10,7 +11,10 @@ using System.Windows;
using System.Windows.Controls;
using System.Windows.Media.Animation;
using System.Windows.Threading;
using System.Xml;
using ICSharpCode.AvalonEdit;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.AvalonEdit.Highlighting.Xshd;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TextView
@ -28,6 +32,16 @@ namespace ICSharpCode.ILSpy.TextView @@ -28,6 +32,16 @@ namespace ICSharpCode.ILSpy.TextView
public DecompilerTextView()
{
HighlightingManager.Instance.RegisterHighlighting(
"ILAsm", new string[] { ".il" },
delegate {
using (Stream s = typeof(DecompilerTextView).Assembly.GetManifestResourceStream(typeof(DecompilerTextView), "ILAsm-Mode.xshd")) {
using (XmlTextReader reader = new XmlTextReader(s)) {
return HighlightingLoader.Load(reader, HighlightingManager.Instance);
}
}
});
InitializeComponent();
this.referenceElementGenerator = new ReferenceElementGenerator(this);
textEditor.TextArea.TextView.ElementGenerators.Add(referenceElementGenerator);
@ -47,8 +61,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -47,8 +61,7 @@ namespace ICSharpCode.ILSpy.TextView
if (previousCancellationTokenSource != null)
previousCancellationTokenSource.Cancel();
var task = RunDecompiler(ILSpy.Language.Current, treeNodes.ToArray(), myCancellationTokenSource.Token);
task.ContinueWith(
delegate {
Action continuation = delegate {
try {
if (currentCancellationTokenSource == myCancellationTokenSource) {
currentCancellationTokenSource = null;
@ -75,8 +88,8 @@ namespace ICSharpCode.ILSpy.TextView @@ -75,8 +88,8 @@ namespace ICSharpCode.ILSpy.TextView
} finally {
myCancellationTokenSource.Dispose();
}
},
TaskScheduler.FromCurrentSynchronizationContext());
};
task.ContinueWith(delegate { Dispatcher.BeginInvoke(DispatcherPriority.Normal, continuation); });
}
static Task<SmartTextOutput> RunDecompiler(ILSpy.Language language, ILSpyTreeNodeBase[] nodes, CancellationToken cancellationToken)

15
ILSpy/TextView/SmartTextOutput.cs

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
using System.Collections.Generic;
using System.Text;
using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Folding;
namespace ICSharpCode.ILSpy.TextView
{
@ -53,7 +54,9 @@ namespace ICSharpCode.ILSpy.TextView @@ -53,7 +54,9 @@ namespace ICSharpCode.ILSpy.TextView
int indent;
bool needsIndent;
TextSegmentCollection<ReferenceSegment> references = new TextSegmentCollection<ReferenceSegment>();
Stack<NewFolding> openFoldings = new Stack<NewFolding>();
public readonly List<NewFolding> Foldings = new List<NewFolding>();
public readonly DefinitionLookup DefinitionLookup = new DefinitionLookup();
public TextSegmentCollection<ReferenceSegment> References {
@ -125,5 +128,17 @@ namespace ICSharpCode.ILSpy.TextView @@ -125,5 +128,17 @@ namespace ICSharpCode.ILSpy.TextView
int end = b.Length;
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = reference });
}
public void MarkFoldStart(string collapsedText, bool defaultClosed)
{
openFoldings.Push(new NewFolding { StartOffset = b.Length, Name = collapsedText, DefaultClosed = defaultClosed });
}
public void MarkFoldEnd()
{
NewFolding f = openFoldings.Pop();
f.EndOffset = b.Length;
this.Foldings.Add(f);
}
}
}

21
ILSpy/TypeTreeNode.cs

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
using System.Windows.Media;
using ICSharpCode.TreeView;
@ -97,7 +98,6 @@ namespace ICSharpCode.ILSpy @@ -97,7 +98,6 @@ namespace ICSharpCode.ILSpy
foreach (FieldDefinition field in type.Fields) {
this.Children.Add(new FieldTreeNode(field));
}
HashSet<MethodDefinition> accessorMethods = new HashSet<MethodDefinition>();
// figure out the name of the indexer:
string defaultMemberName = null;
@ -109,23 +109,11 @@ namespace ICSharpCode.ILSpy @@ -109,23 +109,11 @@ namespace ICSharpCode.ILSpy
foreach (PropertyDefinition property in type.Properties) {
this.Children.Add(new PropertyTreeNode(property, property.Name == defaultMemberName));
accessorMethods.Add(property.GetMethod);
accessorMethods.Add(property.SetMethod);
if (property.HasOtherMethods) {
foreach (var m in property.OtherMethods)
accessorMethods.Add(m);
}
}
foreach (EventDefinition ev in type.Events) {
this.Children.Add(new EventTreeNode(ev));
accessorMethods.Add(ev.AddMethod);
accessorMethods.Add(ev.RemoveMethod);
accessorMethods.Add(ev.InvokeMethod);
if (ev.HasOtherMethods) {
foreach (var m in ev.OtherMethods)
accessorMethods.Add(m);
}
}
HashSet<MethodDefinition> accessorMethods = type.GetAccessorMethods();
foreach (MethodDefinition method in type.Methods) {
if (!accessorMethods.Contains(method)) {
this.Children.Add(new MethodTreeNode(method));
@ -133,6 +121,11 @@ namespace ICSharpCode.ILSpy @@ -133,6 +121,11 @@ namespace ICSharpCode.ILSpy
}
}
public override void Decompile(Language language, ITextOutput output, CancellationToken cancellationToken)
{
language.Decompile(type, output, cancellationToken);
}
#region Icon
enum ClassType
{

Loading…
Cancel
Save