Browse Source

Introduce several new WriteReference overloads

pull/1198/head
Siegfried Pammer 7 years ago
parent
commit
4f8441e142
  1. 2
      ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs
  2. 12
      ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs
  3. 6
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  4. 4
      ICSharpCode.Decompiler/IL/ILReader.cs
  5. 4
      ICSharpCode.Decompiler/IL/ILVariable.cs
  6. 10
      ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs
  7. 2
      ICSharpCode.Decompiler/IL/Instructions/Block.cs
  8. 4
      ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs
  9. 2
      ICSharpCode.Decompiler/IL/Instructions/Branch.cs
  10. 2
      ICSharpCode.Decompiler/IL/Instructions/Leave.cs
  11. 2
      ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs
  12. 2
      ICSharpCode.Decompiler/IL/Instructions/TryInstruction.cs
  13. 29
      ICSharpCode.Decompiler/Output/ITextOutput.cs
  14. 25
      ICSharpCode.Decompiler/Output/PlainTextOutput.cs
  15. 4
      ICSharpCode.Decompiler/Output/TextTokenWriter.cs
  16. 4
      ILSpy/Languages/CSharpLanguage.cs
  17. 56
      ILSpy/MainWindow.xaml.cs
  18. 65
      ILSpy/TextView/AvalonEditTextOutput.cs

2
ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs

@ -64,7 +64,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -64,7 +64,7 @@ namespace ICSharpCode.Decompiler.Disassembler
if (offset == null)
writer.Write("null");
else
writer.WriteReference(OffsetToString(offset.Value), offset);
writer.WriteLocalReference(OffsetToString(offset.Value), offset);
}
public static void WriteTo(this SRM.ExceptionRegion exceptionHandler, Metadata.PEFile module, GenericContext context, ITextOutput writer)

12
ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs

@ -138,7 +138,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -138,7 +138,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Indent();
int index = 0;
foreach (var v in signature) {
output.WriteDefinition("[" + index + "] ", v);
output.WriteLocalReference("[" + index + "] ", v, isDefinition: true);
v(ILNameSyntax.TypeName);
if (index + 1 < signature.Length)
output.Write(',');
@ -298,16 +298,16 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -298,16 +298,16 @@ namespace ICSharpCode.Decompiler.Disassembler
}
}
ILOpCode opCode = ILParser.DecodeOpCode(ref blob);
output.WriteDefinition(DisassemblerHelpers.OffsetToString(offset), offset);
output.WriteLocalReference(DisassemblerHelpers.OffsetToString(offset), offset, isDefinition: true);
output.Write(": ");
if (opCode.IsDefined()) {
output.WriteReference(opCode.GetDisplayName(), new OpCodeInfo(opCode, opCode.GetDisplayName()));
output.WriteReference(new OpCodeInfo(opCode, opCode.GetDisplayName()));
switch (opCode.GetOperandType()) {
case OperandType.BrTarget:
case OperandType.ShortBrTarget:
output.Write(' ');
int targetOffset = ILParser.DecodeBranchTarget(ref blob, opCode);
output.WriteReference($"IL_{targetOffset:x4}", targetOffset, true);
output.WriteLocalReference($"IL_{targetOffset:x4}", targetOffset);
break;
case OperandType.Field:
case OperandType.Method:
@ -392,7 +392,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -392,7 +392,7 @@ namespace ICSharpCode.Decompiler.Disassembler
for (int i = 0; i < targets.Length; i++) {
if (i > 0)
output.Write(", ");
output.WriteReference($"IL_{targets[i]:x4}", targets[i], true);
output.WriteLocalReference($"IL_{targets[i]:x4}", targets[i]);
}
output.Write(")");
break;
@ -421,7 +421,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -421,7 +421,7 @@ namespace ICSharpCode.Decompiler.Disassembler
// split 16-bit value into two emitbyte directives
output.WriteLine($".emitbyte 0x{(byte)(opCodeValue >> 8):x}");
// add label
output.WriteDefinition(DisassemblerHelpers.OffsetToString(offset + 1), offset + 1);
output.WriteLocalReference(DisassemblerHelpers.OffsetToString(offset + 1), offset + 1, isDefinition: true);
output.Write(": ");
output.Write($".emitbyte 0x{(byte)(opCodeValue & 0xFF):x}");
} else {

6
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -398,7 +398,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -398,7 +398,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write('[');
output.Write(nameParts[1]);
output.Write(']');
output.WriteReference(nameParts[0], null); // TODO : hyperlink!
output.Write(nameParts[0]);
}
output.Write(" = {");
blob.ReadCompressedInteger(); // ?
@ -945,7 +945,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -945,7 +945,7 @@ namespace ICSharpCode.Decompiler.Disassembler
if (!md.IsNil) {
WriteMarshalInfo(metadata.GetBlobReader(md));
}
output.WriteDefinition(DisassemblerHelpers.Escape(metadata.GetString(p.Name)), p);
output.WriteLocalReference(DisassemblerHelpers.Escape(metadata.GetString(p.Name)), p, isDefinition: true);
} else {
signature.ParameterTypes[i](ILNameSyntax.Signature);
output.Write(" ''");
@ -1036,7 +1036,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1036,7 +1036,7 @@ namespace ICSharpCode.Decompiler.Disassembler
{
var metadata = module.Metadata;
var fieldDefinition = metadata.GetFieldDefinition(field);
output.WriteDefinition(".field ", field);
output.WriteReference(module, field, ".field ", isDefinition: true);
int offset = fieldDefinition.GetOffset();
if (offset > -1) {
output.Write("[" + offset + "] ");

4
ICSharpCode.Decompiler/IL/ILReader.cs

@ -428,7 +428,7 @@ namespace ICSharpCode.Decompiler.IL @@ -428,7 +428,7 @@ namespace ICSharpCode.Decompiler.IL
isFirstElement = false;
else
output.Write(", ");
output.WriteReference(element.Name, element, isLocal: true);
output.WriteLocalReference(element.Name, element);
output.Write(":");
output.Write(element.StackType);
}
@ -438,7 +438,7 @@ namespace ICSharpCode.Decompiler.IL @@ -438,7 +438,7 @@ namespace ICSharpCode.Decompiler.IL
output.Write('*');
else
output.Write(' ');
output.WriteDefinition("IL_" + inst.ILRange.Start.ToString("x4"), inst.ILRange.Start);
output.WriteLocalReference("IL_" + inst.ILRange.Start.ToString("x4"), inst.ILRange.Start, isDefinition: true);
output.Write(": ");
inst.WriteTo(output, new ILAstWritingOptions());
output.WriteLine();

4
ICSharpCode.Decompiler/IL/ILVariable.cs

@ -319,7 +319,7 @@ namespace ICSharpCode.Decompiler.IL @@ -319,7 +319,7 @@ namespace ICSharpCode.Decompiler.IL
default:
throw new ArgumentOutOfRangeException();
}
output.WriteDefinition(this.Name, this, isLocal: true);
output.WriteLocalReference(this.Name, this, isDefinition: true);
output.Write(" : ");
Type.WriteTo(output);
output.Write('(');
@ -340,7 +340,7 @@ namespace ICSharpCode.Decompiler.IL @@ -340,7 +340,7 @@ namespace ICSharpCode.Decompiler.IL
internal void WriteTo(ITextOutput output)
{
output.WriteReference(this.Name, this, isLocal: true);
output.WriteLocalReference(this.Name, this);
}
/// <summary>

10
ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs

@ -41,15 +41,15 @@ namespace ICSharpCode.Decompiler.IL @@ -41,15 +41,15 @@ namespace ICSharpCode.Decompiler.IL
public static void WriteTo(this IType type, ITextOutput output, ILNameSyntax nameSyntax = ILNameSyntax.ShortTypeName)
{
output.WriteReference(type.ReflectionName, type);
output.WriteReference(type, type.ReflectionName);
}
public static void WriteTo(this ISymbol symbol, ITextOutput output)
public static void WriteTo(this IMember member, ITextOutput output)
{
if (symbol is IMethod method && method.IsConstructor)
output.WriteReference(method.DeclaringType?.Name + "." + method.Name, symbol);
if (member is IMethod method && method.IsConstructor)
output.WriteReference(member, method.DeclaringType?.Name + "." + method.Name);
else
output.WriteReference(symbol.Name, symbol);
output.WriteReference(member, member.Name);
}
public static void WriteTo(this Interval interval, ITextOutput output, ILAstWritingOptions options)

2
ICSharpCode.Decompiler/IL/Instructions/Block.cs

@ -152,7 +152,7 @@ namespace ICSharpCode.Decompiler.IL @@ -152,7 +152,7 @@ namespace ICSharpCode.Decompiler.IL
{
ILRange.WriteTo(output, options);
output.Write("Block ");
output.WriteDefinition(Label, this);
output.WriteLocalReference(Label, this, isDefinition: true);
if (Kind != BlockKind.ControlFlow)
output.Write($" ({Kind})");
if (Parent is BlockContainer)

4
ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs

@ -118,7 +118,7 @@ namespace ICSharpCode.Decompiler.IL @@ -118,7 +118,7 @@ namespace ICSharpCode.Decompiler.IL
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
ILRange.WriteTo(output, options);
output.WriteDefinition("BlockContainer", this);
output.WriteLocalReference("BlockContainer", this, isDefinition: true);
output.Write(' ');
switch (Kind) {
case ContainerKind.Loop:
@ -145,7 +145,7 @@ namespace ICSharpCode.Decompiler.IL @@ -145,7 +145,7 @@ namespace ICSharpCode.Decompiler.IL
inst.WriteTo(output, options);
} else {
output.Write("stale reference to ");
output.WriteReference(inst.Label, inst, isLocal: true);
output.WriteLocalReference(inst.Label, inst);
}
output.WriteLine();
output.WriteLine();

2
ICSharpCode.Decompiler/IL/Instructions/Branch.cs

@ -116,7 +116,7 @@ namespace ICSharpCode.Decompiler.IL @@ -116,7 +116,7 @@ namespace ICSharpCode.Decompiler.IL
ILRange.WriteTo(output, options);
output.Write(OpCode);
output.Write(' ');
output.WriteReference(TargetLabel, (object)targetBlock ?? TargetILOffset, isLocal: true);
output.WriteLocalReference(TargetLabel, (object)targetBlock ?? TargetILOffset);
}
}

2
ICSharpCode.Decompiler/IL/Instructions/Leave.cs

@ -115,7 +115,7 @@ namespace ICSharpCode.Decompiler.IL @@ -115,7 +115,7 @@ namespace ICSharpCode.Decompiler.IL
output.Write(OpCode);
if (targetContainer != null) {
output.Write(' ');
output.WriteReference(TargetLabel, targetContainer, isLocal: true);
output.WriteLocalReference(TargetLabel, targetContainer);
output.Write(" (");
value.WriteTo(output, options);
output.Write(')');

2
ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs

@ -183,7 +183,7 @@ namespace ICSharpCode.Decompiler.IL @@ -183,7 +183,7 @@ namespace ICSharpCode.Decompiler.IL
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
ILRange.WriteTo(output, options);
output.WriteDefinition("case", this, isLocal: true);
output.WriteLocalReference("case", this, isDefinition: true);
output.Write(' ');
if (HasNullLabel) {
output.Write("null");

2
ICSharpCode.Decompiler/IL/Instructions/TryInstruction.cs

@ -165,7 +165,7 @@ namespace ICSharpCode.Decompiler.IL @@ -165,7 +165,7 @@ namespace ICSharpCode.Decompiler.IL
ILRange.WriteTo(output, options);
output.Write("catch ");
if (variable != null) {
output.WriteDefinition(variable.Name, variable);
output.WriteLocalReference(variable.Name, variable, isDefinition: true);
output.Write(" : ");
Disassembler.DisassemblerHelpers.WriteOperand(output, variable.Type);
}

29
ICSharpCode.Decompiler/Output/ITextOutput.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
@ -30,8 +31,11 @@ namespace ICSharpCode.Decompiler @@ -30,8 +31,11 @@ namespace ICSharpCode.Decompiler
void Write(char ch);
void Write(string text);
void WriteLine();
void WriteDefinition(string text, object definition, bool isLocal = true);
void WriteReference(string text, object reference, bool isLocal = false);
void WriteReference(OpCodeInfo opCode);
void WriteReference(PEFile module, EntityHandle handle, string text, bool isDefinition = false);
void WriteReference(IType type, string text, bool isDefinition = false);
void WriteReference(IMember member, string text, bool isDefinition = false);
void WriteLocalReference(string text, object reference, bool isDefinition = false);
void MarkFoldStart(string collapsedText = "...", bool defaultCollapsed = false);
void MarkFoldEnd();
@ -54,26 +58,5 @@ namespace ICSharpCode.Decompiler @@ -54,26 +58,5 @@ namespace ICSharpCode.Decompiler
{
output.WriteLine(string.Format(format, args));
}
public static void WriteReference(this ITextOutput output, PEFile module, EntityHandle handle, string text, bool isDefinition = false)
{
output.Write(text);
}
public static void WriteReference(this ITextOutput output, IType type, string text, bool isDefinition = false)
{
output.Write(text);
}
public static void WriteReference(this ITextOutput output, IMember member, string text, bool isDefinition = false)
{
output.Write(text);
}
public static void WriteLocalReference(this ITextOutput output, string text, object reference, bool isDefinition = false)
{
output.Write(text);
}
}
}

25
ICSharpCode.Decompiler/Output/PlainTextOutput.cs

@ -99,17 +99,32 @@ namespace ICSharpCode.Decompiler @@ -99,17 +99,32 @@ namespace ICSharpCode.Decompiler
line++;
column = 1;
}
public void WriteDefinition(string text, object definition, bool isLocal = true)
public void WriteReference(Disassembler.OpCodeInfo opCode)
{
Write(opCode.Name);
}
public void WriteReference(PEFile module, EntityHandle handle, string text, bool isDefinition = false)
{
Write(text);
}
public void WriteReference(string text, object reference, bool isLocal = false)
public void WriteReference(IType type, string text, bool isDefinition = false)
{
Write(text);
}
public void WriteReference(IMember member, string text, bool isDefinition = false)
{
Write(text);
}
public void WriteLocalReference(string text, object reference, bool isDefinition = false)
{
Write(text);
}
void ITextOutput.MarkFoldStart(string collapsedText, bool defaultCollapsed)
{
}

4
ICSharpCode.Decompiler/Output/TextTokenWriter.cs

@ -84,13 +84,13 @@ namespace ICSharpCode.Decompiler @@ -84,13 +84,13 @@ namespace ICSharpCode.Decompiler
var localDefinition = GetCurrentLocalDefinition();
if (localDefinition != null) {
output.WriteDefinition(identifier.Name, localDefinition);
output.WriteLocalReference(identifier.Name, localDefinition, isDefinition: true);
return;
}
var localRef = GetCurrentLocalReference();
if (localRef != null) {
output.WriteReference(identifier.Name, localRef, true);
output.WriteLocalReference(identifier.Name, localRef);
return;
}

4
ILSpy/Languages/CSharpLanguage.cs

@ -331,7 +331,7 @@ namespace ICSharpCode.ILSpy @@ -331,7 +331,7 @@ namespace ICSharpCode.ILSpy
var globalType = typeSystem.MainAssembly.TypeDefinitions.FirstOrDefault();
if (globalType != null) {
output.Write("// Global type: ");
output.WriteReference(globalType.FullName, globalType);
output.WriteReference(globalType, globalType.FullName);
output.WriteLine();
}
var metadata = module.Metadata;
@ -341,7 +341,7 @@ namespace ICSharpCode.ILSpy @@ -341,7 +341,7 @@ namespace ICSharpCode.ILSpy
var entrypoint = typeSystem.ResolveAsMethod(entrypointHandle);
if (entrypoint != null) {
output.Write("// Entry point: ");
output.WriteReference(entrypoint.DeclaringType.FullName + "." + entrypoint.Name, entrypoint);
output.WriteReference(entrypoint, entrypoint.DeclaringType.FullName + "." + entrypoint.Name);
output.WriteLine();
}
}

56
ILSpy/MainWindow.xaml.cs

@ -611,41 +611,6 @@ namespace ICSharpCode.ILSpy @@ -611,41 +611,6 @@ namespace ICSharpCode.ILSpy
return assemblyListTreeNode.FindPropertyNode(pd);
case IEvent ed:
return assemblyListTreeNode.FindEventNode(ed);
/*
case TypeReference tr:
var resolved = tr.Handle.Resolve(new SimpleMetadataResolveContext(tr.Module));
if (resolved != null && !resolved.IsNil)
return assemblyListTreeNode.FindTypeNode(resolved);
return null;
case TypeSpecification ts:
resolved = ts.Handle.Resolve(new SimpleMetadataResolveContext(ts.Module));
if (!resolved.IsNil)
return assemblyListTreeNode.FindTypeNode(resolved);
return null;
case MemberReference mr:
var resolvedMember = mr.Handle.Resolve(new SimpleMetadataResolveContext(mr.Module));
if (resolvedMember != null && !resolvedMember.IsNil) {
switch (resolvedMember) {
case FieldDefinition fd:
return assemblyListTreeNode.FindFieldNode(fd);
case MethodDefinition md:
return assemblyListTreeNode.FindMethodNode(md);
default:
throw new NotSupportedException();
}
}
return null;
case MethodSpecification ms:
resolvedMember = ms.Handle.Resolve(new SimpleMetadataResolveContext(ms.Module));
if (resolvedMember != null && !resolvedMember.IsNil) {
switch (resolvedMember) {
case MethodDefinition md:
return assemblyListTreeNode.FindMethodNode(md);
default:
throw new NotSupportedException();
}
}
return null;*/
default:
return null;
}
@ -666,11 +631,22 @@ namespace ICSharpCode.ILSpy @@ -666,11 +631,22 @@ namespace ICSharpCode.ILSpy
public Task JumpToReferenceAsync(object reference)
{
decompilationTask = TaskHelper.CompletedTask;
ILSpyTreeNode treeNode = FindTreeNode(reference);
if (treeNode != null) {
SelectNode(treeNode);
} else if (reference is Decompiler.Disassembler.OpCodeInfo opCode) {
OpenLink(opCode.Link);
switch (reference) {
case Decompiler.Disassembler.OpCodeInfo opCode:
OpenLink(opCode.Link);
break;
case ValueTuple<PEFile, System.Reflection.Metadata.EntityHandle> unresolvedEntity:
var typeSystem = new DecompilerTypeSystem(unresolvedEntity.Item1, unresolvedEntity.Item1.GetAssemblyResolver());
if (unresolvedEntity.Item2.Kind.IsTypeKind())
reference = typeSystem.ResolveAsType(unresolvedEntity.Item2).GetDefinition();
else
reference = typeSystem.ResolveAsMember(unresolvedEntity.Item2);
goto default;
default:
ILSpyTreeNode treeNode = FindTreeNode(reference);
if (treeNode != null)
SelectNode(treeNode);
break;
}
return decompilationTask;
}

65
ILSpy/TextView/AvalonEditTextOutput.cs

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection.Metadata;
using System.Text;
using System.Windows;
@ -27,6 +28,8 @@ using ICSharpCode.AvalonEdit.Document; @@ -27,6 +28,8 @@ using ICSharpCode.AvalonEdit.Document;
using ICSharpCode.AvalonEdit.Folding;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using TextLocation = ICSharpCode.Decompiler.CSharp.Syntax.TextLocation;
namespace ICSharpCode.ILSpy.TextView
@ -206,26 +209,72 @@ namespace ICSharpCode.ILSpy.TextView @@ -206,26 +209,72 @@ namespace ICSharpCode.ILSpy.TextView
throw new OutputLengthExceededException();
}
}
public void WriteDefinition(string text, object definition, bool isLocal = true)
public void WriteReference(Decompiler.Disassembler.OpCodeInfo opCode)
{
WriteIndent();
int start = this.TextLength;
b.Append(opCode.Name);
int end = this.TextLength;
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = opCode });
}
public void WriteReference(PEFile module, EntityHandle handle, string text, bool isDefinition = false)
{
WriteIndent();
int start = this.TextLength;
b.Append(text);
int end = this.TextLength;
this.DefinitionLookup.AddDefinition(definition, this.TextLength);
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = definition, IsLocal = isLocal, IsLocalTarget = true });
if (isDefinition) {
this.DefinitionLookup.AddDefinition((module, handle), this.TextLength);
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = (module, handle) });
} else {
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = (module, handle) });
}
}
public void WriteReference(string text, object reference, bool isLocal = false)
public void WriteReference(IType type, string text, bool isDefinition = false)
{
WriteIndent();
int start = this.TextLength;
b.Append(text);
int end = this.TextLength;
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = reference, IsLocal = isLocal });
if (isDefinition) {
this.DefinitionLookup.AddDefinition(type, this.TextLength);
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = type });
} else {
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = type });
}
}
public void WriteReference(IMember member, string text, bool isDefinition = false)
{
WriteIndent();
int start = this.TextLength;
b.Append(text);
int end = this.TextLength;
if (isDefinition) {
this.DefinitionLookup.AddDefinition(member, this.TextLength);
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = member });
} else {
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = member });
}
}
public void WriteLocalReference(string text, object reference, bool isDefinition = false)
{
WriteIndent();
int start = this.TextLength;
b.Append(text);
int end = this.TextLength;
if (isDefinition) {
this.DefinitionLookup.AddDefinition(reference, this.TextLength);
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = reference, IsLocal = true, IsLocalTarget = true });
} else {
references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = reference, IsLocal = true });
}
}
public void MarkFoldStart(string collapsedText = "...", bool defaultCollapsed = false)
{
WriteIndent();

Loading…
Cancel
Save