Browse Source

Rename Dom -> Metadata; Remove bogus abstraction

pull/1198/head
Siegfried Pammer 8 years ago
parent
commit
87ced033ba
  1. 2
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 16
      ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs
  3. 6
      ICSharpCode.Decompiler/CSharp/Transforms/AddXmlDocumentationTransform.cs
  4. 5
      ICSharpCode.Decompiler/CecilExtensions.cs
  5. 4
      ICSharpCode.Decompiler/Disassembler/BlobDecoder.cs
  6. 20
      ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs
  7. 455
      ICSharpCode.Decompiler/Disassembler/DomExtensions.cs
  8. 10
      ICSharpCode.Decompiler/Disassembler/ILStructure.cs
  9. 57
      ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs
  10. 29
      ICSharpCode.Decompiler/Disassembler/OpCodeInfo.cs
  11. 234
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  12. 389
      ICSharpCode.Decompiler/Documentation/XmlDocKeyProvider.cs
  13. 43
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  14. 168
      ICSharpCode.Decompiler/IL/ILOpCodes.tt
  15. 585
      ICSharpCode.Decompiler/Metadata/Dom.cs
  16. 3
      ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs
  17. 2
      ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs
  18. 108
      ICSharpCode.Decompiler/Metadata/ILOpCodes.cs
  19. 64
      ICSharpCode.Decompiler/Metadata/ILOpCodes.tt
  20. 0
      ICSharpCode.Decompiler/Metadata/LightJson/JsonArray.cs
  21. 0
      ICSharpCode.Decompiler/Metadata/LightJson/JsonObject.cs
  22. 0
      ICSharpCode.Decompiler/Metadata/LightJson/JsonValue.cs
  23. 0
      ICSharpCode.Decompiler/Metadata/LightJson/JsonValueType.cs
  24. 0
      ICSharpCode.Decompiler/Metadata/LightJson/Serialization/JsonParseException.cs
  25. 0
      ICSharpCode.Decompiler/Metadata/LightJson/Serialization/JsonReader.cs
  26. 0
      ICSharpCode.Decompiler/Metadata/LightJson/Serialization/JsonSerializationException.cs
  27. 0
      ICSharpCode.Decompiler/Metadata/LightJson/Serialization/JsonWriter.cs
  28. 0
      ICSharpCode.Decompiler/Metadata/LightJson/Serialization/TextPosition.cs
  29. 0
      ICSharpCode.Decompiler/Metadata/LightJson/Serialization/TextScanner.cs
  30. 193
      ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs
  31. 40
      ICSharpCode.Decompiler/Metadata/MetadataResolver.cs
  32. 114
      ICSharpCode.Decompiler/Metadata/OperandType.cs
  33. 2
      ICSharpCode.Decompiler/Metadata/SequencePoint.cs
  34. 4
      ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs
  35. 2
      ICSharpCode.Decompiler/Metadata/UnresolvedAssemblyNameReference.cs
  36. 204
      ICSharpCode.Decompiler/SRMExtensions.cs
  37. 62
      ICSharpCode.Decompiler/SRMHacks.cs
  38. 3
      ICSharpCode.Decompiler/TypeSystem/CecilLoader.cs
  39. 42
      ICSharpCode.Decompiler/TypeSystem/Implementation/TypeSpecification.cs
  40. 8
      ILSpy/ExtensionMethods.cs
  41. 1
      ILSpy/ILSpy.csproj
  42. 2
      ILSpy/Languages/ILAstLanguage.cs
  43. 47
      ILSpy/Languages/ILLanguage.cs
  44. 86
      ILSpy/Languages/ITypeProvider.cs
  45. 80
      ILSpy/Languages/Language.cs
  46. 2
      ILSpy/LoadedAssembly.cs
  47. 6
      ILSpy/MainWindow.xaml.cs
  48. 4
      ILSpy/SearchPane.cs
  49. 106
      ILSpy/SearchStrategies.cs
  50. 18
      ILSpy/TextView/DecompilerTextView.cs
  51. 1
      ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs
  52. 4
      ILSpy/TreeNodes/Analyzer/AnalyzerEntityTreeNode.cs
  53. 19
      ILSpy/TreeNodes/AssemblyListTreeNode.cs
  54. 12
      ILSpy/TreeNodes/AssemblyTreeNode.cs
  55. 41
      ILSpy/TreeNodes/BaseTypesEntryNode.cs
  56. 13
      ILSpy/TreeNodes/BaseTypesTreeNode.cs
  57. 16
      ILSpy/TreeNodes/DerivedTypesEntryNode.cs
  58. 23
      ILSpy/TreeNodes/DerivedTypesTreeNode.cs
  59. 65
      ILSpy/TreeNodes/EventTreeNode.cs
  60. 62
      ILSpy/TreeNodes/FieldTreeNode.cs
  61. 4
      ILSpy/TreeNodes/IMemberTreeNode.cs
  62. 39
      ILSpy/TreeNodes/MethodTreeNode.cs
  63. 68
      ILSpy/TreeNodes/PropertyTreeNode.cs
  64. 2
      ILSpy/TreeNodes/ResourceListTreeNode.cs
  65. 2
      ILSpy/TreeNodes/ResourceNodes/CursorResourceEntryNode.cs
  66. 2
      ILSpy/TreeNodes/ResourceNodes/IResourceNodeFactory.cs
  67. 2
      ILSpy/TreeNodes/ResourceNodes/IconResourceEntryNode.cs
  68. 2
      ILSpy/TreeNodes/ResourceNodes/ImageListResourceEntryNode.cs
  69. 2
      ILSpy/TreeNodes/ResourceNodes/ImageResourceEntryNode.cs
  70. 2
      ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs
  71. 2
      ILSpy/TreeNodes/ResourceNodes/ResourcesFileTreeNode.cs
  72. 2
      ILSpy/TreeNodes/ResourceNodes/XamlResourceNode.cs
  73. 2
      ILSpy/TreeNodes/ResourceNodes/XmlResourceNode.cs
  74. 57
      ILSpy/TreeNodes/TypeTreeNode.cs

2
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -1158,7 +1158,7 @@ namespace ICSharpCode.Decompiler.CSharp
/// ///
/// This only works correctly when the nodes in the syntax tree have line/column information. /// This only works correctly when the nodes in the syntax tree have line/column information.
/// </summary> /// </summary>
public Dictionary<ILFunction, List<Dom.SequencePoint>> CreateSequencePoints(SyntaxTree syntaxTree) public Dictionary<ILFunction, List<Metadata.SequencePoint>> CreateSequencePoints(SyntaxTree syntaxTree)
{ {
SequencePointBuilder spb = new SequencePointBuilder(); SequencePointBuilder spb = new SequencePointBuilder();
syntaxTree.AcceptVisitor(spb); syntaxTree.AcceptVisitor(spb);

16
ICSharpCode.Decompiler/CSharp/SequencePointBuilder.cs

@ -56,7 +56,7 @@ namespace ICSharpCode.Decompiler.CSharp
} }
} }
readonly List<(ILFunction, Dom.SequencePoint)> sequencePoints = new List<(ILFunction, Dom.SequencePoint)>(); readonly List<(ILFunction, Metadata.SequencePoint)> sequencePoints = new List<(ILFunction, Metadata.SequencePoint)>();
readonly HashSet<ILInstruction> mappedInstructions = new HashSet<ILInstruction>(); readonly HashSet<ILInstruction> mappedInstructions = new HashSet<ILInstruction>();
// Stack holding information for outer statements. // Stack holding information for outer statements.
@ -219,7 +219,7 @@ namespace ICSharpCode.Decompiler.CSharp
// use LongSet to deduplicate and merge the intervals // use LongSet to deduplicate and merge the intervals
var longSet = new LongSet(current.Intervals.Select(i => new LongInterval(i.Start, i.End))); var longSet = new LongSet(current.Intervals.Select(i => new LongInterval(i.Start, i.End)));
Debug.Assert(!longSet.IsEmpty); Debug.Assert(!longSet.IsEmpty);
sequencePoints.Add((current.Function, new Dom.SequencePoint { sequencePoints.Add((current.Function, new Metadata.SequencePoint {
Offset = (int)longSet.Intervals[0].Start, Offset = (int)longSet.Intervals[0].Start,
EndOffset = (int)longSet.Intervals[0].End, EndOffset = (int)longSet.Intervals[0].End,
StartLine = startLocation.Line, StartLine = startLocation.Line,
@ -277,18 +277,18 @@ namespace ICSharpCode.Decompiler.CSharp
/// <summary> /// <summary>
/// Called after the visitor is done to return the results. /// Called after the visitor is done to return the results.
/// </summary> /// </summary>
internal Dictionary<ILFunction, List<Dom.SequencePoint>> GetSequencePoints() internal Dictionary<ILFunction, List<Metadata.SequencePoint>> GetSequencePoints()
{ {
var dict = new Dictionary<ILFunction, List<Dom.SequencePoint>>(); var dict = new Dictionary<ILFunction, List<Metadata.SequencePoint>>();
foreach (var (function, sequencePoint) in this.sequencePoints) { foreach (var (function, sequencePoint) in this.sequencePoints) {
if (!dict.TryGetValue(function, out var list)) { if (!dict.TryGetValue(function, out var list)) {
dict.Add(function, list = new List<Dom.SequencePoint>()); dict.Add(function, list = new List<Metadata.SequencePoint>());
} }
list.Add(sequencePoint); list.Add(sequencePoint);
} }
foreach (var (function, list) in dict.ToList()) { foreach (var (function, list) in dict.ToList()) {
// For each function, sort sequence points and fix overlaps+gaps // For each function, sort sequence points and fix overlaps+gaps
var newList = new List<Dom.SequencePoint>(); var newList = new List<Metadata.SequencePoint>();
int pos = 0; int pos = 0;
foreach (var sequencePoint in list.OrderBy(sp => sp.Offset).ThenBy(sp => sp.EndOffset)) { foreach (var sequencePoint in list.OrderBy(sp => sp.Offset).ThenBy(sp => sp.EndOffset)) {
if (sequencePoint.Offset < pos) { if (sequencePoint.Offset < pos) {
@ -305,7 +305,7 @@ namespace ICSharpCode.Decompiler.CSharp
} }
} else if (sequencePoint.Offset > pos) { } else if (sequencePoint.Offset > pos) {
// insert hidden sequence point in the gap. // insert hidden sequence point in the gap.
var hidden = new Dom.SequencePoint(); var hidden = new Metadata.SequencePoint();
hidden.Offset = pos; hidden.Offset = pos;
hidden.EndOffset = sequencePoint.Offset; hidden.EndOffset = sequencePoint.Offset;
hidden.SetHidden(); hidden.SetHidden();
@ -315,7 +315,7 @@ namespace ICSharpCode.Decompiler.CSharp
pos = sequencePoint.EndOffset; pos = sequencePoint.EndOffset;
} }
if (pos < function.CecilMethod.Body.CodeSize) { if (pos < function.CecilMethod.Body.CodeSize) {
var hidden = new Dom.SequencePoint(); var hidden = new Metadata.SequencePoint();
hidden.Offset = pos; hidden.Offset = pos;
hidden.EndOffset = function.CecilMethod.Body.CodeSize; hidden.EndOffset = function.CecilMethod.Body.CodeSize;
hidden.SetHidden(); hidden.SetHidden();

6
ICSharpCode.Decompiler/CSharp/Transforms/AddXmlDocumentationTransform.cs

@ -41,8 +41,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
return; return;
foreach (var entity in rootNode.DescendantsAndSelf.OfType<EntityDeclaration>()) { foreach (var entity in rootNode.DescendantsAndSelf.OfType<EntityDeclaration>()) {
var symbol = entity.GetSymbol(); var symbol = entity.GetSymbol();
Mono.Cecil.MemberReference mr; #warning TODO : replace with SRM
switch (symbol) { /*switch (symbol) {
case IMember member: case IMember member:
mr = context.TypeSystem.GetCecil(member); mr = context.TypeSystem.GetCecil(member);
break; break;
@ -57,7 +57,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
string doc = xmldoc.GetDocumentation(XmlDocKeyProvider.GetKey(mr)); string doc = xmldoc.GetDocumentation(XmlDocKeyProvider.GetKey(mr));
if (doc != null) { if (doc != null) {
InsertXmlDocumentation(entity, new StringReader(doc)); InsertXmlDocumentation(entity, new StringReader(doc));
} }*/
} }
} catch (XmlException ex) { } catch (XmlException ex) {
string[] msg = (" Exception while reading XmlDoc: " + ex).Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); string[] msg = (" Exception while reading XmlDoc: " + ex).Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);

5
ICSharpCode.Decompiler/CecilExtensions.cs

@ -219,11 +219,6 @@ namespace ICSharpCode.Decompiler
} }
} }
public static FullTypeName GetFullTypeName(this TypeDefinition typeDef)
{
return new FullTypeName(typeDef.FullName);
}
public static bool IsDelegate(this TypeDefinition type) public static bool IsDelegate(this TypeDefinition type)
{ {
if (type.BaseType != null && type.BaseType.Namespace == "System") { if (type.BaseType != null && type.BaseType.Namespace == "System") {

4
ICSharpCode.Decompiler/Disassembler/BlobDecoder.cs

@ -133,14 +133,10 @@ namespace ICSharpCode.Decompiler.Disassembler
public KeyValuePair<string, ResolveResult> ReadNamedArg() public KeyValuePair<string, ResolveResult> ReadNamedArg()
{ {
SymbolKind memberType;
var b = blob.ReadByte(); var b = blob.ReadByte();
switch (b) { switch (b) {
case 0x53: case 0x53:
memberType = SymbolKind.Field;
break;
case 0x54: case 0x54:
memberType = SymbolKind.Property;
break; break;
default: default:
throw new NotSupportedException(string.Format("Custom member type 0x{0:x} is not supported.", b)); throw new NotSupportedException(string.Format("Custom member type 0x{0:x} is not supported.", b));

20
ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs

@ -21,7 +21,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Text; using System.Text;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using SRM = System.Reflection.Metadata; using SRM = System.Reflection.Metadata;
@ -67,7 +67,7 @@ namespace ICSharpCode.Decompiler.Disassembler
writer.WriteReference(OffsetToString(offset.Value), offset); writer.WriteReference(OffsetToString(offset.Value), offset);
} }
public static void WriteTo(this SRM.ExceptionRegion exceptionHandler, Dom.MethodDefinition method, ITextOutput writer) public static void WriteTo(this SRM.ExceptionRegion exceptionHandler, Metadata.MethodDefinition method, ITextOutput writer)
{ {
writer.Write(".try "); writer.Write(".try ");
WriteOffsetReference(writer, exceptionHandler.TryOffset); WriteOffsetReference(writer, exceptionHandler.TryOffset);
@ -82,7 +82,7 @@ namespace ICSharpCode.Decompiler.Disassembler
} }
if (!exceptionHandler.CatchType.IsNil) { if (!exceptionHandler.CatchType.IsNil) {
writer.Write(' '); writer.Write(' ');
exceptionHandler.CatchType.CoerceTypeReference(method.Module).WriteTo(writer, new GenericContext(method)); exceptionHandler.CatchType.WriteTo(method.Module, writer, new GenericContext(method));
} }
writer.Write(' '); writer.Write(' ');
WriteOffsetReference(writer, exceptionHandler.HandlerOffset); WriteOffsetReference(writer, exceptionHandler.HandlerOffset);
@ -120,7 +120,7 @@ namespace ICSharpCode.Decompiler.Disassembler
public static string Escape(string identifier) public static string Escape(string identifier)
{ {
if (IsValidIdentifier(identifier) && !IL.ILOpCodeExtensions.ILKeywords.Contains(identifier)) { if (IsValidIdentifier(identifier) && !Metadata.ILOpCodeExtensions.ILKeywords.Contains(identifier)) {
return identifier; return identifier;
} else { } else {
// The ECMA specification says that ' inside SQString should be ecaped using an octal escape sequence, // The ECMA specification says that ' inside SQString should be ecaped using an octal escape sequence,
@ -129,15 +129,17 @@ namespace ICSharpCode.Decompiler.Disassembler
} }
} }
public static void WriteParameterReference(ITextOutput writer, Dom.MethodDefinition method, int sequence) public static void WriteParameterReference(ITextOutput writer, Metadata.MethodDefinition method, int sequence)
{ {
var metadata = method.Module.GetMetadataReader(); var metadata = method.Module.GetMetadataReader();
var signatureHeader = method.DecodeSignature(new FullTypeNameSignatureDecoder(metadata), default(Unit)).Header; var methodDefinition = metadata.GetMethodDefinition(method.Handle);
var signatureHeader = methodDefinition.DecodeSignature(new FullTypeNameSignatureDecoder(metadata), default(Unit)).Header;
int index = signatureHeader.IsInstance && !signatureHeader.HasExplicitThis ? sequence - 1 : sequence; int index = signatureHeader.IsInstance && !signatureHeader.HasExplicitThis ? sequence - 1 : sequence;
if (index < 0 || index >= method.Parameters.Count) { var parameters = methodDefinition.GetParameters();
if (index < 0 || index >= parameters.Count) {
writer.Write(sequence.ToString()); writer.Write(sequence.ToString());
} else { } else {
var param = metadata.GetParameter(method.Parameters.ElementAt(index)); var param = metadata.GetParameter(parameters.ElementAt(index));
if (param.Name.IsNil) { if (param.Name.IsNil) {
writer.Write(sequence.ToString()); writer.Write(sequence.ToString());
} else { } else {
@ -146,7 +148,7 @@ namespace ICSharpCode.Decompiler.Disassembler
} }
} }
public static void WriteVariableReference(ITextOutput writer, Dom.MethodDefinition method, int index) public static void WriteVariableReference(ITextOutput writer, Metadata.MethodDefinition method, int index)
{ {
writer.Write(index.ToString()); writer.Write(index.ToString());
} }

455
ICSharpCode.Decompiler/Disassembler/DomExtensions.cs

@ -20,220 +20,40 @@ using System;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Reflection; using System.Reflection;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using SRM = System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.Disassembler namespace ICSharpCode.Decompiler.Disassembler
{ {
public static class DomExtensions public static class MetadataExtensions
{ {
public static void WriteTo(this Dom.FieldDefinition field, ITextOutput output) public static void WriteTo(this Metadata.TypeDefinition typeDefinition, ITextOutput output, ILNameSyntax syntax = ILNameSyntax.Signature)
{ {
var signature = field.DecodeSignature(new DisassemblerSignatureProvider(field.Module, output), new GenericContext(field.DeclaringType)); var metadata = typeDefinition.Module.GetMetadataReader();
signature(ILNameSyntax.SignatureNoNamedTypeParameters); output.WriteReference(typeDefinition.This().GetFullTypeName(metadata).ToILNameString(), typeDefinition);
output.Write(' ');
field.DeclaringType.WriteTo(output, ILNameSyntax.TypeName);
output.Write("::");
output.Write(DisassemblerHelpers.Escape(field.Name));
}
public static void WriteTo(this IMemberReference member, ITextOutput output, GenericContext genericContext, ILNameSyntax syntax = ILNameSyntax.Signature)
{
void WriteParent(EntityHandle parentHandle)
{
var metadata = member.Module.GetMetadataReader();
switch (parentHandle.Kind) {
case HandleKind.MethodDefinition:
new Dom.MethodDefinition(member.Module, (MethodDefinitionHandle)parentHandle).WriteTo(output, genericContext, syntax);
break;
case HandleKind.ModuleReference:
output.Write('[');
var moduleRef = metadata.GetModuleReference((ModuleReferenceHandle)parentHandle);
output.Write(metadata.GetString(moduleRef.Name));
output.Write(']');
break;
case HandleKind.TypeDefinition:
new Dom.TypeDefinition(member.Module, (TypeDefinitionHandle)parentHandle).WriteTo(output, syntax);
break;
case HandleKind.TypeReference:
new Dom.TypeReference(member.Module, (TypeReferenceHandle)parentHandle).WriteTo(output, syntax);
break;
case HandleKind.TypeSpecification:
new Dom.TypeSpecification(member.Module, (TypeSpecificationHandle)parentHandle).WriteTo(output, genericContext, syntax);
break;
}
}
MethodSignature<Action<ILNameSyntax>> signature;
switch (member) {
case Dom.MethodDefinition md:
md.WriteTo(output);
break;
case Dom.MemberReference mr:
switch (mr.Kind) {
case MemberReferenceKind.Method:
signature = mr.DecodeMethodSignature(new DisassemblerSignatureProvider(member.Module, output), genericContext);
if (signature.Header.HasExplicitThis) {
output.Write("instance explicit ");
} else if (signature.Header.IsInstance) {
output.Write("instance ");
}
if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
output.Write("vararg ");
}
signature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters);
output.Write(' ');
WriteParent(mr.Parent);
output.Write("::");
output.Write(DisassemblerHelpers.Escape(mr.Name));
output.Write("(");
for (int i = 0; i < signature.ParameterTypes.Length; ++i) {
if (i > 0)
output.Write(", ");
signature.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters);
}
output.Write(")");
break;
case MemberReferenceKind.Field:
var fieldSignature = mr.DecodeFieldSignature(new DisassemblerSignatureProvider(member.Module, output), genericContext);
fieldSignature(ILNameSyntax.SignatureNoNamedTypeParameters);
output.Write(' ');
WriteParent(mr.Parent);
output.Write("::");
output.Write(DisassemblerHelpers.Escape(mr.Name));
break;
}
break;
case Dom.MethodSpecification ms:
var substitution = ms.DecodeSignature(new DisassemblerSignatureProvider(ms.Module, output), genericContext);
switch (ms.Method) {
case Dom.MethodDefinition method:
var metadata = method.Module.GetMetadataReader();
signature = method.DecodeSignature(new DisassemblerSignatureProvider(method.Module, output), new GenericContext(method));
if (signature.Header.HasExplicitThis) {
output.Write("instance explicit ");
} else if (signature.Header.IsInstance) {
output.Write("instance ");
}
if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
output.Write("vararg ");
}
signature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters);
output.Write(' ');
if (!method.DeclaringType.IsNil) {
method.DeclaringType.WriteTo(output, ILNameSyntax.TypeName);
output.Write("::");
}
bool isCompilerControlled = (method.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope;
if (isCompilerControlled) {
output.Write(DisassemblerHelpers.Escape(method.Name + "$PST" + MetadataTokens.GetToken(method.Handle).ToString("X8")));
} else {
output.Write(DisassemblerHelpers.Escape(method.Name));
}
output.Write('<');
for (int i = 0; i < substitution.Length; i++) {
if (i > 0)
output.Write(", ");
substitution[i](syntax);
}
output.Write('>');
output.Write("(");
for (int i = 0; i < signature.ParameterTypes.Length; ++i) {
if (i > 0)
output.Write(", ");
signature.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters);
}
output.Write(")");
break;
case Dom.MemberReference mr:
signature = mr.DecodeMethodSignature(new DisassemblerSignatureProvider(member.Module, output), genericContext);
if (signature.Header.HasExplicitThis) {
output.Write("instance explicit ");
} else if (signature.Header.IsInstance) {
output.Write("instance ");
}
if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
output.Write("vararg ");
}
signature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters);
output.Write(' ');
WriteParent(mr.Parent);
output.Write("::");
output.Write(DisassemblerHelpers.Escape(mr.Name));
output.Write('<');
for (int i = 0; i < substitution.Length; i++) {
if (i > 0)
output.Write(", ");
substitution[i](syntax);
}
output.Write('>');
output.Write("(");
for (int i = 0; i < signature.ParameterTypes.Length; ++i) {
if (i > 0)
output.Write(", ");
signature.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters);
}
output.Write(")");
break;
}
break;
}
}
public static void WriteTo(this Dom.TypeReference typeRef, ITextOutput output, ILNameSyntax syntax = ILNameSyntax.Signature)
{
var metadata = typeRef.Module.GetMetadataReader();
if (!typeRef.ResolutionScope.IsNil) {
output.Write("[");
var currentTypeRef = typeRef;
while (currentTypeRef.ResolutionScope.Kind == HandleKind.TypeReference) {
currentTypeRef = new Dom.TypeReference(currentTypeRef.Module, (TypeReferenceHandle)currentTypeRef.ResolutionScope);
}
switch (currentTypeRef.ResolutionScope.Kind) {
case HandleKind.ModuleReference:
break;
case HandleKind.AssemblyReference:
var asmRef = metadata.GetAssemblyReference((AssemblyReferenceHandle)currentTypeRef.ResolutionScope);
output.Write(DisassemblerHelpers.Escape(metadata.GetString(asmRef.Name)));
break;
}
output.Write("]");
}
output.WriteReference(typeRef.FullName.ToILNameString(), typeRef);
}
public static void WriteTo(this Dom.TypeDefinition typeDefinition, ITextOutput output, ILNameSyntax syntax = ILNameSyntax.Signature)
{
output.WriteReference(typeDefinition.FullName.ToILNameString(), typeDefinition);
}
public static void WriteTo(this Dom.TypeSpecification typeSpecification, ITextOutput output, GenericContext genericContext, ILNameSyntax syntax = ILNameSyntax.Signature)
{
var signature = typeSpecification.DecodeSignature(new DisassemblerSignatureProvider(typeSpecification.Module, output), genericContext);
signature(syntax);
} }
public static void WriteTo(this ITypeReference type, ITextOutput output, GenericContext genericContext, ILNameSyntax syntax = ILNameSyntax.Signature) public static void WriteTo(this Metadata.FieldDefinition field, ITextOutput output)
{ {
switch (type) { var metadata = field.Module.GetMetadataReader();
case Dom.TypeDefinition td: var fieldDefinition = metadata.GetFieldDefinition(field.Handle);
td.WriteTo(output, syntax); var declaringType = new Metadata.TypeDefinition(field.Module, fieldDefinition.GetDeclaringType());
break; var signature = fieldDefinition.DecodeSignature(new DisassemblerSignatureProvider(field.Module, output), new GenericContext(declaringType));
case Dom.TypeReference tr: signature(ILNameSyntax.SignatureNoNamedTypeParameters);
tr.WriteTo(output, syntax); output.Write(' ');
break; declaringType.WriteTo(output, ILNameSyntax.TypeName);
case Dom.TypeSpecification ts: output.Write("::");
ts.WriteTo(output, genericContext, syntax); output.Write(DisassemblerHelpers.Escape(metadata.GetString(fieldDefinition.Name)));
break;
}
} }
public static void WriteTo(this Dom.MethodDefinition method, ITextOutput output) public static void WriteTo(this Metadata.MethodDefinition method, ITextOutput output)
{ {
var metadata = method.Module.GetMetadataReader(); var metadata = method.Module.GetMetadataReader();
var signature = method.DecodeSignature(new DisassemblerSignatureProvider(method.Module, output), new GenericContext(method)); var methodDefinition = method.This();
var signature = methodDefinition.DecodeSignature(new DisassemblerSignatureProvider(method.Module, output), new GenericContext(method));
if (signature.Header.HasExplicitThis) { if (signature.Header.HasExplicitThis) {
output.Write("instance explicit "); output.Write("instance explicit ");
} else if (signature.Header.IsInstance) { } else if (signature.Header.IsInstance) {
@ -244,17 +64,18 @@ namespace ICSharpCode.Decompiler.Disassembler
} }
signature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters); signature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters);
output.Write(' '); output.Write(' ');
if (!method.DeclaringType.IsNil) { var declaringType = methodDefinition.GetDeclaringType();
method.DeclaringType.WriteTo(output, ILNameSyntax.TypeName); if (!declaringType.IsNil) {
new Metadata.TypeDefinition(method.Module, declaringType).WriteTo(output, ILNameSyntax.TypeName);
output.Write("::"); output.Write("::");
} }
bool isCompilerControlled = (method.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope; bool isCompilerControlled = (methodDefinition.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope;
if (isCompilerControlled) { if (isCompilerControlled) {
output.Write(DisassemblerHelpers.Escape(method.Name + "$PST" + MetadataTokens.GetToken(method.Handle).ToString("X8"))); output.Write(DisassemblerHelpers.Escape(method.Name + "$PST" + MetadataTokens.GetToken(method.Handle).ToString("X8")));
} else { } else {
output.Write(DisassemblerHelpers.Escape(method.Name)); output.Write(DisassemblerHelpers.Escape(method.Name));
} }
var genericParameters = method.GenericParameters; var genericParameters = methodDefinition.GetGenericParameters();
if (genericParameters.Count > 0) { if (genericParameters.Count > 0) {
output.Write('<'); output.Write('<');
for (int i = 0; i < genericParameters.Count; i++) { for (int i = 0; i < genericParameters.Count; i++) {
@ -276,7 +97,7 @@ namespace ICSharpCode.Decompiler.Disassembler
if (j > 0) if (j > 0)
output.Write(", "); output.Write(", ");
var constraint = metadata.GetGenericParameterConstraint(constraints[j]); var constraint = metadata.GetGenericParameterConstraint(constraints[j]);
constraint.Type.CoerceTypeReference(method.Module).WriteTo(output, new GenericContext(method), ILNameSyntax.TypeName); constraint.Type.WriteTo(method.Module, output, new GenericContext(method), ILNameSyntax.TypeName);
} }
output.Write(") "); output.Write(") ");
} }
@ -298,6 +119,224 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write(")"); output.Write(")");
} }
public static void WriteTo(this EntityHandle entity, PEFile module, ITextOutput output, GenericContext genericContext, ILNameSyntax syntax = ILNameSyntax.Signature)
{
if (entity.IsNil)
throw new ArgumentNullException(nameof(entity));
if (module == null)
throw new ArgumentNullException(nameof(module));
WriteTo(new Entity(module, entity), output, genericContext, syntax);
}
public static void WriteTo(this Entity entity, ITextOutput output, GenericContext genericContext, ILNameSyntax syntax = ILNameSyntax.Signature)
{
if (entity.IsNil)
throw new ArgumentNullException(nameof(entity));
var metadata = entity.Module.GetMetadataReader();
switch (entity.Handle.Kind) {
case HandleKind.TypeDefinition:
WriteTo(entity, output, syntax);
break;
case HandleKind.TypeReference:
WriteTo(new Metadata.TypeReference(entity.Module, (TypeReferenceHandle)entity.Handle), output, syntax);
break;
case HandleKind.TypeSpecification:
WriteTo(new Metadata.TypeSpecification(entity.Module, (TypeSpecificationHandle)entity.Handle), output, genericContext, syntax);
break;
case HandleKind.FieldDefinition:
WriteTo((Metadata.FieldDefinition)entity, output);
break;
case HandleKind.MethodDefinition:
WriteTo((Metadata.MethodDefinition)entity, output);
break;
case HandleKind.MemberReference:
WriteTo((MemberReferenceHandle)entity.Handle, entity.Module, output, genericContext, syntax);
break;
case HandleKind.MethodSpecification:
WriteTo((MethodSpecificationHandle)entity.Handle, entity.Module, output, genericContext, syntax);
break;
case HandleKind.PropertyDefinition:
case HandleKind.EventDefinition:
default:
throw new NotSupportedException();
}
}
public static void WriteTo(this MethodSpecificationHandle handle, PEFile module, ITextOutput output, GenericContext genericContext, ILNameSyntax syntax)
{
var metadata = module.GetMetadataReader();
var ms = metadata.GetMethodSpecification(handle);
var substitution = ms.DecodeSignature(new DisassemblerSignatureProvider(module, output), genericContext);
MethodSignature<Action<ILNameSyntax>> signature;
switch (ms.Method.Kind) {
case HandleKind.MethodDefinition:
var methodDefinition = metadata.GetMethodDefinition((MethodDefinitionHandle)ms.Method);
var methodName = metadata.GetString(methodDefinition.Name);
signature = methodDefinition.DecodeSignature(new DisassemblerSignatureProvider(module, output), genericContext);
if (signature.Header.HasExplicitThis) {
output.Write("instance explicit ");
} else if (signature.Header.IsInstance) {
output.Write("instance ");
}
if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
output.Write("vararg ");
}
signature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters);
output.Write(' ');
var declaringType = methodDefinition.GetDeclaringType();
if (!declaringType.IsNil) {
new Metadata.TypeDefinition(module, declaringType).WriteTo(output, ILNameSyntax.TypeName);
output.Write("::");
}
bool isCompilerControlled = (methodDefinition.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope;
if (isCompilerControlled) {
output.Write(DisassemblerHelpers.Escape(methodName + "$PST" + MetadataTokens.GetToken(ms.Method).ToString("X8")));
} else {
output.Write(DisassemblerHelpers.Escape(methodName));
}
output.Write('<');
for (int i = 0; i < substitution.Length; i++) {
if (i > 0)
output.Write(", ");
substitution[i](syntax);
}
output.Write('>');
output.Write("(");
for (int i = 0; i < signature.ParameterTypes.Length; ++i) {
if (i > 0)
output.Write(", ");
signature.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters);
}
output.Write(")");
break;
case HandleKind.MemberReference:
var memberReference = metadata.GetMemberReference((MemberReferenceHandle)ms.Method);
var memberName = metadata.GetString(memberReference.Name);
signature = memberReference.DecodeMethodSignature(new DisassemblerSignatureProvider(module, output), genericContext);
if (signature.Header.HasExplicitThis) {
output.Write("instance explicit ");
} else if (signature.Header.IsInstance) {
output.Write("instance ");
}
if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
output.Write("vararg ");
}
signature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters);
output.Write(' ');
WriteParent(output, module, metadata, memberReference.Parent, genericContext, syntax);
output.Write("::");
output.Write(DisassemblerHelpers.Escape(memberName));
output.Write('<');
for (int i = 0; i < substitution.Length; i++) {
if (i > 0)
output.Write(", ");
substitution[i](syntax);
}
output.Write('>');
output.Write("(");
for (int i = 0; i < signature.ParameterTypes.Length; ++i) {
if (i > 0)
output.Write(", ");
signature.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters);
}
output.Write(")");
break;
}
}
public static void WriteTo(this MemberReferenceHandle handle, PEFile module, ITextOutput output, GenericContext genericContext, ILNameSyntax syntax = ILNameSyntax.Signature)
{
var metadata = module.GetMetadataReader();
var mr = metadata.GetMemberReference(handle);
var memberName = metadata.GetString(mr.Name);
switch (mr.GetKind()) {
case MemberReferenceKind.Method:
var methodSignature = mr.DecodeMethodSignature(new DisassemblerSignatureProvider(module, output), genericContext);
if (methodSignature.Header.HasExplicitThis) {
output.Write("instance explicit ");
} else if (methodSignature.Header.IsInstance) {
output.Write("instance ");
}
if (methodSignature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
output.Write("vararg ");
}
methodSignature.ReturnType(ILNameSyntax.SignatureNoNamedTypeParameters);
output.Write(' ');
WriteParent(output, module, metadata, mr.Parent, genericContext, syntax);
output.Write("::");
output.Write(DisassemblerHelpers.Escape(memberName));
output.Write("(");
for (int i = 0; i < methodSignature.ParameterTypes.Length; ++i) {
if (i > 0)
output.Write(", ");
methodSignature.ParameterTypes[i](ILNameSyntax.SignatureNoNamedTypeParameters);
}
output.Write(")");
break;
case MemberReferenceKind.Field:
var fieldSignature = mr.DecodeFieldSignature(new DisassemblerSignatureProvider(module, output), genericContext);
fieldSignature(ILNameSyntax.SignatureNoNamedTypeParameters);
output.Write(' ');
WriteParent(output, module, metadata, mr.Parent, genericContext, syntax);
output.Write("::");
output.Write(DisassemblerHelpers.Escape(memberName));
break;
}
}
public static void WriteTo(this Metadata.TypeReference typeRef, ITextOutput output, ILNameSyntax syntax = ILNameSyntax.Signature)
{
var metadata = typeRef.Module.GetMetadataReader();
if (!typeRef.ResolutionScope.IsNil) {
output.Write("[");
var currentTypeRef = typeRef;
while (currentTypeRef.ResolutionScope.Kind == HandleKind.TypeReference) {
currentTypeRef = new Metadata.TypeReference(currentTypeRef.Module, (TypeReferenceHandle)currentTypeRef.ResolutionScope);
}
switch (currentTypeRef.ResolutionScope.Kind) {
case HandleKind.ModuleReference:
break;
case HandleKind.AssemblyReference:
var asmRef = metadata.GetAssemblyReference((AssemblyReferenceHandle)currentTypeRef.ResolutionScope);
output.Write(DisassemblerHelpers.Escape(metadata.GetString(asmRef.Name)));
break;
}
output.Write("]");
}
output.WriteReference(typeRef.FullName.ToILNameString(), typeRef);
}
public static void WriteTo(this Metadata.TypeSpecification typeSpecification, ITextOutput output, GenericContext genericContext, ILNameSyntax syntax = ILNameSyntax.Signature)
{
var signature = typeSpecification.DecodeSignature(new DisassemblerSignatureProvider(typeSpecification.Module, output), genericContext);
signature(syntax);
}
static void WriteParent(ITextOutput output, PEFile module, MetadataReader metadata, EntityHandle parentHandle, GenericContext genericContext, ILNameSyntax syntax)
{
switch (parentHandle.Kind) {
case HandleKind.MethodDefinition:
new Metadata.MethodDefinition(module, (MethodDefinitionHandle)parentHandle).WriteTo(output);
break;
case HandleKind.ModuleReference:
output.Write('[');
var moduleRef = metadata.GetModuleReference((ModuleReferenceHandle)parentHandle);
output.Write(metadata.GetString(moduleRef.Name));
output.Write(']');
break;
case HandleKind.TypeDefinition:
new Metadata.TypeDefinition(module, (TypeDefinitionHandle)parentHandle).WriteTo(output, syntax);
break;
case HandleKind.TypeReference:
new Metadata.TypeReference(module, (TypeReferenceHandle)parentHandle).WriteTo(output, syntax);
break;
case HandleKind.TypeSpecification:
new Metadata.TypeSpecification(module, (TypeSpecificationHandle)parentHandle).WriteTo(output, genericContext, syntax);
break;
}
}
/*
public static bool IsBaseTypeOf(this ITypeReference baseType, ITypeReference derivedType) public static bool IsBaseTypeOf(this ITypeReference baseType, ITypeReference derivedType)
{ {
var derivedTypeDefinition = derivedType.GetDefinition(); var derivedTypeDefinition = derivedType.GetDefinition();
@ -313,7 +352,7 @@ namespace ICSharpCode.Decompiler.Disassembler
public class TypeUsedInSignature : ISignatureTypeProvider<bool, Unit> public class TypeUsedInSignature : ISignatureTypeProvider<bool, Unit>
{ {
readonly PEFile module; readonly PEFile module;
readonly Dom.TypeDefinition type; readonly Metadata.TypeDefinition type;
public TypeUsedInSignature(ITypeReference type) public TypeUsedInSignature(ITypeReference type)
{ {
@ -362,12 +401,12 @@ namespace ICSharpCode.Decompiler.Disassembler
public bool GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) public bool GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind)
{ {
return new Dom.TypeReference(module, handle).GetDefinition() == type; return new Metadata.TypeReference(module, handle).GetDefinition() == type;
} }
public bool GetTypeFromSpecification(MetadataReader reader, Unit genericContext, TypeSpecificationHandle handle, byte rawTypeKind) public bool GetTypeFromSpecification(MetadataReader reader, Unit genericContext, TypeSpecificationHandle handle, byte rawTypeKind)
{ {
return new Dom.TypeSpecification(module, handle).GetDefinition() == type; return new Metadata.TypeSpecification(module, handle).GetDefinition() == type;
} }*/
} }
} }

10
ICSharpCode.Decompiler/Disassembler/ILStructure.cs

@ -20,7 +20,7 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.Disassembler namespace ICSharpCode.Decompiler.Disassembler
@ -57,7 +57,7 @@ namespace ICSharpCode.Decompiler.Disassembler
/// </summary> /// </summary>
public class ILStructure public class ILStructure
{ {
public readonly Dom.MethodDefinition Method; public readonly Metadata.MethodDefinition Method;
public readonly ILStructureType Type; public readonly ILStructureType Type;
/// <summary> /// <summary>
@ -85,7 +85,7 @@ namespace ICSharpCode.Decompiler.Disassembler
/// </summary> /// </summary>
public readonly List<ILStructure> Children = new List<ILStructure>(); public readonly List<ILStructure> Children = new List<ILStructure>();
public ILStructure(Dom.MethodDefinition method, MethodBodyBlock body) public ILStructure(Metadata.MethodDefinition method, MethodBodyBlock body)
: this(method, ILStructureType.Root, 0, body.GetILReader().Length) : this(method, ILStructureType.Root, 0, body.GetILReader().Length)
{ {
// Build the tree of exception structures: // Build the tree of exception structures:
@ -132,7 +132,7 @@ namespace ICSharpCode.Decompiler.Disassembler
SortChildren(); SortChildren();
} }
public ILStructure(Dom.MethodDefinition method, ILStructureType type, int startOffset, int endOffset, ExceptionRegion handler = default(ExceptionRegion)) public ILStructure(Metadata.MethodDefinition method, ILStructureType type, int startOffset, int endOffset, ExceptionRegion handler = default(ExceptionRegion))
{ {
Debug.Assert(startOffset < endOffset); Debug.Assert(startOffset < endOffset);
this.Method = method; this.Method = method;
@ -142,7 +142,7 @@ namespace ICSharpCode.Decompiler.Disassembler
this.ExceptionHandler = handler; this.ExceptionHandler = handler;
} }
public ILStructure(Dom.MethodDefinition method, ILStructureType type, int startOffset, int endOffset, int loopEntryPoint) public ILStructure(Metadata.MethodDefinition method, ILStructureType type, int startOffset, int endOffset, int loopEntryPoint)
{ {
Debug.Assert(startOffset < endOffset); Debug.Assert(startOffset < endOffset);
this.Method = method; this.Method = method;

57
ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs

@ -23,6 +23,7 @@ using System.Reflection.Metadata.Ecma335;
using System.Threading; using System.Threading;
using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.Decompiler.Disassembler namespace ICSharpCode.Decompiler.Disassembler
{ {
@ -44,7 +45,7 @@ namespace ICSharpCode.Decompiler.Disassembler
/// </summary> /// </summary>
public bool ShowSequencePoints { get; set; } public bool ShowSequencePoints { get; set; }
IList<Dom.SequencePoint> sequencePoints; IList<Metadata.SequencePoint> sequencePoints;
int nextSequencePointIndex; int nextSequencePointIndex;
public MethodBodyDisassembler(ITextOutput output, CancellationToken cancellationToken) public MethodBodyDisassembler(ITextOutput output, CancellationToken cancellationToken)
@ -53,17 +54,19 @@ namespace ICSharpCode.Decompiler.Disassembler
this.cancellationToken = cancellationToken; this.cancellationToken = cancellationToken;
} }
public unsafe virtual void Disassemble(Dom.MethodDefinition method) public unsafe virtual void Disassemble(Metadata.MethodDefinition method)
{ {
// start writing IL code // start writing IL code
output.WriteLine("// Method begins at RVA 0x{0:x4}", method.RVA); var metadata = method.Module.GetMetadataReader();
if (method.RVA == 0) { var methodDefinition = metadata.GetMethodDefinition(method.Handle);
output.WriteLine("// Method begins at RVA 0x{0:x4}", methodDefinition.RelativeVirtualAddress);
if (methodDefinition.RelativeVirtualAddress == 0) {
output.WriteLine("// Code size {0} (0x{0:x})", 0); output.WriteLine("// Code size {0} (0x{0:x})", 0);
output.WriteLine(".maxstack {0}", 0); output.WriteLine(".maxstack {0}", 0);
output.WriteLine(); output.WriteLine();
return; return;
} }
var body = method.Body; var body = method.Module.Reader.GetMethodBody(methodDefinition.RelativeVirtualAddress);
var blob = body.GetILReader(); var blob = body.GetILReader();
output.WriteLine("// Code size {0} (0x{0:x})", blob.Length); output.WriteLine("// Code size {0} (0x{0:x})", blob.Length);
output.WriteLine(".maxstack {0}", body.MaxStack); output.WriteLine(".maxstack {0}", body.MaxStack);
@ -75,7 +78,6 @@ namespace ICSharpCode.Decompiler.Disassembler
DisassembleLocalsBlock(method, body); DisassembleLocalsBlock(method, body);
output.WriteLine(); output.WriteLine();
var metadata = method.Module.GetMetadataReader();
sequencePoints = method.GetSequencePoints(); sequencePoints = method.GetSequencePoints();
nextSequencePointIndex = 0; nextSequencePointIndex = 0;
@ -93,11 +95,11 @@ namespace ICSharpCode.Decompiler.Disassembler
sequencePoints = null; sequencePoints = null;
} }
void DisassembleLocalsBlock(Dom.MethodDefinition method, MethodBodyBlock body) void DisassembleLocalsBlock(Metadata.MethodDefinition method, MethodBodyBlock body)
{ {
if (body.LocalSignature.IsNil) return; if (body.LocalSignature.IsNil) return;
var metadata = method.Module.GetMetadataReader(); var metadata = method.Module.GetMetadataReader();
var signature = metadata.GetStandaloneSignature(body.LocalSignature).DecodeLocalSignature(new DisassemblerSignatureProvider(method.Module, output), new Dom.GenericContext(method)); var signature = metadata.GetStandaloneSignature(body.LocalSignature).DecodeLocalSignature(new DisassemblerSignatureProvider(method.Module, output), new Metadata.GenericContext(method));
if (!signature.IsEmpty) { if (!signature.IsEmpty) {
output.Write(".locals "); output.Write(".locals ");
if (body.LocalVariablesInitialized) if (body.LocalVariablesInitialized)
@ -118,7 +120,7 @@ namespace ICSharpCode.Decompiler.Disassembler
} }
} }
internal void WriteExceptionHandlers(Dom.MethodDefinition method, MethodBodyBlock body) internal void WriteExceptionHandlers(Metadata.MethodDefinition method, MethodBodyBlock body)
{ {
var handlers = body.ExceptionRegions; var handlers = body.ExceptionRegions;
if (!handlers.IsEmpty) { if (!handlers.IsEmpty) {
@ -169,7 +171,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write("catch"); output.Write("catch");
if (!s.ExceptionHandler.CatchType.IsNil) { if (!s.ExceptionHandler.CatchType.IsNil) {
output.Write(' '); output.Write(' ');
s.ExceptionHandler.CatchType.CoerceTypeReference(s.Method.Module).WriteTo(output, new Dom.GenericContext(s.Method), ILNameSyntax.TypeName); s.ExceptionHandler.CatchType.WriteTo(s.Method.Module, output, new Metadata.GenericContext(s.Method), ILNameSyntax.TypeName);
} }
output.WriteLine(); output.WriteLine();
break; break;
@ -243,12 +245,12 @@ namespace ICSharpCode.Decompiler.Disassembler
} }
} }
protected virtual void WriteInstruction(ITextOutput output, Dom.MethodDefinition method, ref BlobReader blob) protected virtual void WriteInstruction(ITextOutput output, Metadata.MethodDefinition method, ref BlobReader blob)
{ {
var metadata = method.Module.GetMetadataReader(); var metadata = method.Module.GetMetadataReader();
int offset = blob.Offset; int offset = blob.Offset;
if (ShowSequencePoints && nextSequencePointIndex < sequencePoints?.Count) { if (ShowSequencePoints && nextSequencePointIndex < sequencePoints?.Count) {
Dom.SequencePoint sp = sequencePoints[nextSequencePointIndex]; Metadata.SequencePoint sp = sequencePoints[nextSequencePointIndex];
if (sp.Offset <= offset) { if (sp.Offset <= offset) {
output.Write("// sequence point: "); output.Write("// sequence point: ");
if (sp.Offset != offset) { if (sp.Offset != offset) {
@ -280,7 +282,7 @@ namespace ICSharpCode.Decompiler.Disassembler
case OperandType.Type: case OperandType.Type:
output.Write(' '); output.Write(' ');
var handle = MetadataTokens.EntityHandle(blob.ReadInt32()); var handle = MetadataTokens.EntityHandle(blob.ReadInt32());
WriteEntityHandle(handle, method.Module, new Dom.GenericContext(method), output); handle.WriteTo(method.Module, output, new GenericContext(method));
break; break;
case OperandType.Tok: case OperandType.Tok:
output.Write(' '); output.Write(' ');
@ -300,7 +302,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write("field "); output.Write("field ");
break; break;
} }
WriteEntityHandle(handle, method.Module, new Dom.GenericContext(method), output); handle.WriteTo(method.Module, output, new GenericContext(method));
break; break;
case OperandType.ShortI: case OperandType.ShortI:
output.Write(' '); output.Write(' ');
@ -361,32 +363,5 @@ namespace ICSharpCode.Decompiler.Disassembler
} }
output.WriteLine(); output.WriteLine();
} }
void WriteEntityHandle(EntityHandle entity, Dom.PEFile module, Dom.GenericContext context, ITextOutput output)
{
switch (entity.Kind) {
case HandleKind.TypeReference:
new Dom.TypeReference(module, (TypeReferenceHandle)entity).WriteTo(output);
break;
case HandleKind.TypeDefinition:
new Dom.TypeDefinition(module, (TypeDefinitionHandle)entity).WriteTo(output);
break;
case HandleKind.FieldDefinition:
new Dom.FieldDefinition(module, (FieldDefinitionHandle)entity).WriteTo(output);
break;
case HandleKind.MethodDefinition:
new Dom.MethodDefinition(module, (MethodDefinitionHandle)entity).WriteTo(output);
break;
case HandleKind.MemberReference:
new Dom.MemberReference(module, (MemberReferenceHandle)entity).WriteTo(output, context);
break;
case HandleKind.TypeSpecification:
new Dom.TypeSpecification(module, (TypeSpecificationHandle)entity).WriteTo(output, context);
break;
case HandleKind.MethodSpecification:
new Dom.MethodSpecification(module, (MethodSpecificationHandle)entity).WriteTo(output, context);
break;
}
}
} }
} }

29
ICSharpCode.Decompiler/Disassembler/OpCodeInfo.cs

@ -21,9 +21,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
using System.Text; using ICSharpCode.Decompiler.Metadata;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.IL;
namespace ICSharpCode.Decompiler.Disassembler namespace ICSharpCode.Decompiler.Disassembler
{ {
@ -165,34 +163,11 @@ namespace ICSharpCode.Decompiler.Disassembler
return targets; return targets;
} }
public static string DecodeUserString(ref BlobReader blob, Dom.PEFile module) public static string DecodeUserString(ref BlobReader blob, Metadata.PEFile module)
{ {
return module.GetMetadataReader().GetUserString(MetadataTokens.UserStringHandle(blob.ReadInt32())); return module.GetMetadataReader().GetUserString(MetadataTokens.UserStringHandle(blob.ReadInt32()));
} }
public static Dom.IMemberReference DecodeMemberToken(ref BlobReader blob, Dom.PEFile module)
{
var handle = MetadataTokens.EntityHandle(blob.ReadInt32());
switch (handle.Kind) {
case HandleKind.TypeDefinition:
return new Dom.TypeDefinition(module, (TypeDefinitionHandle)handle);
case HandleKind.TypeReference:
return new Dom.TypeReference(module, (TypeReferenceHandle)handle);
case HandleKind.TypeSpecification:
return new Dom.TypeSpecification(module, (TypeSpecificationHandle)handle);
case HandleKind.MethodDefinition:
return new Dom.MethodDefinition(module, (MethodDefinitionHandle)handle);
case HandleKind.MethodSpecification:
return new Dom.MethodSpecification(module, (MethodSpecificationHandle)handle);
case HandleKind.FieldDefinition:
return new Dom.FieldDefinition(module, (FieldDefinitionHandle)handle);
case HandleKind.MemberReference:
return new Dom.MemberReference(module, (MemberReferenceHandle)handle);
default:
throw new NotSupportedException();
}
}
public static bool IsReturn(this ILOpCode opCode) public static bool IsReturn(this ILOpCode opCode)
{ {
return opCode == ILOpCode.Ret || opCode == ILOpCode.Endfilter || opCode == ILOpCode.Endfinally; return opCode == ILOpCode.Ret || opCode == ILOpCode.Endfilter || opCode == ILOpCode.Endfinally;

234
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -25,7 +25,7 @@ using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
using System.Threading; using System.Threading;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL;
namespace ICSharpCode.Decompiler.Disassembler namespace ICSharpCode.Decompiler.Disassembler
@ -113,37 +113,39 @@ namespace ICSharpCode.Decompiler.Disassembler
{ MethodImplAttributes.PreserveSig, "preservesig" }, { MethodImplAttributes.PreserveSig, "preservesig" },
{ MethodImplAttributes.InternalCall, "internalcall" }, { MethodImplAttributes.InternalCall, "internalcall" },
{ MethodImplAttributes.ForwardRef, "forwardref" }, { MethodImplAttributes.ForwardRef, "forwardref" },
{ MethodImplAttributes.AggressiveInlining, "aggressiveinlining" },
}; };
public void DisassembleMethod(Dom.MethodDefinition method) public void DisassembleMethod(Metadata.MethodDefinition method)
{ {
DisassembleMethodHeader(method); DisassembleMethodHeader(method);
DisassembleMethodBlock(method); DisassembleMethodBlock(method);
} }
public void DisassembleMethodHeader(Dom.MethodDefinition method) public void DisassembleMethodHeader(Metadata.MethodDefinition method)
{ {
// write method header // write method header
output.WriteDefinition(".method ", method); output.WriteDefinition(".method ", method);
DisassembleMethodHeaderInternal(method); DisassembleMethodHeaderInternal(method);
} }
void DisassembleMethodHeaderInternal(Dom.MethodDefinition method) void DisassembleMethodHeaderInternal(Metadata.MethodDefinition method)
{ {
var metadata = method.Module.GetMetadataReader(); var metadata = method.Module.GetMetadataReader();
var methodDefinition = metadata.GetMethodDefinition(method.Handle);
// .method public hidebysig specialname // .method public hidebysig specialname
// instance default class [mscorlib]System.IO.TextWriter get_BaseWriter () cil managed // instance default class [mscorlib]System.IO.TextWriter get_BaseWriter () cil managed
// //
//emit flags //emit flags
WriteEnum(method.Attributes & MethodAttributes.MemberAccessMask, methodVisibility); WriteEnum(methodDefinition.Attributes & MethodAttributes.MemberAccessMask, methodVisibility);
WriteFlags(method.Attributes & ~MethodAttributes.MemberAccessMask, methodAttributeFlags); WriteFlags(methodDefinition.Attributes & ~MethodAttributes.MemberAccessMask, methodAttributeFlags);
bool isCompilerControlled = (method.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope; bool isCompilerControlled = (methodDefinition.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope;
if (isCompilerControlled) if (isCompilerControlled)
output.Write("privatescope "); output.Write("privatescope ");
if ((method.Attributes & MethodAttributes.PinvokeImpl) == MethodAttributes.PinvokeImpl) { if ((methodDefinition.Attributes & MethodAttributes.PinvokeImpl) == MethodAttributes.PinvokeImpl) {
output.Write("pinvokeimpl"); output.Write("pinvokeimpl");
var info = method.Import; var info = methodDefinition.GetImport();
if (!info.Module.IsNil) { if (!info.Module.IsNil) {
var moduleRef = metadata.GetModuleReference(info.Module); var moduleRef = metadata.GetModuleReference(info.Module);
output.Write("(\"" + DisassemblerHelpers.EscapeString(metadata.GetString(moduleRef.Name)) + "\""); output.Write("(\"" + DisassemblerHelpers.EscapeString(metadata.GetString(moduleRef.Name)) + "\"");
@ -194,8 +196,8 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine(); output.WriteLine();
output.Indent(); output.Indent();
var declaringType = method.DeclaringType; var declaringType = methodDefinition.GetDeclaringType();
var signature = method.DecodeSignature(new DisassemblerSignatureProvider(method.Module, output), new GenericContext(method)); var signature = methodDefinition.DecodeSignature(new DisassemblerSignatureProvider(method.Module, output), new GenericContext(method));
if (signature.Header.HasExplicitThis) { if (signature.Header.HasExplicitThis) {
output.Write("instance explicit "); output.Write("instance explicit ");
} else if (signature.Header.IsInstance) { } else if (signature.Header.IsInstance) {
@ -209,7 +211,7 @@ namespace ICSharpCode.Decompiler.Disassembler
signature.ReturnType(ILNameSyntax.Signature); signature.ReturnType(ILNameSyntax.Signature);
output.Write(' '); output.Write(' ');
var parameters = method.Parameters.ToImmutableArray(); var parameters = methodDefinition.GetParameters().ToArray();
if (parameters.Length > 0) { if (parameters.Length > 0) {
var marshallingDesc = metadata.GetParameter(parameters[0]).GetMarshallingDescriptor(); var marshallingDesc = metadata.GetParameter(parameters[0]).GetMarshallingDescriptor();
@ -224,7 +226,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write(DisassemblerHelpers.Escape(method.Name)); output.Write(DisassemblerHelpers.Escape(method.Name));
} }
WriteTypeParameters(output, method.Module, new GenericContext(method), method.GenericParameters); WriteTypeParameters(output, method.Module, new GenericContext(method), methodDefinition.GetGenericParameters());
//( params ) //( params )
output.Write(" ("); output.Write(" (");
@ -236,40 +238,40 @@ namespace ICSharpCode.Decompiler.Disassembler
} }
output.Write(") "); output.Write(") ");
//cil managed //cil managed
WriteEnum(method.ImplAttributes & MethodImplAttributes.CodeTypeMask, methodCodeType); WriteEnum(methodDefinition.ImplAttributes & MethodImplAttributes.CodeTypeMask, methodCodeType);
if ((method.ImplAttributes & MethodImplAttributes.ManagedMask) == MethodImplAttributes.Managed) if ((methodDefinition.ImplAttributes & MethodImplAttributes.ManagedMask) == MethodImplAttributes.Managed)
output.Write("managed "); output.Write("managed ");
else else
output.Write("unmanaged "); output.Write("unmanaged ");
WriteFlags(method.ImplAttributes & ~(MethodImplAttributes.CodeTypeMask | MethodImplAttributes.ManagedMask), methodImpl); WriteFlags(methodDefinition.ImplAttributes & ~(MethodImplAttributes.CodeTypeMask | MethodImplAttributes.ManagedMask), methodImpl);
output.Unindent(); output.Unindent();
} }
void DisassembleMethodBlock(Dom.MethodDefinition method) void DisassembleMethodBlock(Metadata.MethodDefinition method)
{ {
OpenBlock(defaultCollapsed: isInType);
WriteAttributes(method);
var metadata = method.Module.GetMetadataReader(); var metadata = method.Module.GetMetadataReader();
var methodDefinition = metadata.GetMethodDefinition(method.Handle);
foreach (var h in method.GetMethodImplementations()) { OpenBlock(defaultCollapsed: isInType);
WriteAttributes(method.Module, methodDefinition.GetCustomAttributes());
foreach (var h in method.Handle.GetMethodImplementations(metadata)) {
var impl = metadata.GetMethodImplementation(h); var impl = metadata.GetMethodImplementation(h);
output.Write(".override method "); output.Write(".override method ");
var memberRef = impl.MethodDeclaration.CoerceMemberReference(method.Module); impl.MethodDeclaration.WriteTo(method.Module, output, new GenericContext(method));
memberRef.WriteTo(output, new GenericContext(method));
output.WriteLine(); output.WriteLine();
} }
foreach (var p in method.Parameters) { foreach (var p in methodDefinition.GetParameters()) {
WriteParameterAttributes(method.Module, p); WriteParameterAttributes(method.Module, p);
} }
WriteSecurityDeclarations(method.Module, method.DeclarativeSecurityAttributes); WriteSecurityDeclarations(method.Module, methodDefinition.GetDeclarativeSecurityAttributes());
if (method.HasBody) { if (method.Handle.HasBody(metadata)) {
methodBodyDisassembler.Disassemble(method); methodBodyDisassembler.Disassemble(method);
} }
CloseBlock("end of method " + DisassemblerHelpers.Escape(method.DeclaringType.Name) + "::" + DisassemblerHelpers.Escape(method.Name)); var declaringType = metadata.GetTypeDefinition(methodDefinition.GetDeclaringType());
CloseBlock("end of method " + DisassemblerHelpers.Escape(metadata.GetString(declaringType.Name)) + "::" + DisassemblerHelpers.Escape(metadata.GetString(methodDefinition.Name)));
} }
#region Write Security Declarations #region Write Security Declarations
@ -630,7 +632,7 @@ namespace ICSharpCode.Decompiler.Disassembler
} }
#endregion #endregion
void WriteParameters(MetadataReader metadata, ImmutableArray<ParameterHandle> parameters, MethodSignature<Action<ILNameSyntax>> signature) void WriteParameters(MetadataReader metadata, ParameterHandle[] parameters, MethodSignature<Action<ILNameSyntax>> signature)
{ {
int parameterOffset = parameters.Length > signature.ParameterTypes.Length ? 1 : 0; int parameterOffset = parameters.Length > signature.ParameterTypes.Length ? 1 : 0;
for (int i = 0; i < signature.ParameterTypes.Length; i++) { for (int i = 0; i < signature.ParameterTypes.Length; i++) {
@ -719,37 +721,43 @@ namespace ICSharpCode.Decompiler.Disassembler
{ FieldAttributes.NotSerialized, "notserialized" }, { FieldAttributes.NotSerialized, "notserialized" },
}; };
public void DisassembleField(Dom.FieldDefinition field) public void DisassembleField(Metadata.FieldDefinition field)
{ {
var metadata = field.Module.GetMetadataReader(); var metadata = field.Module.GetMetadataReader();
var fieldDefinition = metadata.GetFieldDefinition(field.Handle);
output.WriteDefinition(".field ", field); output.WriteDefinition(".field ", field);
int offset = field.Offset; int offset = fieldDefinition.GetOffset();
if (offset > -1) { if (offset > -1) {
output.Write("[" + offset + "] "); output.Write("[" + offset + "] ");
} }
WriteEnum(field.Attributes & FieldAttributes.FieldAccessMask, fieldVisibility); WriteEnum(fieldDefinition.Attributes & FieldAttributes.FieldAccessMask, fieldVisibility);
const FieldAttributes hasXAttributes = FieldAttributes.HasDefault | FieldAttributes.HasFieldMarshal | FieldAttributes.HasFieldRVA; const FieldAttributes hasXAttributes = FieldAttributes.HasDefault | FieldAttributes.HasFieldMarshal | FieldAttributes.HasFieldRVA;
WriteFlags(field.Attributes & ~(FieldAttributes.FieldAccessMask | hasXAttributes), fieldAttributes); WriteFlags(fieldDefinition.Attributes & ~(FieldAttributes.FieldAccessMask | hasXAttributes), fieldAttributes);
var signature = field.DecodeSignature(new DisassemblerSignatureProvider(field.Module, output), new GenericContext(field.DeclaringType)); var signature = fieldDefinition.DecodeSignature(new DisassemblerSignatureProvider(field.Module, output), new GenericContext(fieldDefinition.GetDeclaringType(), field.Module));
if (!field.GetMarshallingDescriptor().IsNil) { var marshallingDescriptor = fieldDefinition.GetMarshallingDescriptor();
WriteMarshalInfo(metadata.GetBlobReader(field.GetMarshallingDescriptor())); if (!marshallingDescriptor.IsNil) {
WriteMarshalInfo(metadata.GetBlobReader(marshallingDescriptor));
} }
signature(ILNameSyntax.Signature); signature(ILNameSyntax.Signature);
output.Write(' '); output.Write(' ');
output.Write(DisassemblerHelpers.Escape(field.Name)); output.Write(DisassemblerHelpers.Escape(metadata.GetString(fieldDefinition.Name)));
if (field.HasFlag(FieldAttributes.HasFieldRVA)) { if (fieldDefinition.HasFlag(FieldAttributes.HasFieldRVA)) {
output.Write(" at I_{0:x8}", field.RVA); output.Write(" at I_{0:x8}", fieldDefinition.GetRelativeVirtualAddress());
} }
if (!field.GetDefaultValue().IsNil) {
var defaultValue = fieldDefinition.GetDefaultValue();
if (!defaultValue.IsNil) {
output.Write(" = "); output.Write(" = ");
WriteConstant(metadata, metadata.GetConstant(field.GetDefaultValue())); WriteConstant(metadata, metadata.GetConstant(defaultValue));
} }
output.WriteLine(); output.WriteLine();
if (field.CustomAttributes.Count > 0) { var attributes = fieldDefinition.GetCustomAttributes();
if (attributes.Count > 0) {
output.MarkFoldStart(); output.MarkFoldStart();
WriteAttributes(field); WriteAttributes(field.Module, fieldDefinition.GetCustomAttributes());
output.MarkFoldEnd(); output.MarkFoldEnd();
} }
} }
@ -762,39 +770,43 @@ namespace ICSharpCode.Decompiler.Disassembler
{ PropertyAttributes.HasDefault, "hasdefault" }, { PropertyAttributes.HasDefault, "hasdefault" },
}; };
public void DisassembleProperty(Dom.PropertyDefinition property) public void DisassembleProperty(Metadata.PropertyDefinition property)
{ {
var metadata = property.Module.GetMetadataReader(); var metadata = property.Module.GetMetadataReader();
var propertyDefinition = metadata.GetPropertyDefinition(property.Handle);
output.WriteDefinition(".property ", property); output.WriteDefinition(".property ", property);
WriteFlags(property.Attributes, propertyAttributes); WriteFlags(propertyDefinition.Attributes, propertyAttributes);
var accessors = propertyDefinition.GetAccessors();
var declaringType = property.DeclaringType; var declaringType = metadata.GetMethodDefinition(accessors.GetAny()).GetDeclaringType();
var signature = property.DecodeSignature(new DisassemblerSignatureProvider(property.Module, output), new GenericContext(declaringType)); var signature = propertyDefinition.DecodeSignature(new DisassemblerSignatureProvider(property.Module, output), new GenericContext(declaringType, property.Module));
if (signature.Header.IsInstance) if (signature.Header.IsInstance)
output.Write("instance "); output.Write("instance ");
signature.ReturnType(ILNameSyntax.Signature); signature.ReturnType(ILNameSyntax.Signature);
output.Write(' '); output.Write(' ');
output.Write(DisassemblerHelpers.Escape(property.Name)); output.Write(DisassemblerHelpers.Escape(metadata.GetString(propertyDefinition.Name)));
output.Write("("); output.Write("(");
var parameters = property.GetAccessors().First().Method.Parameters; var parameters = metadata.GetMethodDefinition(accessors.Getter).GetParameters();
if (parameters.Count > 0) { if (parameters.Count > 0) {
output.WriteLine(); output.WriteLine();
output.Indent(); output.Indent();
WriteParameters(metadata, parameters.ToImmutableArray(), signature); WriteParameters(metadata, parameters.ToArray(), signature);
output.Unindent(); output.Unindent();
} }
output.Write(")"); output.Write(")");
OpenBlock(false); OpenBlock(false);
WriteAttributes(property); WriteAttributes(property.Module, propertyDefinition.GetCustomAttributes());
WriteNestedMethod(".get", property.GetMethod); WriteNestedMethod(".get", new Metadata.MethodDefinition(property.Module, accessors.Getter));
WriteNestedMethod(".set", property.SetMethod); WriteNestedMethod(".set", new Metadata.MethodDefinition(property.Module, accessors.Setter));
/*foreach (var method in property.OtherMethods) {
WriteNestedMethod(".other", method);
}*/
CloseBlock(); CloseBlock();
} }
void WriteNestedMethod(string keyword, Dom.MethodDefinition method) void WriteNestedMethod(string keyword, Metadata.MethodDefinition method)
{ {
if (method.IsNil) if (method.IsNil)
return; return;
@ -812,23 +824,33 @@ namespace ICSharpCode.Decompiler.Disassembler
{ EventAttributes.RTSpecialName, "rtspecialname" }, { EventAttributes.RTSpecialName, "rtspecialname" },
}; };
public void DisassembleEvent(Dom.EventDefinition ev) public void DisassembleEvent(Metadata.EventDefinition ev)
{ {
var metadata = ev.Module.GetMetadataReader(); var metadata = ev.Module.GetMetadataReader();
var eventDefinition = metadata.GetEventDefinition(ev.Handle);
var accessors = eventDefinition.GetAccessors();
TypeDefinitionHandle declaringType;
if (!accessors.Adder.IsNil) {
declaringType = metadata.GetMethodDefinition(accessors.Adder).GetDeclaringType();
} else if (!accessors.Remover.IsNil) {
declaringType = metadata.GetMethodDefinition(accessors.Remover).GetDeclaringType();
} else {
declaringType = metadata.GetMethodDefinition(accessors.Raiser).GetDeclaringType();
}
output.WriteDefinition(".event ", ev); output.WriteDefinition(".event ", ev);
WriteFlags(ev.Attributes, eventAttributes); WriteFlags(eventDefinition.Attributes, eventAttributes);
var signature = ev.DecodeSignature(new DisassemblerSignatureProvider(ev.Module, output), new GenericContext(ev.DeclaringType)); var signature = eventDefinition.DecodeSignature(metadata, new DisassemblerSignatureProvider(ev.Module, output), new GenericContext(declaringType, ev.Module));
signature(ILNameSyntax.TypeName); signature(ILNameSyntax.TypeName);
output.Write(' '); output.Write(' ');
output.Write(DisassemblerHelpers.Escape(ev.Name)); output.Write(DisassemblerHelpers.Escape(metadata.GetString(eventDefinition.Name)));
OpenBlock(false); OpenBlock(false);
WriteAttributes(ev); WriteAttributes(ev.Module, eventDefinition.GetCustomAttributes());
WriteNestedMethod(".addon", ev.AddMethod); WriteNestedMethod(".addon", new Metadata.MethodDefinition(ev.Module, accessors.Adder));
WriteNestedMethod(".removeon", ev.RemoveMethod); WriteNestedMethod(".removeon", new Metadata.MethodDefinition(ev.Module, accessors.Remover));
WriteNestedMethod(".fire", ev.InvokeMethod); WriteNestedMethod(".fire", new Metadata.MethodDefinition(ev.Module, accessors.Raiser));
foreach (var method in ev.OtherMethods) { /*foreach (var method in ev.OtherMethods) {
WriteNestedMethod(".other", method); WriteNestedMethod(".other", method);
} }*/
CloseBlock(); CloseBlock();
} }
#endregion #endregion
@ -868,32 +890,33 @@ namespace ICSharpCode.Decompiler.Disassembler
{ TypeAttributes.HasSecurity, null }, { TypeAttributes.HasSecurity, null },
}; };
public void DisassembleType(Dom.TypeDefinition type) public void DisassembleType(Metadata.TypeDefinition type)
{ {
var metadata = type.Module.GetMetadataReader(); var metadata = type.Module.GetMetadataReader();
var typeDefinition = metadata.GetTypeDefinition(type.Handle);
output.WriteDefinition(".class ", type); output.WriteDefinition(".class ", type);
if ((type.Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface) if ((typeDefinition.Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface)
output.Write("interface "); output.Write("interface ");
WriteEnum(type.Attributes & TypeAttributes.VisibilityMask, typeVisibility); WriteEnum(typeDefinition.Attributes & TypeAttributes.VisibilityMask, typeVisibility);
WriteEnum(type.Attributes & TypeAttributes.LayoutMask, typeLayout); WriteEnum(typeDefinition.Attributes & TypeAttributes.LayoutMask, typeLayout);
WriteEnum(type.Attributes & TypeAttributes.StringFormatMask, typeStringFormat); WriteEnum(typeDefinition.Attributes & TypeAttributes.StringFormatMask, typeStringFormat);
const TypeAttributes masks = TypeAttributes.ClassSemanticsMask | TypeAttributes.VisibilityMask | TypeAttributes.LayoutMask | TypeAttributes.StringFormatMask; const TypeAttributes masks = TypeAttributes.ClassSemanticsMask | TypeAttributes.VisibilityMask | TypeAttributes.LayoutMask | TypeAttributes.StringFormatMask;
WriteFlags(type.Attributes & ~masks, typeAttributes); WriteFlags(typeDefinition.Attributes & ~masks, typeAttributes);
output.Write(type.DeclaringType.IsNil ? type.FullName.ToILNameString() : DisassemblerHelpers.Escape(type.Name)); output.Write(typeDefinition.GetDeclaringType().IsNil ? typeDefinition.GetFullTypeName(metadata).ToILNameString() : DisassemblerHelpers.Escape(metadata.GetString(typeDefinition.Name)));
WriteTypeParameters(output, type.Module, new GenericContext(type), type.GenericParameters); WriteTypeParameters(output, type.Module, new GenericContext(type), typeDefinition.GetGenericParameters());
output.MarkFoldStart(defaultCollapsed: isInType); output.MarkFoldStart(defaultCollapsed: isInType);
output.WriteLine(); output.WriteLine();
if (type.BaseType != null) { if (!typeDefinition.BaseType.IsNil) {
output.Indent(); output.Indent();
output.Write("extends "); output.Write("extends ");
type.BaseType.WriteTo(output, new GenericContext(type), ILNameSyntax.TypeName); typeDefinition.BaseType.WriteTo(type.Module, output, new GenericContext(type), ILNameSyntax.TypeName);
output.WriteLine(); output.WriteLine();
output.Unindent(); output.Unindent();
} }
var interfaces = type.GetInterfaceImplementations(); var interfaces = typeDefinition.GetInterfaceImplementations();
if (interfaces.Count > 0) { if (interfaces.Count > 0) {
output.Indent(); output.Indent();
bool first = true; bool first = true;
@ -907,8 +930,7 @@ namespace ICSharpCode.Decompiler.Disassembler
first = false; first = false;
var iface = metadata.GetInterfaceImplementation(i); var iface = metadata.GetInterfaceImplementation(i);
WriteAttributes(type.Module, iface.GetCustomAttributes()); WriteAttributes(type.Module, iface.GetCustomAttributes());
var ifaceRef = iface.Interface.CoerceTypeReference(type.Module); iface.Interface.WriteTo(type.Module, output, new GenericContext(type), ILNameSyntax.TypeName);
ifaceRef.WriteTo(output, new GenericContext(type), ILNameSyntax.TypeName);
} }
output.WriteLine(); output.WriteLine();
output.Unindent(); output.Unindent();
@ -918,57 +940,62 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Indent(); output.Indent();
bool oldIsInType = isInType; bool oldIsInType = isInType;
isInType = true; isInType = true;
WriteAttributes(type); WriteAttributes(type.Module, typeDefinition.GetCustomAttributes());
WriteSecurityDeclarations(type.Module, type.DeclarativeSecurityAttributes); WriteSecurityDeclarations(type.Module, typeDefinition.GetDeclarativeSecurityAttributes());
var layout = type.GetLayout(); var layout = type.This().GetLayout();
if (!layout.IsDefault) { if (!layout.IsDefault) {
output.WriteLine(".pack {0}", layout.PackingSize); output.WriteLine(".pack {0}", layout.PackingSize);
output.WriteLine(".size {0}", layout.Size); output.WriteLine(".size {0}", layout.Size);
output.WriteLine(); output.WriteLine();
} }
if (!type.NestedTypes.IsEmpty) { var nestedTypes = typeDefinition.GetNestedTypes();
if (!nestedTypes.IsEmpty) {
output.WriteLine("// Nested Types"); output.WriteLine("// Nested Types");
foreach (var nestedType in type.NestedTypes) { foreach (var nestedType in nestedTypes) {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
DisassembleType(nestedType); DisassembleType(new Metadata.TypeDefinition(type.Module, nestedType));
output.WriteLine(); output.WriteLine();
} }
output.WriteLine(); output.WriteLine();
} }
if (!type.Fields.IsEmpty) { var fields = typeDefinition.GetFields();
if (fields.Any()) {
output.WriteLine("// Fields"); output.WriteLine("// Fields");
foreach (var field in type.Fields) { foreach (var field in fields) {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
DisassembleField(field); DisassembleField(new Metadata.FieldDefinition(type.Module, field));
} }
output.WriteLine(); output.WriteLine();
} }
if (!type.Methods.IsEmpty) { var methods = typeDefinition.GetMethods();
if (methods.Any()) {
output.WriteLine("// Methods"); output.WriteLine("// Methods");
foreach (var m in type.Methods) { foreach (var m in methods) {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
DisassembleMethod(m); DisassembleMethod(new Metadata.MethodDefinition(type.Module, m));
output.WriteLine(); output.WriteLine();
} }
} }
if (!type.Events.IsEmpty) { var events = typeDefinition.GetEvents();
if (events.Any()) {
output.WriteLine("// Events"); output.WriteLine("// Events");
foreach (var ev in type.Events) { foreach (var ev in events) {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
DisassembleEvent(ev); DisassembleEvent(new Metadata.EventDefinition(type.Module, ev));
output.WriteLine(); output.WriteLine();
} }
output.WriteLine(); output.WriteLine();
} }
if (!type.Properties.IsEmpty) { var properties = typeDefinition.GetProperties();
if (properties.Any()) {
output.WriteLine("// Properties"); output.WriteLine("// Properties");
foreach (var prop in type.Properties) { foreach (var prop in properties) {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
DisassembleProperty(prop); DisassembleProperty(new Metadata.PropertyDefinition(type.Module, prop));
} }
output.WriteLine(); output.WriteLine();
} }
CloseBlock("end of class " + (!type.DeclaringType.IsNil ? type.Name : type.FullName.ToString())); CloseBlock("end of class " + (!typeDefinition.GetDeclaringType().IsNil ? metadata.GetString(typeDefinition.Name) : typeDefinition.GetFullTypeName(metadata).ToString()));
isInType = oldIsInType; isInType = oldIsInType;
} }
@ -996,7 +1023,7 @@ namespace ICSharpCode.Decompiler.Disassembler
if (j > 0) if (j > 0)
output.Write(", "); output.Write(", ");
var constraint = metadata.GetGenericParameterConstraint(constraints[j]); var constraint = metadata.GetGenericParameterConstraint(constraints[j]);
constraint.Type.CoerceTypeReference(module).WriteTo(output, context, ILNameSyntax.TypeName); constraint.Type.WriteTo(module, output, context, ILNameSyntax.TypeName);
} }
output.Write(") "); output.Write(") ");
} }
@ -1013,18 +1040,13 @@ namespace ICSharpCode.Decompiler.Disassembler
#endregion #endregion
#region Helper methods #region Helper methods
void WriteAttributes(Dom.ICustomAttributeProvider attributes)
{
WriteAttributes(attributes.Module, attributes.CustomAttributes);
}
void WriteAttributes(PEFile module, CustomAttributeHandleCollection attributes) void WriteAttributes(PEFile module, CustomAttributeHandleCollection attributes)
{ {
var metadata = module.GetMetadataReader(); var metadata = module.GetMetadataReader();
foreach (CustomAttributeHandle a in attributes) { foreach (CustomAttributeHandle a in attributes) {
output.Write(".custom "); output.Write(".custom ");
var attr = metadata.GetCustomAttribute(a); var attr = metadata.GetCustomAttribute(a);
attr.Constructor.CoerceMemberReference(module).WriteTo(output, GenericContext.Empty); attr.Constructor.WriteTo(module, output, GenericContext.Empty);
byte[] blob = metadata.GetBlobBytes(attr.Value); byte[] blob = metadata.GetBlobBytes(attr.Value);
if (blob.Length > 0) { if (blob.Length > 0) {
output.Write(" = "); output.Write(" = ");
@ -1126,7 +1148,7 @@ namespace ICSharpCode.Decompiler.Disassembler
} }
#endregion #endregion
public void DisassembleNamespace(string nameSpace, IEnumerable<Dom.TypeDefinition> types) public void DisassembleNamespace(string nameSpace, IEnumerable<Metadata.TypeDefinition> types)
{ {
if (!string.IsNullOrEmpty(nameSpace)) { if (!string.IsNullOrEmpty(nameSpace)) {
output.Write(".namespace " + DisassemblerHelpers.Escape(nameSpace)); output.Write(".namespace " + DisassemblerHelpers.Escape(nameSpace));
@ -1440,7 +1462,7 @@ namespace ICSharpCode.Decompiler.Disassembler
default: default:
throw new NotSupportedException($"rawTypeKind: {rawTypeKind} (0x{rawTypeKind:x})"); throw new NotSupportedException($"rawTypeKind: {rawTypeKind} (0x{rawTypeKind:x})");
} }
var td = new Dom.TypeDefinition(module, handle); var td = new Metadata.TypeDefinition(module, handle);
td.WriteTo(output); td.WriteTo(output);
}; };
} }
@ -1460,7 +1482,7 @@ namespace ICSharpCode.Decompiler.Disassembler
default: default:
throw new NotSupportedException($"rawTypeKind: {rawTypeKind} (0x{rawTypeKind:x})"); throw new NotSupportedException($"rawTypeKind: {rawTypeKind} (0x{rawTypeKind:x})");
} }
var typeRef = new Dom.TypeReference(module, handle); var typeRef = new Metadata.TypeReference(module, handle);
typeRef.WriteTo(output); typeRef.WriteTo(output);
}; };
} }

389
ICSharpCode.Decompiler/Documentation/XmlDocKeyProvider.cs

@ -22,10 +22,10 @@ using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using Mono.Cecil; using ICSharpCode.Decompiler.Metadata;
using ArrayType = Mono.Cecil.ArrayType; using SRM = System.Reflection.Metadata;
using ByReferenceType = Mono.Cecil.ByReferenceType; using ICSharpCode.Decompiler.Util;
using PointerType = Mono.Cecil.PointerType; using System.Collections.Immutable;
namespace ICSharpCode.Decompiler.Documentation namespace ICSharpCode.Decompiler.Documentation
{ {
@ -35,160 +35,233 @@ namespace ICSharpCode.Decompiler.Documentation
public sealed class XmlDocKeyProvider public sealed class XmlDocKeyProvider
{ {
#region GetKey #region GetKey
public static string GetKey(MemberReference member) public static string GetKey(Entity entity)
{
return GetKey(entity.Module.GetMetadataReader(), entity.Handle);
}
public static string GetKey(SRM.MetadataReader metadata, SRM.EntityHandle member)
{ {
StringBuilder b = new StringBuilder(); StringBuilder b = new StringBuilder();
if (member is TypeReference) {
b.Append("T:"); void AppendTypeName(SRM.EntityHandle type)
AppendTypeName(b, (TypeReference)member); {
} else { switch (type.Kind) {
if (member is FieldReference) case SRM.HandleKind.TypeDefinition:
b.Append("F:"); b.Append("T:");
else if (member is PropertyDefinition) b.Append(((SRM.TypeDefinitionHandle)type).GetFullTypeName(metadata));
b.Append("P:"); break;
else if (member is EventDefinition) case SRM.HandleKind.TypeReference:
b.Append("E:"); b.Append("T:");
else if (member is MethodReference) b.Append(((SRM.TypeReferenceHandle)type).GetFullTypeName(metadata));
b.Append("M:"); break;
AppendTypeName(b, member.DeclaringType); default:
b.Append('.'); throw new NotImplementedException();
b.Append(member.Name.Replace('.', '#')); /*case SRM.HandleKind.TypeSpecification:
IList<ParameterDefinition> parameters; b.Append("T:");
TypeReference explicitReturnType = null; var typeSpec = metadata.GetTypeSpecification((SRM.TypeSpecificationHandle)type);
if (member is PropertyDefinition) { b.Append(typeSpec.DecodeSignature(new DocumentationKeySignatureTypeProvider(), default(Unit)));
parameters = ((PropertyDefinition)member).Parameters; break;*/
} else if (member is MethodReference) {
MethodReference mr = (MethodReference)member;
if (mr.HasGenericParameters) {
b.Append("``");
b.Append(mr.GenericParameters.Count);
}
parameters = mr.Parameters;
if (mr.Name == "op_Implicit" || mr.Name == "op_Explicit") {
explicitReturnType = mr.ReturnType;
}
} else {
parameters = null;
} }
if (parameters != null && parameters.Count > 0) { }
b.Append('(');
for (int i = 0; i < parameters.Count; i++) { void AppendSignature(SRM.MethodSignature<string> signature, bool printExplicitReturnType = false)
if (i > 0) b.Append(','); {
AppendTypeName(b, parameters[i].ParameterType); if (signature.GenericParameterCount > 0) {
} b.Append("``");
b.Append(')'); b.Append(signature.GenericParameterCount);
} }
if (explicitReturnType != null) { b.Append('(');
for (int i = 0; i < signature.ParameterTypes.Length; i++) {
if (i > 0)
b.Append(',');
b.Append(signature.ParameterTypes[i]);
}
b.Append(')');
if (printExplicitReturnType) {
b.Append('~'); b.Append('~');
AppendTypeName(b, explicitReturnType); b.Append(signature.ReturnType);
} }
} }
return b.ToString();
}
static void AppendTypeName(StringBuilder b, TypeReference type) switch (member.Kind) {
{ case SRM.HandleKind.TypeDefinition:
if (type == null) { case SRM.HandleKind.TypeReference:
// could happen when a TypeSpecification has no ElementType; e.g. function pointers in C++/CLI assemblies case SRM.HandleKind.TypeSpecification:
return; b.Append("T:");
} AppendTypeName(member);
if (type is GenericInstanceType) { break;
GenericInstanceType giType = (GenericInstanceType)type; case SRM.HandleKind.FieldDefinition:
AppendTypeNameWithArguments(b, giType.ElementType, giType.GenericArguments); b.Append("F:");
} else if (type is TypeSpecification) { var field = metadata.GetFieldDefinition((SRM.FieldDefinitionHandle)member);
AppendTypeName(b, ((TypeSpecification)type).ElementType); AppendTypeName(field.GetDeclaringType());
ArrayType arrayType = type as ArrayType; b.Append('.');
if (arrayType != null) { b.Append(metadata.GetString(field.Name).Replace('.', '#'));
b.Append('['); break;
for (int i = 0; i < arrayType.Dimensions.Count; i++) { case SRM.HandleKind.PropertyDefinition: {
if (i > 0) b.Append("P:");
b.Append(','); var property = metadata.GetPropertyDefinition((SRM.PropertyDefinitionHandle)member);
ArrayDimension ad = arrayType.Dimensions[i]; var accessors = property.GetAccessors();
if (ad.IsSized) { SRM.TypeDefinitionHandle declaringType;
b.Append(ad.LowerBound); if (!accessors.Getter.IsNil) {
b.Append(':'); declaringType = metadata.GetMethodDefinition(accessors.Getter).GetDeclaringType();
b.Append(ad.UpperBound); } else {
} declaringType = metadata.GetMethodDefinition(accessors.Setter).GetDeclaringType();
} }
b.Append(']'); AppendTypeName(declaringType);
} b.Append('.');
ByReferenceType refType = type as ByReferenceType; b.Append(metadata.GetString(property.Name).Replace('.', '#'));
if (refType != null) { AppendSignature(property.DecodeSignature(new DocumentationKeySignatureTypeProvider(), default(Unit)));
b.Append('@'); break;
}
PointerType ptrType = type as PointerType;
if (ptrType != null) {
b.Append('*');
} }
} else { case SRM.HandleKind.MethodDefinition:
GenericParameter gp = type as GenericParameter; b.Append("M:");
if (gp != null) { var method = metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)member);
b.Append('`'); AppendTypeName(method.GetDeclaringType());
if (gp.Owner.GenericParameterType == GenericParameterType.Method) { b.Append('.');
b.Append('`'); var methodName = metadata.GetString(method.Name);
b.Append(metadata.GetString(method.Name).Replace('.', '#'));
AppendSignature(method.DecodeSignature(new DocumentationKeySignatureTypeProvider(), default(Unit)), methodName == "op_Implicit" || methodName == "op_Explicit");
break;
case SRM.HandleKind.EventDefinition: {
b.Append("E:");
var @event = metadata.GetEventDefinition((SRM.EventDefinitionHandle)member);
var accessors = @event.GetAccessors();
SRM.TypeDefinitionHandle declaringType;
if (!accessors.Adder.IsNil) {
declaringType = metadata.GetMethodDefinition(accessors.Adder).GetDeclaringType();
} else if (!accessors.Remover.IsNil) {
declaringType = metadata.GetMethodDefinition(accessors.Remover).GetDeclaringType();
} else {
declaringType = metadata.GetMethodDefinition(accessors.Raiser).GetDeclaringType();
} }
b.Append(gp.Position); AppendTypeName(declaringType);
} else if (type.DeclaringType != null) {
AppendTypeName(b, type.DeclaringType);
b.Append('.'); b.Append('.');
b.Append(type.Name); b.Append(metadata.GetString(@event.Name).Replace('.', '#'));
} else { break;
b.Append(type.FullName);
} }
default:
throw new NotImplementedException();
} }
return b.ToString();
} }
static int AppendTypeNameWithArguments(StringBuilder b, TypeReference type, IList<TypeReference> genericArguments) public sealed class DocumentationKeySignatureTypeProvider : SRM.ISignatureTypeProvider<string, Unit>
{ {
int outerTypeParameterCount = 0; public string GetArrayType(string elementType, SRM.ArrayShape shape)
if (type.DeclaringType != null) { {
TypeReference declType = type.DeclaringType; string shapeString = "";
outerTypeParameterCount = AppendTypeNameWithArguments(b, declType, genericArguments); for (int i = 0; i < shape.Rank; i++) {
b.Append('.'); if (i > 0)
} else if (!string.IsNullOrEmpty(type.Namespace)) { shapeString += ',';
b.Append(type.Namespace); int? lowerBound = i < shape.LowerBounds.Length ? (int?)shape.LowerBounds[i] : null;
b.Append('.'); int? size = i < shape.Sizes.Length ? (int?)shape.Sizes[i] : null;
} if (lowerBound != null || size != null) {
int localTypeParameterCount = 0; shapeString += lowerBound.ToString();
b.Append(ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out localTypeParameterCount)); shapeString += ':';
shapeString += (lowerBound + size - 1).ToString();
if (localTypeParameterCount > 0) { }
int totalTypeParameterCount = outerTypeParameterCount + localTypeParameterCount;
b.Append('{');
for (int i = outerTypeParameterCount; i < totalTypeParameterCount && i < genericArguments.Count; i++) {
if (i > outerTypeParameterCount) b.Append(',');
AppendTypeName(b, genericArguments[i]);
} }
b.Append('}'); return elementType + "[" + shapeString + "]";
}
public string GetByReferenceType(string elementType)
{
return elementType + '@';
}
public string GetFunctionPointerType(SRM.MethodSignature<string> signature)
{
return "";
}
public string GetGenericInstantiation(string genericType, ImmutableArray<string> typeArguments)
{
string arguments = "";
for (int i = 0; i < typeArguments.Length; i++) {
if (i > 0)
arguments += ',';
arguments += typeArguments[i];
}
return genericType + "{" + arguments + "}";
}
public string GetGenericMethodParameter(Unit genericContext, int index)
{
return "``" + index;
}
public string GetGenericTypeParameter(Unit genericContext, int index)
{
return "`" + index;
}
public string GetModifiedType(string modifier, string unmodifiedType, bool isRequired)
{
throw new NotImplementedException();
}
public string GetPinnedType(string elementType)
{
throw new NotImplementedException();
}
public string GetPointerType(string elementType)
{
return elementType + '*';
}
public string GetPrimitiveType(SRM.PrimitiveTypeCode typeCode)
{
return $"System.{typeCode}";
}
public string GetSZArrayType(string elementType)
{
return elementType + "[]";
}
public string GetTypeFromDefinition(SRM.MetadataReader reader, SRM.TypeDefinitionHandle handle, byte rawTypeKind)
{
return handle.GetFullTypeName(reader).ToString();
}
public string GetTypeFromReference(SRM.MetadataReader reader, SRM.TypeReferenceHandle handle, byte rawTypeKind)
{
return handle.GetFullTypeName(reader).ToString();
}
public string GetTypeFromSpecification(SRM.MetadataReader reader, Unit genericContext, SRM.TypeSpecificationHandle handle, byte rawTypeKind)
{
return handle.GetFullTypeName(reader).ToString();
} }
return outerTypeParameterCount + localTypeParameterCount;
} }
#endregion #endregion
#region FindMemberByKey #region FindMemberByKey
public static MemberReference FindMemberByKey(ModuleDefinition module, string key) public static Entity FindMemberByKey(PEFile module, string key)
{ {
if (module == null) if (module == null)
throw new ArgumentNullException(nameof(module)); throw new ArgumentNullException(nameof(module));
if (key == null || key.Length < 2 || key[1] != ':') if (key == null || key.Length < 2 || key[1] != ':')
return null; return default(Entity);
switch (key[0]) { switch (key[0]) {
case 'T': case 'T':
return FindType(module, key.Substring(2)); return FindType(module, key.Substring(2));
case 'F': case 'F':
return FindMember(module, key, type => type.Fields); return FindMember(module, key, type => type.This().GetFields().Select(f => new Entity(module, f)));
case 'P': case 'P':
return FindMember(module, key, type => type.Properties); return FindMember(module, key, type => type.This().GetProperties().Select(p => new Entity(module, p)));
case 'E': case 'E':
return FindMember(module, key, type => type.Events); return FindMember(module, key, type => type.This().GetEvents().Select(e => new Entity(module, e)));
case 'M': case 'M':
return FindMember(module, key, type => type.Methods); return FindMember(module, key, type => type.This().GetMethods().Select(m => new Entity(module, m)));
default: default:
return null; return default(Entity);
} }
} }
static MemberReference FindMember(ModuleDefinition module, string key, Func<TypeDefinition, IEnumerable<MemberReference>> memberSelector) static Entity FindMember(PEFile module, string key, Func<TypeDefinition, IEnumerable<Entity>> memberSelector)
{ {
Debug.WriteLine("Looking for member " + key); Debug.WriteLine("Looking for member " + key);
int parenPos = key.IndexOf('('); int parenPos = key.IndexOf('(');
@ -198,50 +271,80 @@ namespace ICSharpCode.Decompiler.Documentation
} else { } else {
dotPos = key.LastIndexOf('.'); dotPos = key.LastIndexOf('.');
} }
if (dotPos < 0) return null; if (dotPos < 0)
return default(Entity);
TypeDefinition type = FindType(module, key.Substring(2, dotPos - 2)); TypeDefinition type = FindType(module, key.Substring(2, dotPos - 2));
if (type == null) if (type == null)
return null; return default(Entity);
string shortName; string shortName;
if (parenPos > 0) { if (parenPos > 0) {
shortName = key.Substring(dotPos + 1, parenPos - (dotPos + 1)); shortName = key.Substring(dotPos + 1, parenPos - (dotPos + 1));
} else { } else {
shortName = key.Substring(dotPos + 1); shortName = key.Substring(dotPos + 1);
} }
Debug.WriteLine("Searching in type {0} for {1}", type.FullName, shortName); Debug.WriteLine("Searching in type {0} for {1}", type.Handle.GetFullTypeName(module.GetMetadataReader()), shortName);
MemberReference shortNameMatch = null; Entity shortNameMatch = default(Entity);
foreach (MemberReference member in memberSelector(type)) { var metadata = module.GetMetadataReader();
foreach (var member in memberSelector(type)) {
string memberKey = GetKey(member); string memberKey = GetKey(member);
Debug.WriteLine(memberKey); Debug.WriteLine(memberKey);
if (memberKey == key) if (memberKey == key)
return member; return member;
if (shortName == member.Name.Replace('.', '#')) string name;
switch (member.Handle.Kind) {
case SRM.HandleKind.MethodDefinition:
name = metadata.GetString(metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)member.Handle).Name);
break;
case SRM.HandleKind.FieldDefinition:
name = metadata.GetString(metadata.GetFieldDefinition((SRM.FieldDefinitionHandle)member.Handle).Name);
break;
case SRM.HandleKind.PropertyDefinition:
name = metadata.GetString(metadata.GetPropertyDefinition((SRM.PropertyDefinitionHandle)member.Handle).Name);
break;
case SRM.HandleKind.EventDefinition:
name = metadata.GetString(metadata.GetEventDefinition((SRM.EventDefinitionHandle)member.Handle).Name);
break;
default:
throw new NotSupportedException();
}
if (shortName == name.Replace('.', '#'))
shortNameMatch = member; shortNameMatch = member;
} }
// if there's no match by ID string (key), return the match by name. // if there's no match by ID string (key), return the match by name.
return shortNameMatch; return shortNameMatch;
} }
static TypeDefinition FindType(ModuleDefinition module, string name) static TypeDefinition FindType(PEFile module, string name)
{ {
int pos = name.LastIndexOf('.'); var metadata = module.GetMetadataReader();
string ns; string[] segments = name.Split('.');
if (pos >= 0) { var currentNamespace = metadata.GetNamespaceDefinitionRoot();
ns = name.Substring(0, pos); int i = 0;
name = name.Substring(pos + 1); while (i < segments.Length) {
} else { string part = segments[i];
ns = string.Empty; var next = currentNamespace.NamespaceDefinitions.FirstOrDefault(ns => metadata.GetString(metadata.GetNamespaceDefinition(ns).Name) == part);
} if (next.IsNil)
if (string.IsNullOrEmpty(name)) return null; break;
TypeDefinition type = module.GetType(ns, name); currentNamespace = metadata.GetNamespaceDefinition(next);
if (type == null && ns.Length > 0) { i++;
// try if this is a nested type }
type = FindType(module, ns); if (i == segments.Length)
if (type != null) { return default(TypeDefinition);
type = type.NestedTypes.FirstOrDefault(t => t.Name == name); var typeDefinitions = currentNamespace.TypeDefinitions;
while (i < segments.Length) {
string part = segments[i];
foreach (var t in typeDefinitions) {
var type = metadata.GetTypeDefinition(t);
if (metadata.GetString(type.Name) == part) {
if (i + 1 == segments.Length)
return new TypeDefinition(module, t);
typeDefinitions = type.GetNestedTypes();
i++;
break;
}
} }
} }
return type; return default(TypeDefinition);
} }
#endregion #endregion
} }

43
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -277,26 +277,27 @@
<Compile Include="Documentation\XmlDocKeyProvider.cs" /> <Compile Include="Documentation\XmlDocKeyProvider.cs" />
<Compile Include="Documentation\XmlDocLoader.cs" /> <Compile Include="Documentation\XmlDocLoader.cs" />
<Compile Include="Documentation\XmlDocumentationProvider.cs" /> <Compile Include="Documentation\XmlDocumentationProvider.cs" />
<Compile Include="Dom\Dom.cs" /> <Compile Include="Metadata\Dom.cs" />
<Compile Include="Dom\MetadataResolver.cs" /> <Compile Include="Metadata\MetadataResolver.cs" />
<Compile Include="DotNetCore\DotNetCorePathFinder.cs" /> <Compile Include="Metadata\DotNetCorePathFinder.cs" />
<Compile Include="DotNetCore\DotNetCorePathFinderExtensions.cs" /> <Compile Include="Metadata\DotNetCorePathFinderExtensions.cs" />
<Compile Include="DotNetCore\LightJson\JsonArray.cs" /> <Compile Include="Metadata\LightJson\JsonArray.cs" />
<Compile Include="DotNetCore\LightJson\JsonObject.cs" /> <Compile Include="Metadata\LightJson\JsonObject.cs" />
<Compile Include="DotNetCore\LightJson\JsonValue.cs" /> <Compile Include="Metadata\LightJson\JsonValue.cs" />
<Compile Include="DotNetCore\LightJson\JsonValueType.cs" /> <Compile Include="Metadata\LightJson\JsonValueType.cs" />
<Compile Include="DotNetCore\LightJson\Serialization\JsonParseException.cs" /> <Compile Include="Metadata\LightJson\Serialization\JsonParseException.cs" />
<Compile Include="DotNetCore\LightJson\Serialization\JsonReader.cs" /> <Compile Include="Metadata\LightJson\Serialization\JsonReader.cs" />
<Compile Include="DotNetCore\LightJson\Serialization\JsonSerializationException.cs" /> <Compile Include="Metadata\LightJson\Serialization\JsonSerializationException.cs" />
<Compile Include="DotNetCore\LightJson\Serialization\JsonWriter.cs" /> <Compile Include="Metadata\LightJson\Serialization\JsonWriter.cs" />
<Compile Include="DotNetCore\LightJson\Serialization\TextPosition.cs" /> <Compile Include="Metadata\LightJson\Serialization\TextPosition.cs" />
<Compile Include="DotNetCore\LightJson\Serialization\TextScanner.cs" /> <Compile Include="Metadata\LightJson\Serialization\TextScanner.cs" />
<Compile Include="DotNetCore\UniversalAssemblyResolver.cs" /> <Compile Include="Metadata\OperandType.cs" />
<Compile Include="DotNetCore\UnresolvedAssemblyNameReference.cs" /> <Compile Include="Metadata\UniversalAssemblyResolver.cs" />
<Compile Include="Metadata\UnresolvedAssemblyNameReference.cs" />
<Compile Include="IL\ILAstWritingOptions.cs" /> <Compile Include="IL\ILAstWritingOptions.cs" />
<Compile Include="IL\Instructions\LdFlda.cs" /> <Compile Include="IL\Instructions\LdFlda.cs" />
<Compile Include="IL\Instructions\StLoc.cs" /> <Compile Include="IL\Instructions\StLoc.cs" />
<Compile Include="Dom\SequencePoint.cs" /> <Compile Include="Metadata\SequencePoint.cs" />
<Compile Include="IL\Instructions\CallIndirect.cs" /> <Compile Include="IL\Instructions\CallIndirect.cs" />
<Compile Include="IL\Instructions\DefaultValue.cs" /> <Compile Include="IL\Instructions\DefaultValue.cs" />
<Compile Include="IL\Transforms\EarlyExpressionTransforms.cs" /> <Compile Include="IL\Transforms\EarlyExpressionTransforms.cs" />
@ -329,8 +330,10 @@
<Compile Include="IL\Transforms\StatementTransform.cs" /> <Compile Include="IL\Transforms\StatementTransform.cs" />
<Compile Include="IL\Transforms\TransformCollectionAndObjectInitializers.cs" /> <Compile Include="IL\Transforms\TransformCollectionAndObjectInitializers.cs" />
<Compile Include="Output\TextTokenWriter.cs" /> <Compile Include="Output\TextTokenWriter.cs" />
<Compile Include="SRMExtensions.cs" />
<Compile Include="SRMHacks.cs" />
<Compile Include="TypeSystem\Implementation\TypeSpecification.cs" /> <Compile Include="TypeSystem\Implementation\TypeSpecification.cs" />
<Compile Include="Dom\MetadataExtensions.cs" /> <Compile Include="Metadata\MetadataExtensions.cs" />
<Compile Include="Util\GraphVizGraph.cs" /> <Compile Include="Util\GraphVizGraph.cs" />
<Compile Include="Util\KeyComparer.cs" /> <Compile Include="Util\KeyComparer.cs" />
<Compile Include="Util\LongDict.cs" /> <Compile Include="Util\LongDict.cs" />
@ -396,7 +399,7 @@
<Compile Include="Disassembler\ReflectionDisassembler.cs" /> <Compile Include="Disassembler\ReflectionDisassembler.cs" />
<Compile Include="IL\SemanticHelper.cs" /> <Compile Include="IL\SemanticHelper.cs" />
<Compile Include="IL\BlockBuilder.cs" /> <Compile Include="IL\BlockBuilder.cs" />
<Compile Include="IL\ILOpCodes.cs"> <Compile Include="Metadata\ILOpCodes.cs">
<AutoGen>True</AutoGen> <AutoGen>True</AutoGen>
<DesignTime>True</DesignTime> <DesignTime>True</DesignTime>
<DependentUpon>ILOpCodes.tt</DependentUpon> <DependentUpon>ILOpCodes.tt</DependentUpon>
@ -576,7 +579,7 @@
<None Include="ICSharpCode.Decompiler.nuspec.template" /> <None Include="ICSharpCode.Decompiler.nuspec.template" />
<None Include="ICSharpCode.Decompiler.ruleset" /> <None Include="ICSharpCode.Decompiler.ruleset" />
<None Include="ICSharpCode.Decompiler.snk" /> <None Include="ICSharpCode.Decompiler.snk" />
<None Include="IL\ILOpCodes.tt"> <None Include="Metadata\ILOpCodes.tt">
<Generator>TextTemplatingFileGenerator</Generator> <Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>ILOpCodes.cs</LastGenOutput> <LastGenOutput>ILOpCodes.cs</LastGenOutput>
</None> </None>

168
ICSharpCode.Decompiler/IL/ILOpCodes.tt

@ -1,168 +0,0 @@
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Reflection.Metadata" #>
<#@ import namespace="System.Reflection.Emit" #>
<#@ output extension=".cs" #>
using System;
using System.Collections.Generic;
using System.Reflection.Metadata;
<#
var operandTypes = Enumerable.Repeat((OperandType)0xff, 0x11f).ToArray();
var operandNames = new string[0x11f];
#>
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Describes the operand type of Microsoft intermediate language (MSIL) instruction.</summary>
public enum OperandType
{
/// <summary>The operand is a 32-bit integer branch target.</summary>
BrTarget,
/// <summary>The operand is a 32-bit metadata token.</summary>
Field,
/// <summary>The operand is a 32-bit integer.</summary>
I,
/// <summary>The operand is a 64-bit integer.</summary>
I8,
/// <summary>The operand is a 32-bit metadata token.</summary>
Method,
/// <summary>No operand.</summary>
None,
/// <summary>The operand is reserved and should not be used.</summary>
[Obsolete("This API has been deprecated. http://go.microsoft.com/fwlink/?linkid=14202")]
Phi,
/// <summary>The operand is a 64-bit IEEE floating point number.</summary>
R,
/// <summary>The operand is a 32-bit metadata signature token.</summary>
Sig = 9,
/// <summary>The operand is a 32-bit metadata string token.</summary>
String,
/// <summary>The operand is the 32-bit integer argument to a switch instruction.</summary>
Switch,
/// <summary>The operand is a <see langword="FieldRef" />, <see langword="MethodRef" />, or <see langword="TypeRef" /> token.</summary>
Tok,
/// <summary>The operand is a 32-bit metadata token.</summary>
Type,
/// <summary>The operand is 16-bit integer containing the ordinal of a local variable or an argument.</summary>
Variable,
/// <summary>The operand is an 8-bit integer branch target.</summary>
ShortBrTarget,
/// <summary>The operand is an 8-bit integer.</summary>
ShortI,
/// <summary>The operand is a 32-bit IEEE floating point number.</summary>
ShortR,
/// <summary>The operand is an 8-bit integer containing the ordinal of a local variable or an argumenta.</summary>
ShortVariable
}
<#
foreach (var field in typeof(OpCodes).GetFields()) {
var opCode = (OpCode)field.GetValue(null);
ushort index = (ushort)(((opCode.Value & 0x200) >> 1) | (opCode.Value & 0xff));
operandTypes[index] = opCode.OperandType;
operandNames[index] = opCode.Name;
} #>
static class ILOpCodeExtensions
{
// We use a byte array instead of an enum array because it can be initialized more efficiently
static readonly byte[] operandTypes = { <#
foreach (var operandType in operandTypes) {
if ((byte)operandType == 255) {
Write("255, ");
} else {
string operandTypeName = operandType.ToString().Replace("Inline", "").Replace("Var", "Variable");
Write("(byte)OperandType." + operandTypeName + ", ");
}
}
#> };
static readonly string[] operandNames = { <#
foreach (var operandName in operandNames) {
Write("\"" + operandName + "\", ");
}
#> };
public static OperandType GetOperandType(this ILOpCode opCode)
{
ushort index = (ushort)((((int)opCode & 0x200) >> 1) | ((int)opCode & 0xff));
if (index >= operandTypes.Length)
return (OperandType)255;
return (OperandType)operandTypes[index];
}
public static string GetDisplayName(this ILOpCode opCode)
{
ushort index = (ushort)((((int)opCode & 0x200) >> 1) | ((int)opCode & 0xff));
if (index >= operandNames.Length)
return "";
return operandNames[index];
}
public static bool IsDefined(this ILOpCode opCode)
{
return !string.IsNullOrEmpty(GetDisplayName(opCode));
}
public static readonly HashSet<string> ILKeywords = BuildKeywordList(
"abstract", "algorithm", "alignment", "ansi", "any", "arglist",
"array", "as", "assembly", "assert", "at", "auto", "autochar", "beforefieldinit",
"blob", "blob_object", "bool", "brnull", "brnull.s", "brzero", "brzero.s", "bstr",
"bytearray", "byvalstr", "callmostderived", "carray", "catch", "cdecl", "cf",
"char", "cil", "class", "clsid", "const", "currency", "custom", "date", "decimal",
"default", "demand", "deny", "endmac", "enum", "error", "explicit", "extends", "extern",
"false", "famandassem", "family", "famorassem", "fastcall", "fault", "field", "filetime",
"filter", "final", "finally", "fixed", "float", "float32", "float64", "forwardref",
"fromunmanaged", "handler", "hidebysig", "hresult", "idispatch", "il", "illegal",
"implements", "implicitcom", "implicitres", "import", "in", "inheritcheck", "init",
"initonly", "instance", "int", "int16", "int32", "int64", "int8", "interface", "internalcall",
"iunknown", "lasterr", "lcid", "linkcheck", "literal", "localloc", "lpstr", "lpstruct", "lptstr",
"lpvoid", "lpwstr", "managed", "marshal", "method", "modopt", "modreq", "native", "nested",
"newslot", "noappdomain", "noinlining", "nomachine", "nomangle", "nometadata", "noncasdemand",
"noncasinheritance", "noncaslinkdemand", "noprocess", "not", "not_in_gc_heap", "notremotable",
"notserialized", "null", "nullref", "object", "objectref", "opt", "optil", "out",
"permitonly", "pinned", "pinvokeimpl", "prefix1", "prefix2", "prefix3", "prefix4", "prefix5", "prefix6",
"prefix7", "prefixref", "prejitdeny", "prejitgrant", "preservesig", "private", "privatescope", "protected",
"public", "record", "refany", "reqmin", "reqopt", "reqrefuse", "reqsecobj", "request", "retval",
"rtspecialname", "runtime", "safearray", "sealed", "sequential", "serializable", "special", "specialname",
"static", "stdcall", "storage", "stored_object", "stream", "streamed_object", "string", "struct",
"synchronized", "syschar", "sysstring", "tbstr", "thiscall", "tls", "to", "true", "typedref",
"unicode", "unmanaged", "unmanagedexp", "unsigned", "unused", "userdefined", "value", "valuetype",
"vararg", "variant", "vector", "virtual", "void", "wchar", "winapi", "with", "wrapper",
// These are not listed as keywords in spec, but ILAsm treats them as such
"property", "type", "flags", "callconv", "strict"
);
static HashSet<string> BuildKeywordList(params string[] keywords)
{
HashSet<string> s = new HashSet<string>(keywords);
foreach (var inst in operandNames) {
if (string.IsNullOrEmpty(inst))
continue;
s.Add(inst);
}
return s;
}
}
}

585
ICSharpCode.Decompiler/Dom/Dom.cs → ICSharpCode.Decompiler/Metadata/Dom.cs

@ -9,10 +9,11 @@ using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable; using System.Reflection.PortableExecutable;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
using ICSharpCode.Decompiler.Documentation;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.Dom namespace ICSharpCode.Decompiler.Metadata
{ {
using SRMMemberRef = System.Reflection.Metadata.MemberReference; using SRMMemberRef = System.Reflection.Metadata.MemberReference;
using SRMMethod = System.Reflection.Metadata.MethodDefinition; using SRMMethod = System.Reflection.Metadata.MethodDefinition;
@ -41,12 +42,6 @@ namespace ICSharpCode.Decompiler.Dom
} }
} }
public interface ICustomAttributeProvider
{
PEFile Module { get; }
CustomAttributeHandleCollection CustomAttributes { get; }
}
public interface IAssemblyResolver public interface IAssemblyResolver
{ {
PEFile Resolve(IAssemblyReference reference); PEFile Resolve(IAssemblyReference reference);
@ -66,45 +61,21 @@ namespace ICSharpCode.Decompiler.Dom
public interface IAssemblyDocumentationResolver public interface IAssemblyDocumentationResolver
{ {
XmlDocumentationProvider GetProvider();
} }
public struct Variable { } public interface IMetadataEntity
public interface IDebugInfoProvider
{
IList<SequencePoint> GetSequencePoints(MethodDefinition method);
IList<Variable> GetVariables(MethodDefinition method);
}
public interface IMemberReference
{ {
PEFile Module { get; } PEFile Module { get; }
string Name { get; } EntityHandle Handle { get; }
IMemberDefinition GetDefinition();
ITypeReference DeclaringType { get; }
} }
public interface IMemberDefinition : IMemberReference, ICustomAttributeProvider public struct Variable { }
{
new TypeDefinition DeclaringType { get; }
}
public interface IMethodReference : IMemberReference
{
}
public interface ITypeReference : IMemberReference
{
PEFile Module { get; }
FullTypeName FullName { get; }
string Namespace { get; }
new TypeDefinition GetDefinition();
}
public interface ITypeDefinition : ITypeReference, IMemberDefinition public interface IDebugInfoProvider
{ {
new PEFile Module { get; } IList<SequencePoint> GetSequencePoints(MethodDefinition method);
TypeDefinitionHandle Handle { get; } IList<Variable> GetVariables(MethodDefinition method);
} }
public class PEFile public class PEFile
@ -348,11 +319,107 @@ namespace ICSharpCode.Decompiler.Dom
} }
} }
public struct MethodDefinition : IEquatable<MethodDefinition>, IMethodReference, IMemberDefinition public struct Entity : IEquatable<Entity>, IMetadataEntity
{
public PEFile Module { get; }
public EntityHandle Handle { get; }
public bool IsNil => Handle.IsNil;
public Entity(PEFile module, EntityHandle handle) : this()
{
this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle;
}
public bool IsType() => Handle.Kind == HandleKind.TypeDefinition || Handle.Kind == HandleKind.TypeReference || Handle.Kind == HandleKind.TypeSpecification;
public TypeDefinition ResolveAsType()
{
return MetadataResolver.ResolveType(Handle, new SimpleMetadataResolveContext(Module));
}
public MethodDefinition ResolveAsMethod()
{
return MetadataResolver.ResolveMember(Handle, new SimpleMetadataResolveContext(Module));
}
public bool Equals(Entity other)
{
return Module == other.Module && Handle == other.Handle;
}
public override bool Equals(object obj)
{
if (obj is Entity entity)
return Equals(entity);
return false;
}
public override int GetHashCode()
{
return unchecked(982451629 * Module.GetHashCode() + 982451653 * MetadataTokens.GetToken(Handle));
}
public static bool operator ==(Entity lhs, Entity rhs) => lhs.Equals(rhs);
public static bool operator !=(Entity lhs, Entity rhs) => !lhs.Equals(rhs);
public static implicit operator Entity(MethodDefinition method)
{
return new Entity(method.Module, method.Handle);
}
public static implicit operator Entity(PropertyDefinition property)
{
return new Entity(property.Module, property.Handle);
}
public static implicit operator Entity(EventDefinition @event)
{
return new Entity(@event.Module, @event.Handle);
}
public static implicit operator Entity(FieldDefinition field)
{
return new Entity(field.Module, field.Handle);
}
public static implicit operator Entity(TypeDefinition type)
{
return new Entity(type.Module, type.Handle);
}
public static implicit operator TypeDefinition(Entity entity)
{
return new TypeDefinition(entity.Module, (TypeDefinitionHandle)entity.Handle);
}
public static implicit operator MethodDefinition(Entity entity)
{
return new MethodDefinition(entity.Module, (MethodDefinitionHandle)entity.Handle);
}
public static implicit operator PropertyDefinition(Entity entity)
{
return new PropertyDefinition(entity.Module, (PropertyDefinitionHandle)entity.Handle);
}
public static implicit operator EventDefinition(Entity entity)
{
return new EventDefinition(entity.Module, (EventDefinitionHandle)entity.Handle);
}
public static implicit operator FieldDefinition(Entity entity)
{
return new FieldDefinition(entity.Module, (FieldDefinitionHandle)entity.Handle);
}
}
public struct MethodDefinition : IEquatable<MethodDefinition>, IMetadataEntity
{ {
public PEFile Module { get; } public PEFile Module { get; }
public MethodDefinitionHandle Handle { get; } public MethodDefinitionHandle Handle { get; }
public bool IsNil => Handle.IsNil; public bool IsNil => Handle.IsNil;
EntityHandle IMetadataEntity.Handle => Handle;
public MethodDefinition(PEFile module, MethodDefinitionHandle handle) : this() public MethodDefinition(PEFile module, MethodDefinitionHandle handle) : this()
{ {
@ -360,7 +427,7 @@ namespace ICSharpCode.Decompiler.Dom
this.Handle = handle; this.Handle = handle;
} }
SRMMethod This() => Module.GetMetadataReader().GetMethodDefinition(Handle); public SRMMethod This() => Module.GetMetadataReader().GetMethodDefinition(Handle);
public bool Equals(MethodDefinition other) public bool Equals(MethodDefinition other)
{ {
@ -388,9 +455,8 @@ namespace ICSharpCode.Decompiler.Dom
return reader.GetString(reader.GetMethodDefinition(Handle).Name); return reader.GetString(reader.GetMethodDefinition(Handle).Name);
} }
} }
/*
public TypeDefinition DeclaringType => new TypeDefinition(Module, This().GetDeclaringType()); public TypeDefinition DeclaringType => new TypeDefinition(Module, This().GetDeclaringType());
ITypeReference IMemberReference.DeclaringType => DeclaringType;
public MethodAttributes Attributes => This().Attributes; public MethodAttributes Attributes => This().Attributes;
public MethodImplAttributes ImplAttributes => This().ImplAttributes; public MethodImplAttributes ImplAttributes => This().ImplAttributes;
@ -399,80 +465,7 @@ namespace ICSharpCode.Decompiler.Dom
public bool HasFlag(MethodAttributes attribute) => (This().Attributes & attribute) == attribute; public bool HasFlag(MethodAttributes attribute) => (This().Attributes & attribute) == attribute;
public bool HasPInvokeInfo => !This().GetImport().Module.IsNil || HasFlag(MethodAttributes.PinvokeImpl); public bool HasPInvokeInfo => !This().GetImport().Module.IsNil || HasFlag(MethodAttributes.PinvokeImpl);
public bool IsConstructor => This().IsConstructor(Module.GetMetadataReader()); public bool IsConstructor => This().IsConstructor(Module.GetMetadataReader());
public bool HasParameters => This().GetParameters().Count > 0; public bool HasParameters => This().GetParameters().Count > 0;*/
public bool HasBody => (Attributes & MethodAttributes.Abstract) == 0 &&
(Attributes & MethodAttributes.PinvokeImpl) == 0 &&
(ImplAttributes & MethodImplAttributes.InternalCall) == 0 &&
(ImplAttributes & MethodImplAttributes.Native) == 0 &&
(ImplAttributes & MethodImplAttributes.Unmanaged) == 0 &&
(ImplAttributes & MethodImplAttributes.Runtime) == 0;
public int RVA => This().RelativeVirtualAddress;
public MethodBodyBlock Body => Module.Reader.GetMethodBody(RVA);
public MethodImport Import => This().GetImport();
public GenericParameterHandleCollection GenericParameters => This().GetGenericParameters();
public ParameterHandleCollection Parameters => This().GetParameters();
public bool IsExtensionMethod {
get {
if (!HasFlag(MethodAttributes.Static)) {
var metadata = Module.GetMetadataReader();
foreach (var attribute in This().GetCustomAttributes()) {
string typeName = metadata.GetCustomAttribute(attribute).GetAttributeType(Module).FullName.ToString();
if (typeName == "System.Runtime.CompilerServices.ExtensionAttribute")
return true;
}
}
return false;
}
}
public unsafe MethodSemanticsAttributes GetMethodSemanticsAttributes()
{
var reader = Module.GetMetadataReader();
byte* startPointer = reader.MetadataPointer;
int offset = reader.GetTableMetadataOffset(TableIndex.MethodSemantics);
int rowSize = reader.GetTableRowSize(TableIndex.MethodSemantics);
int rowCount = reader.GetTableRowCount(TableIndex.MethodSemantics);
var small = reader.IsSmallReference(TableIndex.MethodDef);
int methodRowNo = reader.GetRowNumber(Handle);
for (int row = rowCount - 1; row >= 0; row--) {
byte* ptr = startPointer + offset + rowSize * row;
uint rowNo = small ? *(ushort*)(ptr + 2) : *(uint*)(ptr + 2);
if (methodRowNo == rowNo) {
return (MethodSemanticsAttributes)(*(ushort*)ptr);
}
}
return 0;
}
public unsafe ImmutableArray<MethodImplementationHandle> GetMethodImplementations()
{
var reader = Module.GetMetadataReader();
byte* startPointer = reader.MetadataPointer;
int offset = reader.GetTableMetadataOffset(TableIndex.MethodImpl);
int rowSize = reader.GetTableRowSize(TableIndex.MethodImpl);
int rowCount = reader.GetTableRowCount(TableIndex.MethodImpl);
var methodDefSize = reader.GetReferenceSize(TableIndex.MethodDef);
var typeDefSize = reader.GetReferenceSize(TableIndex.TypeDef);
var containingTypeRow = reader.GetRowNumber(This().GetDeclaringType());
var methodDefRow = reader.GetRowNumber(Handle);
var list = new List<MethodImplementationHandle>();
// TODO : if sorted -> binary search?
for (int row = 0; row < reader.GetTableRowCount(TableIndex.MethodImpl); row++) {
byte* ptr = startPointer + offset + rowSize * row;
uint currentTypeRow = typeDefSize == 2 ? *(ushort*)ptr : *(uint*)ptr;
if (currentTypeRow != containingTypeRow) continue;
uint currentMethodRowCoded = methodDefSize == 2 ? *(ushort*)(ptr + typeDefSize) : *(uint*)(ptr + typeDefSize);
if ((currentMethodRowCoded >> 1) != methodDefRow) continue;
list.Add(MetadataTokens.MethodImplementationHandle(row + 1));
}
return list.ToImmutableArray();
}
public IList<SequencePoint> GetSequencePoints() public IList<SequencePoint> GetSequencePoints()
{ {
@ -483,20 +476,14 @@ namespace ICSharpCode.Decompiler.Dom
{ {
return Module.DebugInfo?.GetVariables(this); return Module.DebugInfo?.GetVariables(this);
} }
public MethodSignature<TType> DecodeSignature<TType, TGenericContext>(ISignatureTypeProvider<TType, TGenericContext> provider, TGenericContext genericContext)
{
return This().DecodeSignature(provider, genericContext);
}
IMemberDefinition IMemberReference.GetDefinition() => this;
} }
public struct PropertyDefinition : IEquatable<PropertyDefinition>, IMemberDefinition, ICustomAttributeProvider public struct PropertyDefinition : IEquatable<PropertyDefinition>, IMetadataEntity
{ {
public PEFile Module { get; } public PEFile Module { get; }
public PropertyDefinitionHandle Handle { get; } public PropertyDefinitionHandle Handle { get; }
public bool IsNil => Handle.IsNil; public bool IsNil => Handle.IsNil;
EntityHandle IMetadataEntity.Handle => Handle;
public PropertyDefinition(PEFile module, PropertyDefinitionHandle handle) : this() public PropertyDefinition(PEFile module, PropertyDefinitionHandle handle) : this()
{ {
@ -504,7 +491,7 @@ namespace ICSharpCode.Decompiler.Dom
this.Handle = handle; this.Handle = handle;
} }
SRMProperty This() => Module.GetMetadataReader().GetPropertyDefinition(Handle); public SRMProperty This() => Module.GetMetadataReader().GetPropertyDefinition(Handle);
public bool Equals(PropertyDefinition other) public bool Equals(PropertyDefinition other)
{ {
@ -525,7 +512,7 @@ namespace ICSharpCode.Decompiler.Dom
public static bool operator ==(PropertyDefinition lhs, PropertyDefinition rhs) => lhs.Equals(rhs); public static bool operator ==(PropertyDefinition lhs, PropertyDefinition rhs) => lhs.Equals(rhs);
public static bool operator !=(PropertyDefinition lhs, PropertyDefinition rhs) => !lhs.Equals(rhs); public static bool operator !=(PropertyDefinition lhs, PropertyDefinition rhs) => !lhs.Equals(rhs);
/*
public string Name { public string Name {
get { get {
var reader = Module.GetMetadataReader(); var reader = Module.GetMetadataReader();
@ -534,7 +521,6 @@ namespace ICSharpCode.Decompiler.Dom
} }
public TypeDefinition DeclaringType => GetAccessors().First().Method.DeclaringType; public TypeDefinition DeclaringType => GetAccessors().First().Method.DeclaringType;
ITypeReference IMemberReference.DeclaringType => DeclaringType;
public MethodDefinition GetMethod => GetAccessors().FirstOrDefault(m => m.Kind == MethodSemanticsAttributes.Getter).Method; public MethodDefinition GetMethod => GetAccessors().FirstOrDefault(m => m.Kind == MethodSemanticsAttributes.Getter).Method;
public MethodDefinition SetMethod => GetAccessors().FirstOrDefault(m => m.Kind == MethodSemanticsAttributes.Setter).Method; public MethodDefinition SetMethod => GetAccessors().FirstOrDefault(m => m.Kind == MethodSemanticsAttributes.Setter).Method;
@ -547,44 +533,17 @@ namespace ICSharpCode.Decompiler.Dom
public bool IsIndexer => HasMatchingDefaultMemberAttribute(out var attr); public bool IsIndexer => HasMatchingDefaultMemberAttribute(out var attr);
public bool HasMatchingDefaultMemberAttribute(out CustomAttributeHandle defaultMemberAttribute) public unsafe ImmutableArray<(MethodSemanticsAttributes Kind, MethodDefinition Method)> GetAccessors()
{ {
var metadata = Module.GetMetadataReader(); return GetAccessors(Module, (uint)(MetadataTokens.GetRowNumber(Handle) << 1) | 1);
defaultMemberAttribute = default(CustomAttributeHandle);
if (HasParameters) {
var accessor = GetAccessors().First(a => a.Kind != MethodSemanticsAttributes.Other).Method;
PropertyDefinition basePropDef = this;
var firstOverrideHandle = accessor.GetMethodImplementations().FirstOrDefault();
if (!firstOverrideHandle.IsNil) {
// if the property is explicitly implementing an interface, look up the property in the interface:
var firstOverride = metadata.GetMethodImplementation(firstOverrideHandle);
var baseAccessor = firstOverride.MethodDeclaration.CoerceMemberReference(Module).GetDefinition() as MethodDefinition?;
if (baseAccessor != null) {
foreach (PropertyDefinition baseProp in baseAccessor?.DeclaringType.Properties) {
if (baseProp.GetMethod == baseAccessor || baseProp.SetMethod == baseAccessor) {
basePropDef = baseProp;
break;
}
}
} else
return false;
}
var defaultMemberName = basePropDef.DeclaringType.Handle.GetDefaultMemberName(metadata, out var attr);
if (defaultMemberName == basePropDef.Name) {
defaultMemberAttribute = attr;
return true;
}
}
return false;
} }
public unsafe ImmutableArray<(MethodSemanticsAttributes Kind, MethodDefinition Method)> GetAccessors() internal static unsafe ImmutableArray<(MethodSemanticsAttributes Kind, MethodDefinition Method)> GetAccessors(PEFile module, uint encodedTag)
{ {
var reader = Module.GetMetadataReader(); var reader = module.GetMetadataReader();
byte* startPointer = reader.MetadataPointer; byte* startPointer = reader.MetadataPointer;
int offset = reader.GetTableMetadataOffset(TableIndex.MethodSemantics); int offset = reader.GetTableMetadataOffset(TableIndex.MethodSemantics);
uint encodedTag = (uint)(MetadataTokens.GetRowNumber(Handle) << 1) | 1;
var methodDefRefSize = reader.GetReferenceSize(TableIndex.MethodDef); var methodDefRefSize = reader.GetReferenceSize(TableIndex.MethodDef);
(int startRow, int endRow) = reader.BinarySearchRange(TableIndex.MethodSemantics, 2 + methodDefRefSize, encodedTag, reader.IsSmallReference(TableIndex.MethodSemantics)); (int startRow, int endRow) = reader.BinarySearchRange(TableIndex.MethodSemantics, 2 + methodDefRefSize, encodedTag, reader.IsSmallReference(TableIndex.MethodSemantics));
if (startRow == -1) if (startRow == -1)
@ -595,8 +554,9 @@ namespace ICSharpCode.Decompiler.Dom
int rowOffset = row * rowSize; int rowOffset = row * rowSize;
byte* ptr = startPointer + offset + rowOffset; byte* ptr = startPointer + offset + rowOffset;
var kind = (MethodSemanticsAttributes)(*(ushort*)ptr); var kind = (MethodSemanticsAttributes)(*(ushort*)ptr);
var handle = MetadataTokens.MethodDefinitionHandle(*(ushort*)(ptr + 2)); uint rowNo = methodDefRefSize == 2 ? *(ushort*)(ptr + 2) : *(uint*)(ptr + 2);
methods[row - startRow] = (kind, new MethodDefinition(Module, handle)); var handle = MetadataTokens.MethodDefinitionHandle((int)rowNo);
methods[row - startRow] = (kind, new MethodDefinition(module, handle));
} }
return methods.ToImmutableArray(); return methods.ToImmutableArray();
} }
@ -605,15 +565,15 @@ namespace ICSharpCode.Decompiler.Dom
{ {
return This().DecodeSignature(provider, genericContext); return This().DecodeSignature(provider, genericContext);
} }
*/
IMemberDefinition IMemberReference.GetDefinition() => this;
} }
public struct FieldDefinition : IEquatable<FieldDefinition>, IMemberDefinition, ICustomAttributeProvider public struct FieldDefinition : IEquatable<FieldDefinition>, IMetadataEntity
{ {
public PEFile Module { get; } public PEFile Module { get; }
public FieldDefinitionHandle Handle { get; } public FieldDefinitionHandle Handle { get; }
public bool IsNil => Handle.IsNil; public bool IsNil => Handle.IsNil;
EntityHandle IMetadataEntity.Handle => Handle;
public FieldDefinition(PEFile module, FieldDefinitionHandle handle) : this() public FieldDefinition(PEFile module, FieldDefinitionHandle handle) : this()
{ {
@ -621,7 +581,7 @@ namespace ICSharpCode.Decompiler.Dom
this.Handle = handle; this.Handle = handle;
} }
SRMField This() => Module.GetMetadataReader().GetFieldDefinition(Handle); public SRMField This() => Module.GetMetadataReader().GetFieldDefinition(Handle);
public bool Equals(FieldDefinition other) public bool Equals(FieldDefinition other)
{ {
@ -643,34 +603,10 @@ namespace ICSharpCode.Decompiler.Dom
public static bool operator ==(FieldDefinition lhs, FieldDefinition rhs) => lhs.Equals(rhs); public static bool operator ==(FieldDefinition lhs, FieldDefinition rhs) => lhs.Equals(rhs);
public static bool operator !=(FieldDefinition lhs, FieldDefinition rhs) => !lhs.Equals(rhs); public static bool operator !=(FieldDefinition lhs, FieldDefinition rhs) => !lhs.Equals(rhs);
public string Name {
get {
var reader = Module.GetMetadataReader();
return reader.GetString(reader.GetFieldDefinition(Handle).Name);
}
}
public TypeDefinition DeclaringType => new TypeDefinition(Module, This().GetDeclaringType());
ITypeReference IMemberReference.DeclaringType => DeclaringType;
public FieldAttributes Attributes => This().Attributes;
public bool HasFlag(FieldAttributes attribute) => (This().Attributes & attribute) == attribute;
public CustomAttributeHandleCollection CustomAttributes => This().GetCustomAttributes();
public int RVA => This().GetRelativeVirtualAddress();
public int Offset => This().GetOffset();
public BlobHandle GetMarshallingDescriptor() => This().GetMarshallingDescriptor();
public ConstantHandle GetDefaultValue() => This().GetDefaultValue();
public TType DecodeSignature<TType, TGenericContext>(ISignatureTypeProvider<TType, TGenericContext> provider, TGenericContext genericContext)
{
return This().DecodeSignature(provider, genericContext);
}
public object DecodeConstant() public object DecodeConstant()
{ {
var metadata = Module.GetMetadataReader(); var metadata = Module.GetMetadataReader();
var constant = metadata.GetConstant(GetDefaultValue()); var constant = metadata.GetConstant(This().GetDefaultValue());
var blob = metadata.GetBlobReader(constant.Value); var blob = metadata.GetBlobReader(constant.Value);
switch (constant.TypeCode) { switch (constant.TypeCode) {
case ConstantTypeCode.Boolean: case ConstantTypeCode.Boolean:
@ -705,15 +641,14 @@ namespace ICSharpCode.Decompiler.Dom
throw new NotSupportedException(); throw new NotSupportedException();
} }
} }
IMemberDefinition IMemberReference.GetDefinition() => this;
} }
public struct EventDefinition : IEquatable<EventDefinition>, IMemberDefinition, ICustomAttributeProvider public struct EventDefinition : IEquatable<EventDefinition>, IMetadataEntity
{ {
public PEFile Module { get; } public PEFile Module { get; }
public EventDefinitionHandle Handle { get; } public EventDefinitionHandle Handle { get; }
public bool IsNil => Handle.IsNil; public bool IsNil => Handle.IsNil;
EntityHandle IMetadataEntity.Handle => Handle;
public EventDefinition(PEFile module, EventDefinitionHandle handle) public EventDefinition(PEFile module, EventDefinitionHandle handle)
{ {
@ -721,7 +656,7 @@ namespace ICSharpCode.Decompiler.Dom
this.Handle = handle; this.Handle = handle;
} }
SRMEvent This() => Module.GetMetadataReader().GetEventDefinition(Handle); public SRMEvent This() => Module.GetMetadataReader().GetEventDefinition(Handle);
public bool Equals(EventDefinition other) public bool Equals(EventDefinition other)
{ {
@ -742,7 +677,7 @@ namespace ICSharpCode.Decompiler.Dom
public static bool operator ==(EventDefinition lhs, EventDefinition rhs) => lhs.Equals(rhs); public static bool operator ==(EventDefinition lhs, EventDefinition rhs) => lhs.Equals(rhs);
public static bool operator !=(EventDefinition lhs, EventDefinition rhs) => !lhs.Equals(rhs); public static bool operator !=(EventDefinition lhs, EventDefinition rhs) => !lhs.Equals(rhs);
/*
public string Name { public string Name {
get { get {
var reader = Module.GetMetadataReader(); var reader = Module.GetMetadataReader();
@ -751,7 +686,6 @@ namespace ICSharpCode.Decompiler.Dom
} }
public TypeDefinition DeclaringType => GetAccessors().First().Method.DeclaringType; public TypeDefinition DeclaringType => GetAccessors().First().Method.DeclaringType;
ITypeReference IMemberReference.DeclaringType => DeclaringType;
public EventAttributes Attributes => This().Attributes; public EventAttributes Attributes => This().Attributes;
public bool HasFlag(EventAttributes attribute) => (This().Attributes & attribute) == attribute; public bool HasFlag(EventAttributes attribute) => (This().Attributes & attribute) == attribute;
@ -764,59 +698,25 @@ namespace ICSharpCode.Decompiler.Dom
public unsafe ImmutableArray<(MethodSemanticsAttributes Kind, MethodDefinition Method)> GetAccessors() public unsafe ImmutableArray<(MethodSemanticsAttributes Kind, MethodDefinition Method)> GetAccessors()
{ {
var reader = Module.GetMetadataReader(); return PropertyDefinition.GetAccessors(Module, (uint)(MetadataTokens.GetRowNumber(Handle) << 1) | 0);
byte* startPointer = reader.MetadataPointer; }*/
int offset = reader.GetTableMetadataOffset(TableIndex.MethodSemantics);
uint encodedTag = (uint)(MetadataTokens.GetRowNumber(Handle) << 1) | 0;
var methodDefRefSize = reader.GetReferenceSize(TableIndex.MethodDef);
(int startRow, int endRow) = reader.BinarySearchRange(TableIndex.MethodSemantics, 2 + methodDefRefSize, encodedTag, reader.IsSmallReference(TableIndex.MethodSemantics));
if (startRow == -1)
return ImmutableArray<(MethodSemanticsAttributes Kind, MethodDefinition Method)>.Empty;
var methods = new(MethodSemanticsAttributes Kind, MethodDefinition Method)[endRow - startRow + 1];
int rowSize = reader.GetTableRowSize(TableIndex.MethodSemantics);
for (int row = startRow; row <= endRow; row++) {
int rowOffset = row * rowSize;
byte* ptr = startPointer + offset + rowOffset;
var kind = (MethodSemanticsAttributes)(*(ushort*)ptr);
var handle = MetadataTokens.MethodDefinitionHandle(*(ushort*)(ptr + 2));
methods[row - startRow] = (kind, new MethodDefinition(Module, handle));
}
return methods.ToImmutableArray();
}
public TType DecodeSignature<TType, TGenericContext>(ISignatureTypeProvider<TType, TGenericContext> provider, TGenericContext genericContext)
{
var type = This().Type;
var reader = Module.GetMetadataReader();
switch (type.Kind) {
case HandleKind.TypeDefinition:
return provider.GetTypeFromDefinition(reader, (TypeDefinitionHandle)type, 0);
case HandleKind.TypeReference:
return provider.GetTypeFromReference(reader, (TypeReferenceHandle)type, 0);
case HandleKind.TypeSpecification:
return provider.GetTypeFromSpecification(reader, genericContext, (TypeSpecificationHandle)type, 0);
default:
throw new NotSupportedException();
}
}
IMemberDefinition IMemberReference.GetDefinition() => this;
} }
public struct TypeDefinition : IEquatable<TypeDefinition>, ITypeDefinition, ICustomAttributeProvider public struct TypeDefinition : IEquatable<TypeDefinition>, IMetadataEntity
{ {
public PEFile Module { get; } public PEFile Module { get; }
public TypeDefinitionHandle Handle { get; } public TypeDefinitionHandle Handle { get; }
public bool IsNil => Handle.IsNil; public bool IsNil => Handle.IsNil;
EntityHandle IMetadataEntity.Handle => Handle;
public TypeDefinition(PEFile module, TypeDefinitionHandle handle) public TypeDefinition(PEFile module, TypeDefinitionHandle handle)
{ {
this.Module = module ?? throw new ArgumentNullException(nameof(module)); this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle; this.Handle = handle;
} }
internal SRMTypeDef This() => Module.GetMetadataReader().GetTypeDefinition(Handle); public SRMTypeDef This() => Module.GetMetadataReader().GetTypeDefinition(Handle);
public bool Equals(TypeDefinition other) public bool Equals(TypeDefinition other)
{ {
@ -837,106 +737,9 @@ namespace ICSharpCode.Decompiler.Dom
public static bool operator ==(TypeDefinition lhs, TypeDefinition rhs) => lhs.Equals(rhs); public static bool operator ==(TypeDefinition lhs, TypeDefinition rhs) => lhs.Equals(rhs);
public static bool operator !=(TypeDefinition lhs, TypeDefinition rhs) => !lhs.Equals(rhs); public static bool operator !=(TypeDefinition lhs, TypeDefinition rhs) => !lhs.Equals(rhs);
public string Name => Module.GetMetadataReader().GetString(This().Name);
public string Namespace => Module.GetMetadataReader().GetString(This().Namespace);
public FullTypeName FullName => This().GetFullTypeName(Module.GetMetadataReader());
public TypeAttributes Attributes => This().Attributes;
public bool HasFlag(TypeAttributes attribute) => (This().Attributes & attribute) == attribute;
public TypeDefinition DeclaringType => new TypeDefinition(Module, This().GetDeclaringType());
ITypeReference IMemberReference.DeclaringType => DeclaringType;
public GenericParameterHandleCollection GenericParameters => This().GetGenericParameters();
public CustomAttributeHandleCollection CustomAttributes => This().GetCustomAttributes();
public DeclarativeSecurityAttributeHandleCollection DeclarativeSecurityAttributes => This().GetDeclarativeSecurityAttributes();
public TypeLayout GetLayout() => This().GetLayout();
public ITypeReference BaseType {
get {
var baseType = This().BaseType;
return CreateTypeReference(baseType);
}
}
ITypeReference CreateTypeReference(EntityHandle baseType)
{
if (baseType.IsNil)
return null;
switch (baseType.Kind) {
case HandleKind.TypeDefinition:
return new TypeDefinition(Module, (TypeDefinitionHandle)baseType);
case HandleKind.TypeReference:
return new TypeReference(Module, (TypeReferenceHandle)baseType);
case HandleKind.TypeSpecification:
return new TypeSpecification(Module, (TypeSpecificationHandle)baseType);
default:
throw new NotSupportedException();
}
}
public bool HasInterfaces => This().GetInterfaceImplementations().Count > 0;
public ImmutableArray<ITypeReference> Interfaces => GetInterfaces().ToImmutableArray();
IEnumerable<ITypeReference> GetInterfaces()
{
var reader = Module.GetMetadataReader();
foreach (var h in This().GetInterfaceImplementations()) {
var interfaceImpl = reader.GetInterfaceImplementation(h);
yield return CreateTypeReference(interfaceImpl.Interface);
}
}
public bool IsValueType => This().IsValueType(Module.GetMetadataReader());
public bool IsEnum => This().IsEnum(Module.GetMetadataReader());
public bool IsInterface => (This().Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface;
public bool IsClass => (This().Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Class;
public bool IsNotPublic => (This().Attributes & TypeAttributes.VisibilityMask) == 0;
public bool IsDelegate {
get {
var baseType = This().BaseType;
return !baseType.IsNil && baseType.GetFullTypeName(Module.GetMetadataReader()).ToString() == typeof(MulticastDelegate).FullName;
}
}
public ImmutableArray<TypeDefinition> NestedTypes {
get {
var module = Module;
return This().GetNestedTypes().Select(nt => new TypeDefinition(module, nt)).ToImmutableArray();
}
}
public ImmutableArray<FieldDefinition> Fields {
get {
var module = Module;
return This().GetFields().Select(f => new FieldDefinition(module, f)).ToImmutableArray();
}
}
public ImmutableArray<PropertyDefinition> Properties {
get {
var module = Module;
return This().GetProperties().Select(p => new PropertyDefinition(module, p)).ToImmutableArray();
}
}
public ImmutableArray<EventDefinition> Events {
get {
var module = Module;
return This().GetEvents().Select(e => new EventDefinition(module, e)).ToImmutableArray();
}
}
public ImmutableArray<MethodDefinition> Methods {
get {
var module = Module;
return This().GetMethods().Select(m => new MethodDefinition(module, m)).ToImmutableArray();
}
}
TypeDefinition ITypeReference.GetDefinition() => this;
public InterfaceImplementationHandleCollection GetInterfaceImplementations() => This().GetInterfaceImplementations();
IMemberDefinition IMemberReference.GetDefinition() => this;
} }
public struct TypeReference : ITypeReference public struct TypeReference
{ {
public PEFile Module { get; } public PEFile Module { get; }
public TypeReferenceHandle Handle { get; } public TypeReferenceHandle Handle { get; }
@ -971,12 +774,9 @@ namespace ICSharpCode.Decompiler.Dom
{ {
return MetadataResolver.Resolve(Handle, new SimpleMetadataResolveContext(Module)); return MetadataResolver.Resolve(Handle, new SimpleMetadataResolveContext(Module));
} }
IMemberDefinition IMemberReference.GetDefinition() => GetDefinition();
ITypeReference IMemberReference.DeclaringType => new TypeReference(Module, This().GetDeclaringType());
} }
public struct TypeSpecification : ITypeReference public struct TypeSpecification
{ {
public PEFile Module { get; } public PEFile Module { get; }
public TypeSpecificationHandle Handle { get; } public TypeSpecificationHandle Handle { get; }
@ -1000,56 +800,31 @@ namespace ICSharpCode.Decompiler.Dom
public string Namespace => FullName.TopLevelTypeName.Namespace; public string Namespace => FullName.TopLevelTypeName.Namespace;
public ITypeReference DeclaringType => GetDefinition().DeclaringType;
public TypeDefinition GetDefinition() public TypeDefinition GetDefinition()
{ {
return MetadataResolver.Resolve(Handle, new SimpleMetadataResolveContext(Module)); return MetadataResolver.Resolve(Handle, new SimpleMetadataResolveContext(Module));
} }
IMemberDefinition IMemberReference.GetDefinition()
{
return GetDefinition();
}
public TType DecodeSignature<TType, TGenericContext>(ISignatureTypeProvider<TType, TGenericContext> provider, TGenericContext genericContext) public TType DecodeSignature<TType, TGenericContext>(ISignatureTypeProvider<TType, TGenericContext> provider, TGenericContext genericContext)
{ {
return This().DecodeSignature(provider, genericContext); return This().DecodeSignature(provider, genericContext);
} }
} }
public struct MethodSpecification : IMethodReference public struct MethodSpecification
{ {
public PEFile Module { get; } public PEFile Module { get; }
public MethodSpecificationHandle Handle { get; } public MethodSpecificationHandle Handle { get; }
public bool IsNil => Handle.IsNil; public bool IsNil => Handle.IsNil;
public string Name => This().Method.CoerceMemberReference(Module).Name;
public MethodSpecification(PEFile module, MethodSpecificationHandle handle) public MethodSpecification(PEFile module, MethodSpecificationHandle handle)
{ {
this.Module = module ?? throw new ArgumentNullException(nameof(module)); this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle; this.Handle = handle;
} }
SRMMethodSpec This() => Module.GetMetadataReader().GetMethodSpecification(Handle);
public ImmutableArray<TType> DecodeSignature<TType, TGenericContext>(ISignatureTypeProvider<TType, TGenericContext> provider, TGenericContext genericContext)
{
return This().DecodeSignature(provider, genericContext);
}
public IMemberDefinition GetDefinition()
{
return Method.GetDefinition();
}
public ITypeReference DeclaringType => Method.DeclaringType;
public IMemberReference Method => This().Method.CoerceMemberReference(Module);
} }
public struct MemberReference : IMemberReference public struct MemberReference
{ {
public PEFile Module { get; } public PEFile Module { get; }
public MemberReferenceHandle Handle { get; } public MemberReferenceHandle Handle { get; }
@ -1062,42 +837,9 @@ namespace ICSharpCode.Decompiler.Dom
this.Module = module ?? throw new ArgumentNullException(nameof(module)); this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle; this.Handle = handle;
} }
public string Name {
get {
var reader = Module.GetMetadataReader();
return reader.GetString(reader.GetMemberReference(Handle).Name);
}
}
public MemberReferenceKind Kind => This().GetKind();
/// <summary>
/// MethodDef, ModuleRef,TypeDef, TypeRef, or TypeSpec handle.
/// </summary>
public EntityHandle Parent => This().Parent;
public MethodSignature<TType> DecodeMethodSignature<TType, TGenericContext>(ISignatureTypeProvider<TType, TGenericContext> provider, TGenericContext genericContext)
{
return This().DecodeMethodSignature(provider, genericContext);
}
public TType DecodeFieldSignature<TType, TGenericContext>(ISignatureTypeProvider<TType, TGenericContext> provider, TGenericContext genericContext)
{
return This().DecodeFieldSignature(provider, genericContext);
}
public IMemberDefinition GetDefinition()
{
return MetadataResolver.Resolve(Handle, new SimpleMetadataResolveContext(Module));
}
public TypeDefinition DeclaringType => GetDefinition().DeclaringType;
ITypeReference IMemberReference.DeclaringType => DeclaringType;
} }
class FullTypeNameSignatureDecoder : ISignatureTypeProvider<FullTypeName, Unit> public sealed class FullTypeNameSignatureDecoder : ISignatureTypeProvider<FullTypeName, Unit>
{ {
readonly MetadataReader metadata; readonly MetadataReader metadata;
@ -1179,53 +921,70 @@ namespace ICSharpCode.Decompiler.Dom
public class GenericContext public class GenericContext
{ {
readonly MethodDefinition method; readonly PEFile module;
readonly TypeDefinition declaringType;
readonly MetadataReader metadata; readonly MetadataReader metadata;
readonly TypeDefinitionHandle declaringType;
readonly MethodDefinitionHandle method;
public static readonly GenericContext Empty = new GenericContext(); public static readonly GenericContext Empty = new GenericContext();
private GenericContext() { } private GenericContext() { }
public GenericContext(MethodDefinition method) public GenericContext(MethodDefinitionHandle method, PEFile module)
{ {
this.module = module;
this.metadata = module.GetMetadataReader();
this.method = method; this.method = method;
this.declaringType = method.DeclaringType; this.declaringType = metadata.GetMethodDefinition(method).GetDeclaringType();
this.metadata = method.Module.GetMetadataReader();
} }
public GenericContext(TypeDefinition declaringType) public GenericContext(MethodDefinition method)
: this(method.Handle, method.Module)
{
}
public GenericContext(TypeDefinitionHandle declaringType, PEFile module)
{ {
this.module = module;
this.metadata = module.GetMetadataReader();
this.declaringType = declaringType; this.declaringType = declaringType;
this.metadata = declaringType.Module.GetMetadataReader(); }
public GenericContext(TypeDefinition declaringType)
: this(declaringType.Handle, declaringType.Module)
{
} }
public string GetGenericTypeParameterName(int index) public string GetGenericTypeParameterName(int index)
{ {
if (declaringType.IsNil || index < 0 || index >= declaringType.GenericParameters.Count) GenericParameterHandle genericParameter = GetGenericTypeParameterHandleOrNull(index);
if (genericParameter.IsNil)
return index.ToString(); return index.ToString();
return metadata.GetString(metadata.GetGenericParameter(declaringType.GenericParameters[index]).Name); return metadata.GetString(metadata.GetGenericParameter(genericParameter).Name);
} }
public string GetGenericMethodTypeParameterName(int index) public string GetGenericMethodTypeParameterName(int index)
{ {
if (method.IsNil || index < 0 || index >= method.GenericParameters.Count) GenericParameterHandle genericParameter = GetGenericMethodTypeParameterHandleOrNull(index);
if (genericParameter.IsNil)
return index.ToString(); return index.ToString();
return metadata.GetString(metadata.GetGenericParameter(method.GenericParameters[index]).Name); return metadata.GetString(metadata.GetGenericParameter(genericParameter).Name);
} }
public GenericParameterHandle GetGenericTypeParameterHandleOrNull(int index) public GenericParameterHandle GetGenericTypeParameterHandleOrNull(int index)
{ {
if (declaringType.IsNil || index < 0 || index >= declaringType.GenericParameters.Count) GenericParameterHandleCollection genericParameters;
if (declaringType.IsNil || index < 0 || index >= (genericParameters = metadata.GetTypeDefinition(declaringType).GetGenericParameters()).Count)
return MetadataTokens.GenericParameterHandle(0); return MetadataTokens.GenericParameterHandle(0);
return declaringType.GenericParameters[index]; return genericParameters[index];
} }
public GenericParameterHandle GetGenericMethodTypeParameterHandleOrNull(int index) public GenericParameterHandle GetGenericMethodTypeParameterHandleOrNull(int index)
{ {
if (method.IsNil || index < 0 || index >= method.GenericParameters.Count) GenericParameterHandleCollection genericParameters;
if (method.IsNil || index < 0 || index >= (genericParameters = metadata.GetMethodDefinition(method).GetGenericParameters()).Count)
return MetadataTokens.GenericParameterHandle(0); return MetadataTokens.GenericParameterHandle(0);
return method.GenericParameters[index]; return genericParameters[index];
} }
} }
} }

3
ICSharpCode.Decompiler/DotNetCore/DotNetCorePathFinder.cs → ICSharpCode.Decompiler/Metadata/DotNetCorePathFinder.cs

@ -5,10 +5,9 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
using ICSharpCode.Decompiler.Dom;
using LightJson.Serialization; using LightJson.Serialization;
namespace ICSharpCode.Decompiler namespace ICSharpCode.Decompiler.Metadata
{ {
public class DotNetCorePathFinder public class DotNetCorePathFinder
{ {

2
ICSharpCode.Decompiler/DotNetCore/DotNetCorePathFinderExtensions.cs → ICSharpCode.Decompiler/Metadata/DotNetCorePathFinderExtensions.cs

@ -4,7 +4,7 @@ using System.Linq;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Reflection.PortableExecutable; using System.Reflection.PortableExecutable;
namespace ICSharpCode.Decompiler namespace ICSharpCode.Decompiler.Metadata
{ {
public static class DotNetCorePathFinderExtensions public static class DotNetCorePathFinderExtensions
{ {

108
ICSharpCode.Decompiler/IL/ILOpCodes.cs → ICSharpCode.Decompiler/Metadata/ILOpCodes.cs

File diff suppressed because one or more lines are too long

64
ICSharpCode.Decompiler/Metadata/ILOpCodes.tt

@ -0,0 +1,64 @@
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Reflection.Metadata" #>
<#@ import namespace="System.Reflection.Emit" #>
<#@ output extension=".cs" #>
using System;
using System.Collections.Generic;
using System.Reflection.Metadata;
<#
var operandTypes = Enumerable.Repeat((OperandType)0xff, 0x11f).ToArray();
var operandNames = new string[0x11f];
#>
namespace ICSharpCode.Decompiler.Metadata
{
<#
foreach (var field in typeof(OpCodes).GetFields()) {
var opCode = (OpCode)field.GetValue(null);
ushort index = (ushort)(((opCode.Value & 0x200) >> 1) | (opCode.Value & 0xff));
operandTypes[index] = opCode.OperandType;
operandNames[index] = opCode.Name;
} #>
static partial class ILOpCodeExtensions
{
// We use a byte array instead of an enum array because it can be initialized more efficiently
static readonly byte[] operandTypes = { <#
foreach (var operandType in operandTypes) {
if ((byte)operandType == 255) {
Write("255, ");
} else {
string operandTypeName = operandType.ToString().Replace("Inline", "").Replace("Var", "Variable");
Write("(byte)OperandType." + operandTypeName + ", ");
}
}
#> };
static readonly string[] operandNames = { <#
foreach (var operandName in operandNames) {
Write("\"" + operandName + "\", ");
}
#> };
}
}

0
ICSharpCode.Decompiler/DotNetCore/LightJson/JsonArray.cs → ICSharpCode.Decompiler/Metadata/LightJson/JsonArray.cs

0
ICSharpCode.Decompiler/DotNetCore/LightJson/JsonObject.cs → ICSharpCode.Decompiler/Metadata/LightJson/JsonObject.cs

0
ICSharpCode.Decompiler/DotNetCore/LightJson/JsonValue.cs → ICSharpCode.Decompiler/Metadata/LightJson/JsonValue.cs

0
ICSharpCode.Decompiler/DotNetCore/LightJson/JsonValueType.cs → ICSharpCode.Decompiler/Metadata/LightJson/JsonValueType.cs

0
ICSharpCode.Decompiler/DotNetCore/LightJson/Serialization/JsonParseException.cs → ICSharpCode.Decompiler/Metadata/LightJson/Serialization/JsonParseException.cs

0
ICSharpCode.Decompiler/DotNetCore/LightJson/Serialization/JsonReader.cs → ICSharpCode.Decompiler/Metadata/LightJson/Serialization/JsonReader.cs

0
ICSharpCode.Decompiler/DotNetCore/LightJson/Serialization/JsonSerializationException.cs → ICSharpCode.Decompiler/Metadata/LightJson/Serialization/JsonSerializationException.cs

0
ICSharpCode.Decompiler/DotNetCore/LightJson/Serialization/JsonWriter.cs → ICSharpCode.Decompiler/Metadata/LightJson/Serialization/JsonWriter.cs

0
ICSharpCode.Decompiler/DotNetCore/LightJson/Serialization/TextPosition.cs → ICSharpCode.Decompiler/Metadata/LightJson/Serialization/TextPosition.cs

0
ICSharpCode.Decompiler/DotNetCore/LightJson/Serialization/TextScanner.cs → ICSharpCode.Decompiler/Metadata/LightJson/Serialization/TextScanner.cs

193
ICSharpCode.Decompiler/Dom/MetadataExtensions.cs → ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using SRM = System.Reflection.Metadata;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable; using System.Reflection.PortableExecutable;
@ -13,43 +14,20 @@ using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler namespace ICSharpCode.Decompiler.Metadata
{ {
public static class MetadataExtensions public static class MetadataExtensions
{ {
public static Dom.ITypeReference CoerceTypeReference(this EntityHandle handle, Dom.PEFile module) #region Resolver
public static TypeDefinition ResolveAsType(this EntityHandle entity, PEFile module)
{ {
if (handle.IsNil) return new Entity(module, entity).ResolveAsType();
return null;
switch (handle.Kind) {
case HandleKind.TypeDefinition:
return new Dom.TypeDefinition(module, (TypeDefinitionHandle)handle);
case HandleKind.TypeReference:
return new Dom.TypeReference(module, (TypeReferenceHandle)handle);
case HandleKind.TypeSpecification:
return new Dom.TypeSpecification(module, (TypeSpecificationHandle)handle);
default:
throw new ArgumentException("must be either TypeDef, TypeRef or TypeSpec!", nameof(handle));
}
}
public static Dom.IMemberReference CoerceMemberReference(this EntityHandle handle, Dom.PEFile module)
{
if (handle.IsNil)
return null;
switch (handle.Kind) {
case HandleKind.MemberReference:
return new Dom.MemberReference(module, (MemberReferenceHandle)handle);
case HandleKind.MethodDefinition:
return new Dom.MethodDefinition(module, (MethodDefinitionHandle)handle);
default:
throw new ArgumentException("must be either MethodDef or MemberRef!", nameof(handle));
}
} }
#endregion
public static bool IsNil(this Dom.IAssemblyReference reference) public static bool IsNil(this IAssemblyReference reference)
{ {
return reference == null || (reference is Dom.AssemblyReference ar && ar.IsNil); return reference == null || (reference is Metadata.AssemblyReference ar && ar.IsNil);
} }
public static string GetFullAssemblyName(this MetadataReader reader) public static string GetFullAssemblyName(this MetadataReader reader)
@ -63,10 +41,10 @@ namespace ICSharpCode.Decompiler
var publicKeyTokenBytes = sha1.ComputeHash(reader.GetBlobBytes(asm.PublicKey)).Skip(12).ToArray(); var publicKeyTokenBytes = sha1.ComputeHash(reader.GetBlobBytes(asm.PublicKey)).Skip(12).ToArray();
publicKey = publicKeyTokenBytes.ToHexString(); publicKey = publicKeyTokenBytes.ToHexString();
} }
return $"{reader.GetString(asm.Name)}, Version={asm.Version}, Culture={reader.GetString(asm.Culture)}, PublicKeyToken={publicKey}"; return $"{reader.GetString(asm.Name)}, Version={asm.Version}, Culture={(asm.Culture.IsNil ? "neutral" : reader.GetString(asm.Culture))}, PublicKeyToken={publicKey}";
} }
public static string GetFullAssemblyName(this AssemblyReference reference, MetadataReader reader) public static string GetFullAssemblyName(this SRM.AssemblyReference reference, MetadataReader reader)
{ {
string publicKey = "null"; string publicKey = "null";
if (!reference.PublicKeyOrToken.IsNil && (reference.Flags & AssemblyFlags.PublicKey) != 0) { if (!reference.PublicKeyOrToken.IsNil && (reference.Flags & AssemblyFlags.PublicKey) != 0) {
@ -88,41 +66,6 @@ namespace ICSharpCode.Decompiler
return sb.ToString(); return sb.ToString();
} }
/// <summary>
/// Gets the type of the attribute.
/// </summary>
public static Dom.ITypeReference GetAttributeType(this CustomAttribute attribute, Dom.PEFile module)
{
var reader = module.GetMetadataReader();
switch (attribute.Constructor.Kind) {
case HandleKind.MethodDefinition:
var md = reader.GetMethodDefinition((MethodDefinitionHandle)attribute.Constructor);
return new Dom.TypeDefinition(module, md.GetDeclaringType());
case HandleKind.MemberReference:
var mr = reader.GetMemberReference((MemberReferenceHandle)attribute.Constructor);
return mr.Parent.CoerceTypeReference(module);
default:
throw new NotSupportedException();
}
}
/// <summary>
/// Gets the type of the attribute.
/// </summary>
public static EntityHandle GetAttributeType(this CustomAttribute attribute, MetadataReader reader)
{
switch (attribute.Constructor.Kind) {
case HandleKind.MethodDefinition:
var md = reader.GetMethodDefinition((MethodDefinitionHandle)attribute.Constructor);
return md.GetDeclaringType();
case HandleKind.MemberReference:
var mr = reader.GetMemberReference((MemberReferenceHandle)attribute.Constructor);
return mr.Parent;
default:
throw new NotSupportedException();
}
}
public static IEnumerable<TypeDefinitionHandle> GetTopLevelTypeDefinitions(this MetadataReader reader) public static IEnumerable<TypeDefinitionHandle> GetTopLevelTypeDefinitions(this MetadataReader reader)
{ {
var queue = new Queue<NamespaceDefinition>(); var queue = new Queue<NamespaceDefinition>();
@ -136,62 +79,6 @@ namespace ICSharpCode.Decompiler
} }
} }
public static FullTypeName GetFullTypeName(this EntityHandle handle, MetadataReader reader)
{
if (handle.IsNil)
throw new ArgumentNullException(nameof(handle));
switch (handle.Kind) {
case HandleKind.TypeDefinition:
return ((TypeDefinitionHandle)handle).GetFullTypeName(reader);
case HandleKind.TypeReference:
return ((TypeReferenceHandle)handle).GetFullTypeName(reader);
case HandleKind.TypeSpecification:
return ((TypeSpecificationHandle)handle).GetFullTypeName(reader);
default:
throw new NotSupportedException();
}
}
public static FullTypeName GetFullTypeName(this TypeSpecificationHandle handle, MetadataReader reader, bool omitGenericParamCount = false)
{
if (handle.IsNil)
throw new ArgumentNullException(nameof(handle));
var ts = reader.GetTypeSpecification(handle);
return ts.DecodeSignature(new Dom.FullTypeNameSignatureDecoder(reader), default(Unit));
}
public static FullTypeName GetFullTypeName(this TypeReferenceHandle handle, MetadataReader reader, bool omitGenericParamCount = false)
{
if (handle.IsNil)
throw new ArgumentNullException(nameof(handle));
var tr = reader.GetTypeReference(handle);
TypeReferenceHandle declaringTypeHandle;
if ((declaringTypeHandle = tr.GetDeclaringType()).IsNil) {
string @namespace = tr.Namespace.IsNil ? "" : reader.GetString(tr.Namespace);
return new FullTypeName(new TopLevelTypeName(@namespace, reader.GetString(tr.Name)));
} else {
return declaringTypeHandle.GetFullTypeName(reader, omitGenericParamCount).NestedType(reader.GetString(tr.Name), 0);
}
}
public static FullTypeName GetFullTypeName(this TypeDefinitionHandle handle, MetadataReader reader)
{
if (handle.IsNil)
throw new ArgumentNullException(nameof(handle));
return reader.GetTypeDefinition(handle).GetFullTypeName(reader);
}
public static FullTypeName GetFullTypeName(this TypeDefinition td, MetadataReader reader)
{
TypeDefinitionHandle declaringTypeHandle;
if ((declaringTypeHandle = td.GetDeclaringType()).IsNil) {
string @namespace = td.Namespace.IsNil ? "" : reader.GetString(td.Namespace);
return new FullTypeName(new TopLevelTypeName(@namespace, reader.GetString(td.Name)));
} else {
return declaringTypeHandle.GetFullTypeName(reader).NestedType(reader.GetString(td.Name), 0);
}
}
public static string ToILNameString(this FullTypeName typeName) public static string ToILNameString(this FullTypeName typeName)
{ {
var escapedName = Disassembler.DisassemblerHelpers.Escape(typeName.Name); var escapedName = Disassembler.DisassemblerHelpers.Escape(typeName.Name);
@ -204,16 +91,6 @@ namespace ICSharpCode.Decompiler
} }
} }
public static TypeReferenceHandle GetDeclaringType(this TypeReference tr)
{
switch (tr.ResolutionScope.Kind) {
case HandleKind.TypeReference:
return (TypeReferenceHandle)tr.ResolutionScope;
default:
return default(TypeReferenceHandle);
}
}
public static AssemblyReferenceHandle GetDeclaringAssembly(this TypeReferenceHandle handle, MetadataReader reader) public static AssemblyReferenceHandle GetDeclaringAssembly(this TypeReferenceHandle handle, MetadataReader reader)
{ {
var tr = reader.GetTypeReference(handle); var tr = reader.GetTypeReference(handle);
@ -227,29 +104,47 @@ namespace ICSharpCode.Decompiler
} }
} }
public static bool IsValueType(this TypeDefinition typeDefinition, MetadataReader reader) public static bool IsConstructor(this SRM.MethodDefinition methodDefinition, MetadataReader reader)
{
if (typeDefinition.BaseType.IsNil)
return false;
var baseType = typeDefinition.BaseType.GetFullTypeName(reader).ToString();
if (baseType == "System.Enum")
return true;
var thisType = typeDefinition.GetFullTypeName(reader).ToString();
return baseType == "System.ValueType" && thisType != "System.Enum";
}
public static bool IsConstructor(this MethodDefinition methodDefinition, MetadataReader reader)
{ {
string name = reader.GetString(methodDefinition.Name); string name = reader.GetString(methodDefinition.Name);
return (methodDefinition.Attributes & (MethodAttributes.RTSpecialName | MethodAttributes.SpecialName)) != 0 return (methodDefinition.Attributes & (MethodAttributes.RTSpecialName | MethodAttributes.SpecialName)) != 0
&& (name == ".cctor" || name == ".ctor"); && (name == ".cctor" || name == ".ctor");
} }
public static bool IsEnum(this TypeDefinition typeDefinition, MetadataReader reader) public static bool HasMatchingDefaultMemberAttribute(this PropertyDefinitionHandle handle, PEFile module, out CustomAttributeHandle defaultMemberAttribute)
{ {
if (typeDefinition.BaseType.IsNil) defaultMemberAttribute = default(CustomAttributeHandle);
return false; var metadata = module.GetMetadataReader();
return typeDefinition.BaseType.GetFullTypeName(reader).ToString() == "System.Enum"; var propertyDefinition = metadata.GetPropertyDefinition(handle);
var accessorHandle = propertyDefinition.GetAccessors().GetAny();
var accessor = metadata.GetMethodDefinition(accessorHandle);
if (accessor.GetParameters().Count > 0) {
var basePropDef = propertyDefinition;
var firstOverrideHandle = accessorHandle.GetMethodImplementations(metadata).FirstOrDefault();
if (!firstOverrideHandle.IsNil) {
// if the property is explicitly implementing an interface, look up the property in the interface:
var firstOverride = metadata.GetMethodImplementation(firstOverrideHandle);
var baseAccessor = new Metadata.Entity(module, firstOverride.MethodDeclaration).ResolveAsMethod();
if (!baseAccessor.IsNil) {
var declaringType = metadata.GetTypeDefinition(metadata.GetMethodDefinition(baseAccessor.Handle).GetDeclaringType());
foreach (var basePropHandle in declaringType.GetProperties()) {
var baseProp = metadata.GetPropertyDefinition(basePropHandle);
var accessors = baseProp.GetAccessors();
if (accessors.Getter == baseAccessor.Handle || accessors.Setter == baseAccessor.Handle) {
basePropDef = baseProp;
break;
}
}
} else
return false;
}
var defaultMemberName = accessor.GetDeclaringType().GetDefaultMemberName(metadata, out var attr);
if (defaultMemberName == metadata.GetString(basePropDef.Name)) {
defaultMemberAttribute = attr;
return true;
}
}
return false;
} }
public static string GetDefaultMemberName(this TypeDefinitionHandle type, MetadataReader reader) public static string GetDefaultMemberName(this TypeDefinitionHandle type, MetadataReader reader)

40
ICSharpCode.Decompiler/Dom/MetadataResolver.cs → ICSharpCode.Decompiler/Metadata/MetadataResolver.cs

@ -9,7 +9,7 @@ using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.Dom namespace ICSharpCode.Decompiler.Metadata
{ {
public interface IMetadataResolveContext public interface IMetadataResolveContext
{ {
@ -43,10 +43,33 @@ namespace ICSharpCode.Decompiler.Dom
public static class MetadataResolver public static class MetadataResolver
{ {
public static TypeDefinition ResolveType(EntityHandle handle, IMetadataResolveContext context)
{
switch (handle.Kind) {
case HandleKind.TypeDefinition:
return new TypeDefinition(context.CurrentModule, (TypeDefinitionHandle)handle);
case HandleKind.TypeReference:
return Resolve((TypeReferenceHandle)handle, context);
case HandleKind.TypeSpecification:
return Resolve((TypeSpecificationHandle)handle, context);
default:
throw new NotSupportedException();
}
}
public static MethodDefinition ResolveMember(EntityHandle handle, IMetadataResolveContext context)
{
switch (handle.Kind) {
case HandleKind.MemberReference:
break;
}
throw new NotImplementedException();
}
/// <summary> /// <summary>
/// Implements resolving of TypeReferences to TypeDefinitions as decribed in II.7.3 of ECMA-335 6th edition. /// Implements resolving of TypeReferences to TypeDefinitions as decribed in II.7.3 of ECMA-335 6th edition.
/// </summary> /// </summary>
public static TypeDefinition Resolve(TypeReferenceHandle handle, IMetadataResolveContext context) public static TypeDefinition Resolve(this TypeReferenceHandle handle, IMetadataResolveContext context)
{ {
var metadata = context.CurrentModule.GetMetadataReader(); var metadata = context.CurrentModule.GetMetadataReader();
var tr = metadata.GetTypeReference(handle); var tr = metadata.GetTypeReference(handle);
@ -101,7 +124,7 @@ namespace ICSharpCode.Decompiler.Dom
return default(TypeDefinitionHandle); return default(TypeDefinitionHandle);
} }
public static IMemberDefinition Resolve(MemberReferenceHandle handle, IMetadataResolveContext context) public static IMetadataEntity Resolve(MemberReferenceHandle handle, IMetadataResolveContext context)
{ {
var metadata = context.CurrentModule.GetMetadataReader(); var metadata = context.CurrentModule.GetMetadataReader();
var mr = metadata.GetMemberReference(handle); var mr = metadata.GetMemberReference(handle);
@ -120,23 +143,24 @@ namespace ICSharpCode.Decompiler.Dom
default: default:
throw new NotSupportedException(); throw new NotSupportedException();
} }
var name = metadata.GetString(mr.Name); /*var name = metadata.GetString(mr.Name);
switch (mr.GetKind()) { switch (mr.GetKind()) {
case MemberReferenceKind.Field: case MemberReferenceKind.Field:
return declaringType.Fields.FirstOrDefault(fd => fd.Name == name); return declaringType.Fields.FirstOrDefault(fd => fd.Name == name);
case MemberReferenceKind.Method: case MemberReferenceKind.Method:
var signature = mr.DecodeMethodSignature(new TypeSystem.Implementation.TypeReferenceSignatureDecoder(), default(Unit)); var signature = mr.DecodeMethodSignature(new TypeSystem.Implementation.TypeReferenceSignatureDecoder(), default(Unit));
return declaringType.Methods.SingleOrDefault(md => MatchMethodDefinition(name, signature, md)); return declaringType.Methods.SingleOrDefault(md => MatchMethodDefinition(name, signature, md));
} }*/
throw new NotSupportedException(); throw new NotSupportedException();
} }
static bool MatchMethodDefinition(string name, MethodSignature<TypeSystem.ITypeReference> signature, MethodDefinition md) static bool MatchMethodDefinition(string name, MethodSignature<TypeSystem.ITypeReference> signature, MethodDefinition md)
{ {
if (name != md.Name || md.GenericParameters.Count != signature.GenericParameterCount || signature.RequiredParameterCount != md.Parameters.Count) throw new NotImplementedException();
return false; //if (name != md.Name || md.GenericParameters.Count != signature.GenericParameterCount || signature.RequiredParameterCount != md.Parameters.Count)
// return false;
// TODO overload resolution... OMG // TODO overload resolution... OMG
return true; //return true;
} }
public static TypeDefinition Resolve(TypeSpecificationHandle handle, IMetadataResolveContext context) public static TypeDefinition Resolve(TypeSpecificationHandle handle, IMetadataResolveContext context)

114
ICSharpCode.Decompiler/Metadata/OperandType.cs

@ -0,0 +1,114 @@
// Copyright (c) 2014 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.Reflection.Metadata;
namespace ICSharpCode.Decompiler.Metadata
{
public enum OperandType
{
BrTarget,
Field,
I,
I8,
Method,
None,
R = 7,
Sig = 9,
String,
Switch,
Tok,
Type,
Variable,
ShortBrTarget,
ShortI,
ShortR,
ShortVariable
}
static partial class ILOpCodeExtensions
{
public static OperandType GetOperandType(this ILOpCode opCode)
{
ushort index = (ushort)((((int)opCode & 0x200) >> 1) | ((int)opCode & 0xff));
if (index >= operandTypes.Length)
return (OperandType)255;
return (OperandType)operandTypes[index];
}
public static string GetDisplayName(this ILOpCode opCode)
{
ushort index = (ushort)((((int)opCode & 0x200) >> 1) | ((int)opCode & 0xff));
if (index >= operandNames.Length)
return "";
return operandNames[index];
}
public static bool IsDefined(this ILOpCode opCode)
{
return !string.IsNullOrEmpty(GetDisplayName(opCode));
}
static ILOpCodeExtensions()
{
ILKeywords = BuildKeywordList(
"abstract", "algorithm", "alignment", "ansi", "any", "arglist",
"array", "as", "assembly", "assert", "at", "auto", "autochar", "beforefieldinit",
"blob", "blob_object", "bool", "brnull", "brnull.s", "brzero", "brzero.s", "bstr",
"bytearray", "byvalstr", "callmostderived", "carray", "catch", "cdecl", "cf",
"char", "cil", "class", "clsid", "const", "currency", "custom", "date", "decimal",
"default", "demand", "deny", "endmac", "enum", "error", "explicit", "extends", "extern",
"false", "famandassem", "family", "famorassem", "fastcall", "fault", "field", "filetime",
"filter", "final", "finally", "fixed", "float", "float32", "float64", "forwardref",
"fromunmanaged", "handler", "hidebysig", "hresult", "idispatch", "il", "illegal",
"implements", "implicitcom", "implicitres", "import", "in", "inheritcheck", "init",
"initonly", "instance", "int", "int16", "int32", "int64", "int8", "interface", "internalcall",
"iunknown", "lasterr", "lcid", "linkcheck", "literal", "localloc", "lpstr", "lpstruct", "lptstr",
"lpvoid", "lpwstr", "managed", "marshal", "method", "modopt", "modreq", "native", "nested",
"newslot", "noappdomain", "noinlining", "nomachine", "nomangle", "nometadata", "noncasdemand",
"noncasinheritance", "noncaslinkdemand", "noprocess", "not", "not_in_gc_heap", "notremotable",
"notserialized", "null", "nullref", "object", "objectref", "opt", "optil", "out",
"permitonly", "pinned", "pinvokeimpl", "prefix1", "prefix2", "prefix3", "prefix4", "prefix5", "prefix6",
"prefix7", "prefixref", "prejitdeny", "prejitgrant", "preservesig", "private", "privatescope", "protected",
"public", "record", "refany", "reqmin", "reqopt", "reqrefuse", "reqsecobj", "request", "retval",
"rtspecialname", "runtime", "safearray", "sealed", "sequential", "serializable", "special", "specialname",
"static", "stdcall", "storage", "stored_object", "stream", "streamed_object", "string", "struct",
"synchronized", "syschar", "sysstring", "tbstr", "thiscall", "tls", "to", "true", "typedref",
"unicode", "unmanaged", "unmanagedexp", "unsigned", "unused", "userdefined", "value", "valuetype",
"vararg", "variant", "vector", "virtual", "void", "wchar", "winapi", "with", "wrapper",
// These are not listed as keywords in spec, but ILAsm treats them as such
"property", "type", "flags", "callconv", "strict"
);
}
public static readonly HashSet<string> ILKeywords;
static HashSet<string> BuildKeywordList(params string[] keywords)
{
HashSet<string> s = new HashSet<string>(keywords);
foreach (var inst in operandNames) {
if (string.IsNullOrEmpty(inst))
continue;
s.Add(inst);
}
return s;
}
}
}

2
ICSharpCode.Decompiler/Dom/SequencePoint.cs → ICSharpCode.Decompiler/Metadata/SequencePoint.cs

@ -4,7 +4,7 @@ using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
using System.Text; using System.Text;
namespace ICSharpCode.Decompiler.Dom namespace ICSharpCode.Decompiler.Metadata
{ {
using SRMDocument = System.Reflection.Metadata.Document; using SRMDocument = System.Reflection.Metadata.Document;

4
ICSharpCode.Decompiler/DotNetCore/UniversalAssemblyResolver.cs → ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs

@ -3,10 +3,8 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Reflection.PortableExecutable; using System.Reflection.PortableExecutable;
using System.Text; using System.Text;
using ICSharpCode.Decompiler.Dom;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler namespace ICSharpCode.Decompiler.Metadata
{ {
public class UniversalAssemblyResolver : IAssemblyResolver public class UniversalAssemblyResolver : IAssemblyResolver
{ {

2
ICSharpCode.Decompiler/DotNetCore/UnresolvedAssemblyNameReference.cs → ICSharpCode.Decompiler/Metadata/UnresolvedAssemblyNameReference.cs

@ -4,7 +4,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace ICSharpCode.Decompiler namespace ICSharpCode.Decompiler.Metadata
{ {
public sealed class UnresolvedAssemblyNameReference public sealed class UnresolvedAssemblyNameReference
{ {

204
ICSharpCode.Decompiler/SRMExtensions.cs

@ -0,0 +1,204 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler
{
public static partial class SRMExtensions
{
public static bool HasFlag(this TypeDefinition typeDefinition, TypeAttributes attribute) => (typeDefinition.Attributes & attribute) == attribute;
public static bool HasFlag(this MethodDefinition methodDefinition, MethodAttributes attribute) => (methodDefinition.Attributes & attribute) == attribute;
public static bool HasFlag(this FieldDefinition fieldDefinition, FieldAttributes attribute) => (fieldDefinition.Attributes & attribute) == attribute;
public static bool HasFlag(this PropertyDefinition propertyDefinition, PropertyAttributes attribute) => (propertyDefinition.Attributes & attribute) == attribute;
public static bool HasFlag(this EventDefinition eventDefinition, EventAttributes attribute) => (eventDefinition.Attributes & attribute) == attribute;
public static bool IsValueType(this TypeDefinitionHandle handle, MetadataReader reader)
{
return reader.GetTypeDefinition(handle).IsValueType(reader);
}
public static bool IsValueType(this TypeDefinition typeDefinition, MetadataReader reader)
{
if (typeDefinition.BaseType.IsNil)
return false;
var baseType = typeDefinition.BaseType.GetFullTypeName(reader).ToString();
if (baseType == "System.Enum")
return true;
var thisType = typeDefinition.GetFullTypeName(reader).ToString();
return baseType == "System.ValueType" && thisType != "System.Enum";
}
public static bool IsEnum(this TypeDefinitionHandle handle, MetadataReader reader)
{
return reader.GetTypeDefinition(handle).IsEnum(reader);
}
public static bool IsEnum(this TypeDefinition typeDefinition, MetadataReader reader)
{
if (typeDefinition.BaseType.IsNil)
return false;
return typeDefinition.BaseType.GetFullTypeName(reader).ToString() == "System.Enum";
}
public static bool IsDelegate(this TypeDefinitionHandle handle, MetadataReader reader)
{
return reader.GetTypeDefinition(handle).IsDelegate(reader);
}
public static bool IsDelegate(this TypeDefinition typeDefinition, MetadataReader reader)
{
var baseType = typeDefinition.BaseType;
return !baseType.IsNil && baseType.GetFullTypeName(reader).ToString() == typeof(MulticastDelegate).FullName;
}
public static bool IsExtensionMethod(this MethodDefinition methodDefinition, MetadataReader reader)
{
if (methodDefinition.HasFlag(MethodAttributes.Static)) {
foreach (var attribute in methodDefinition.GetCustomAttributes()) {
string typeName = reader.GetCustomAttribute(attribute).GetAttributeType(reader).GetFullTypeName(reader).ToString();
if (typeName == "System.Runtime.CompilerServices.ExtensionAttribute")
return true;
}
}
return false;
}
public static bool HasBody(this MethodDefinitionHandle handle, MetadataReader reader)
{
var methodDefinition = reader.GetMethodDefinition(handle);
return (methodDefinition.Attributes & MethodAttributes.Abstract) == 0 &&
(methodDefinition.Attributes & MethodAttributes.PinvokeImpl) == 0 &&
(methodDefinition.ImplAttributes & MethodImplAttributes.InternalCall) == 0 &&
(methodDefinition.ImplAttributes & MethodImplAttributes.Native) == 0 &&
(methodDefinition.ImplAttributes & MethodImplAttributes.Unmanaged) == 0 &&
(methodDefinition.ImplAttributes & MethodImplAttributes.Runtime) == 0;
}
public static bool HasBody(this MethodDefinition methodDefinition)
{
return (methodDefinition.Attributes & MethodAttributes.Abstract) == 0 &&
(methodDefinition.Attributes & MethodAttributes.PinvokeImpl) == 0 &&
(methodDefinition.ImplAttributes & MethodImplAttributes.InternalCall) == 0 &&
(methodDefinition.ImplAttributes & MethodImplAttributes.Native) == 0 &&
(methodDefinition.ImplAttributes & MethodImplAttributes.Unmanaged) == 0 &&
(methodDefinition.ImplAttributes & MethodImplAttributes.Runtime) == 0;
}
public static MethodDefinitionHandle GetAny(this PropertyAccessors accessors)
{
if (!accessors.Getter.IsNil)
return accessors.Getter;
return accessors.Setter;
}
public static MethodDefinitionHandle GetAny(this EventAccessors accessors)
{
if (!accessors.Adder.IsNil)
return accessors.Adder;
if (!accessors.Remover.IsNil)
return accessors.Remover;
return accessors.Raiser;
}
/// <summary>
/// Gets the type of the attribute.
/// </summary>
public static EntityHandle GetAttributeType(this CustomAttribute attribute, MetadataReader reader)
{
switch (attribute.Constructor.Kind) {
case HandleKind.MethodDefinition:
var md = reader.GetMethodDefinition((MethodDefinitionHandle)attribute.Constructor);
return md.GetDeclaringType();
case HandleKind.MemberReference:
var mr = reader.GetMemberReference((MemberReferenceHandle)attribute.Constructor);
return mr.Parent;
default:
throw new NotSupportedException();
}
}
public static TypeReferenceHandle GetDeclaringType(this TypeReference tr)
{
switch (tr.ResolutionScope.Kind) {
case HandleKind.TypeReference:
return (TypeReferenceHandle)tr.ResolutionScope;
default:
return default(TypeReferenceHandle);
}
}
public static FullTypeName GetFullTypeName(this EntityHandle handle, MetadataReader reader)
{
if (handle.IsNil)
throw new ArgumentNullException(nameof(handle));
switch (handle.Kind) {
case HandleKind.TypeDefinition:
return ((TypeDefinitionHandle)handle).GetFullTypeName(reader);
case HandleKind.TypeReference:
return ((TypeReferenceHandle)handle).GetFullTypeName(reader);
case HandleKind.TypeSpecification:
return ((TypeSpecificationHandle)handle).GetFullTypeName(reader);
default:
throw new NotSupportedException();
}
}
public static FullTypeName GetFullTypeName(this TypeSpecificationHandle handle, MetadataReader reader, bool omitGenericParamCount = false)
{
if (handle.IsNil)
throw new ArgumentNullException(nameof(handle));
var ts = reader.GetTypeSpecification(handle);
return ts.DecodeSignature(new Metadata.FullTypeNameSignatureDecoder(reader), default(Unit));
}
public static FullTypeName GetFullTypeName(this TypeReferenceHandle handle, MetadataReader reader, bool omitGenericParamCount = false)
{
if (handle.IsNil)
throw new ArgumentNullException(nameof(handle));
var tr = reader.GetTypeReference(handle);
TypeReferenceHandle declaringTypeHandle;
if ((declaringTypeHandle = tr.GetDeclaringType()).IsNil) {
string @namespace = tr.Namespace.IsNil ? "" : reader.GetString(tr.Namespace);
return new FullTypeName(new TopLevelTypeName(@namespace, reader.GetString(tr.Name)));
} else {
return declaringTypeHandle.GetFullTypeName(reader, omitGenericParamCount).NestedType(reader.GetString(tr.Name), 0);
}
}
public static FullTypeName GetFullTypeName(this TypeDefinitionHandle handle, MetadataReader reader)
{
if (handle.IsNil)
throw new ArgumentNullException(nameof(handle));
return reader.GetTypeDefinition(handle).GetFullTypeName(reader);
}
public static FullTypeName GetFullTypeName(this TypeDefinition td, MetadataReader reader)
{
TypeDefinitionHandle declaringTypeHandle;
if ((declaringTypeHandle = td.GetDeclaringType()).IsNil) {
string @namespace = td.Namespace.IsNil ? "" : reader.GetString(td.Namespace);
return new FullTypeName(new TopLevelTypeName(@namespace, reader.GetString(td.Name)));
} else {
return declaringTypeHandle.GetFullTypeName(reader).NestedType(reader.GetString(td.Name), 0);
}
}
public static TType DecodeSignature<TType, TGenericContext>(this EventDefinition ev, MetadataReader reader, ISignatureTypeProvider<TType, TGenericContext> provider, TGenericContext genericContext)
{
switch (ev.Type.Kind) {
case HandleKind.TypeDefinition:
return provider.GetTypeFromDefinition(reader, (TypeDefinitionHandle)ev.Type, 0);
case HandleKind.TypeReference:
return provider.GetTypeFromReference(reader, (TypeReferenceHandle)ev.Type, 0);
case HandleKind.TypeSpecification:
return provider.GetTypeFromSpecification(reader, genericContext, (TypeSpecificationHandle)ev.Type, 0);
default:
throw new NotSupportedException();
}
}
}
}

62
ICSharpCode.Decompiler/SRMHacks.cs

@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.Decompiler
{
public static partial class SRMExtensions
{
public static unsafe MethodSemanticsAttributes GetMethodSemanticsAttributes(this MethodDefinitionHandle handle, MetadataReader reader)
{
byte* startPointer = reader.MetadataPointer;
int offset = reader.GetTableMetadataOffset(TableIndex.MethodSemantics);
int rowSize = reader.GetTableRowSize(TableIndex.MethodSemantics);
int rowCount = reader.GetTableRowCount(TableIndex.MethodSemantics);
var small = reader.IsSmallReference(TableIndex.MethodDef);
int methodRowNo = reader.GetRowNumber(handle);
for (int row = rowCount - 1; row >= 0; row--) {
byte* ptr = startPointer + offset + rowSize * row;
uint rowNo = small ? *(ushort*)(ptr + 2) : *(uint*)(ptr + 2);
if (methodRowNo == rowNo) {
return (MethodSemanticsAttributes)(*(ushort*)ptr);
}
}
return 0;
}
public static unsafe ImmutableArray<MethodImplementationHandle> GetMethodImplementations(this MethodDefinitionHandle handle, MetadataReader reader)
{
byte* startPointer = reader.MetadataPointer;
int offset = reader.GetTableMetadataOffset(TableIndex.MethodImpl);
int rowSize = reader.GetTableRowSize(TableIndex.MethodImpl);
int rowCount = reader.GetTableRowCount(TableIndex.MethodImpl);
var methodDefSize = reader.GetReferenceSize(TableIndex.MethodDef);
var typeDefSize = reader.GetReferenceSize(TableIndex.TypeDef);
var containingTypeRow = reader.GetRowNumber(reader.GetMethodDefinition(handle).GetDeclaringType());
var methodDefRow = reader.GetRowNumber(handle);
var list = new List<MethodImplementationHandle>();
// TODO : if sorted -> binary search?
for (int row = 0; row < reader.GetTableRowCount(TableIndex.MethodImpl); row++) {
byte* ptr = startPointer + offset + rowSize * row;
uint currentTypeRow = typeDefSize == 2 ? *(ushort*)ptr : *(uint*)ptr;
if (currentTypeRow != containingTypeRow) continue;
uint currentMethodRowCoded = methodDefSize == 2 ? *(ushort*)(ptr + typeDefSize) : *(uint*)(ptr + typeDefSize);
if ((currentMethodRowCoded >> 1) != methodDefRow) continue;
list.Add(MetadataTokens.MethodImplementationHandle(row + 1));
}
return list.ToImmutableArray();
}
}
}

3
ICSharpCode.Decompiler/TypeSystem/CecilLoader.cs

@ -23,7 +23,6 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable; using System.Reflection.PortableExecutable;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -31,6 +30,8 @@ using System.Threading;
using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using static ICSharpCode.Decompiler.Metadata.MetadataExtensions;
namespace ICSharpCode.Decompiler.TypeSystem namespace ICSharpCode.Decompiler.TypeSystem
{ {
/// <summary> /// <summary>

42
ICSharpCode.Decompiler/TypeSystem/Implementation/TypeSpecification.cs

@ -17,22 +17,20 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using System.Reflection.Metadata; using SRM = System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{ {
class SignatureTypeReference : ITypeReference class SignatureTypeReference : ITypeReference
{ {
readonly TypeSpecification typeSpecification; readonly SRM.TypeSpecification typeSpecification;
readonly MetadataReader reader; readonly SRM.MetadataReader reader;
public SignatureTypeReference(TypeSpecificationHandle handle, MetadataReader reader) public SignatureTypeReference(SRM.TypeSpecificationHandle handle, SRM.MetadataReader reader)
{ {
this.typeSpecification = reader.GetTypeSpecification(handle); this.typeSpecification = reader.GetTypeSpecification(handle);
this.reader = reader; this.reader = reader;
@ -105,9 +103,9 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
} }
} }
class TypeReferenceSignatureDecoder : ISignatureTypeProvider<ITypeReference, Unit> class TypeReferenceSignatureDecoder : SRM.ISignatureTypeProvider<ITypeReference, Unit>
{ {
public ITypeReference GetArrayType(ITypeReference elementType, ArrayShape shape) public ITypeReference GetArrayType(ITypeReference elementType, SRM.ArrayShape shape)
{ {
return new ArrayTypeReference(elementType, shape.Rank); return new ArrayTypeReference(elementType, shape.Rank);
} }
@ -117,7 +115,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return new ByReferenceTypeReference(elementType); return new ByReferenceTypeReference(elementType);
} }
public ITypeReference GetFunctionPointerType(MethodSignature<ITypeReference> signature) public ITypeReference GetFunctionPointerType(SRM.MethodSignature<ITypeReference> signature)
{ {
return KnownTypeReference.IntPtr; return KnownTypeReference.IntPtr;
} }
@ -152,7 +150,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return new PointerTypeReference(elementType); return new PointerTypeReference(elementType);
} }
public ITypeReference GetPrimitiveType(PrimitiveTypeCode typeCode) public ITypeReference GetPrimitiveType(SRM.PrimitiveTypeCode typeCode)
{ {
return KnownTypeReference.Get(typeCode.ToKnownTypeCode()); return KnownTypeReference.Get(typeCode.ToKnownTypeCode());
} }
@ -162,12 +160,12 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return new ArrayTypeReference(elementType); return new ArrayTypeReference(elementType);
} }
public ITypeReference GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) public ITypeReference GetTypeFromDefinition(SRM.MetadataReader reader, SRM.TypeDefinitionHandle handle, byte rawTypeKind)
{ {
return new GetClassTypeReference(handle.GetFullTypeName(reader), DefaultAssemblyReference.CurrentAssembly); return new GetClassTypeReference(handle.GetFullTypeName(reader), DefaultAssemblyReference.CurrentAssembly);
} }
public ITypeReference GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) public ITypeReference GetTypeFromReference(SRM.MetadataReader reader, SRM.TypeReferenceHandle handle, byte rawTypeKind)
{ {
var asmref = handle.GetDeclaringAssembly(reader); var asmref = handle.GetDeclaringAssembly(reader);
if (asmref.IsNil) if (asmref.IsNil)
@ -176,13 +174,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return new GetClassTypeReference(handle.GetFullTypeName(reader), new DefaultAssemblyReference(reader.GetString(asm.Name))); return new GetClassTypeReference(handle.GetFullTypeName(reader), new DefaultAssemblyReference(reader.GetString(asm.Name)));
} }
public ITypeReference GetTypeFromSpecification(MetadataReader reader, Unit genericContext, TypeSpecificationHandle handle, byte rawTypeKind) public ITypeReference GetTypeFromSpecification(SRM.MetadataReader reader, Unit genericContext, SRM.TypeSpecificationHandle handle, byte rawTypeKind)
{ {
return new SignatureTypeReference(handle, reader); return new SignatureTypeReference(handle, reader);
} }
} }
public class TypeSystemAttributeTypeProvider : ICustomAttributeTypeProvider<IType> public class TypeSystemAttributeTypeProvider : SRM.ICustomAttributeTypeProvider<IType>
{ {
readonly ITypeResolveContext context; readonly ITypeResolveContext context;
@ -193,7 +191,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
this.context = context; this.context = context;
} }
public IType GetPrimitiveType(PrimitiveTypeCode typeCode) public IType GetPrimitiveType(SRM.PrimitiveTypeCode typeCode)
{ {
return context.Compilation.FindType(typeCode.ToKnownTypeCode()); return context.Compilation.FindType(typeCode.ToKnownTypeCode());
} }
@ -208,13 +206,13 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return new ArrayType(context.Compilation, elementType); return new ArrayType(context.Compilation, elementType);
} }
public IType GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) public IType GetTypeFromDefinition(SRM.MetadataReader reader, SRM.TypeDefinitionHandle handle, byte rawTypeKind)
{ {
var type = reader.GetTypeDefinition(handle); var type = reader.GetTypeDefinition(handle);
return new DefaultUnresolvedTypeDefinition(type.GetFullTypeName(reader).ToString()).Resolve(context); return new DefaultUnresolvedTypeDefinition(type.GetFullTypeName(reader).ToString()).Resolve(context);
} }
public IType GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) public IType GetTypeFromReference(SRM.MetadataReader reader, SRM.TypeReferenceHandle handle, byte rawTypeKind)
{ {
return new DefaultUnresolvedTypeDefinition(handle.GetFullTypeName(reader).ToString()).Resolve(context); return new DefaultUnresolvedTypeDefinition(handle.GetFullTypeName(reader).ToString()).Resolve(context);
} }
@ -224,7 +222,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
return new GetClassTypeReference(new FullTypeName(name)).Resolve(context); return new GetClassTypeReference(new FullTypeName(name)).Resolve(context);
} }
public PrimitiveTypeCode GetUnderlyingEnumType(IType type) public SRM.PrimitiveTypeCode GetUnderlyingEnumType(IType type)
{ {
var def = type.GetEnumUnderlyingType().GetDefinition(); var def = type.GetEnumUnderlyingType().GetDefinition();
if (def == null) if (def == null)
@ -240,11 +238,11 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public class MetadataUnresolvedAttributeBlob : IUnresolvedAttribute, ISupportsInterning public class MetadataUnresolvedAttributeBlob : IUnresolvedAttribute, ISupportsInterning
{ {
MetadataReader reader; SRM.MetadataReader reader;
ITypeReference attributeType; ITypeReference attributeType;
CustomAttribute attribute; SRM.CustomAttribute attribute;
public MetadataUnresolvedAttributeBlob(MetadataReader reader, ITypeReference attributeType, CustomAttribute attribute) public MetadataUnresolvedAttributeBlob(SRM.MetadataReader reader, ITypeReference attributeType, SRM.CustomAttribute attribute)
{ {
this.reader = reader; this.reader = reader;
this.attributeType = attributeType; this.attributeType = attributeType;

8
ILSpy/ExtensionMethods.cs

@ -102,6 +102,14 @@ namespace ICSharpCode.ILSpy
return false; return false;
} }
public static string ToSuffixString(this System.Reflection.Metadata.EntityHandle token)
{
if (!DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokens)
return string.Empty;
return " @" + System.Reflection.Metadata.Ecma335.MetadataTokens.GetToken(token).ToString("x8");
}
public static string ToSuffixString(this System.Reflection.Metadata.MethodDefinitionHandle token) public static string ToSuffixString(this System.Reflection.Metadata.MethodDefinitionHandle token)
{ {
if (!DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokens) if (!DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokens)

1
ILSpy/ILSpy.csproj

@ -126,7 +126,6 @@
<Compile Include="Images\Images.cs" /> <Compile Include="Images\Images.cs" />
<Compile Include="Languages\ILLanguage.cs" /> <Compile Include="Languages\ILLanguage.cs" />
<Compile Include="Languages\IResourceFileHandler.cs" /> <Compile Include="Languages\IResourceFileHandler.cs" />
<Compile Include="Languages\ITypeProvider.cs" />
<Compile Include="Languages\Language.cs" /> <Compile Include="Languages\Language.cs" />
<Compile Include="Languages\Languages.cs" /> <Compile Include="Languages\Languages.cs" />
<Compile Include="LoadedAssembly.cs" /> <Compile Include="LoadedAssembly.cs" />

2
ILSpy/Languages/ILAstLanguage.cs

@ -23,7 +23,7 @@ using System.Linq;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.IL.Transforms;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;

47
ILSpy/Languages/ILLanguage.cs

@ -25,7 +25,7 @@ using System.Reflection.Metadata;
using System.IO; using System.IO;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
using System.Linq; using System.Linq;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
{ {
@ -57,62 +57,69 @@ namespace ICSharpCode.ILSpy
}; };
} }
public override void DecompileMethod(Decompiler.Dom.MethodDefinition method, ITextOutput output, DecompilationOptions options) public override void DecompileMethod(Decompiler.Metadata.MethodDefinition method, ITextOutput output, DecompilationOptions options)
{ {
var dis = CreateDisassembler(output, options); var dis = CreateDisassembler(output, options);
dis.DisassembleMethod(method); dis.DisassembleMethod(method);
} }
public override void DecompileField(Decompiler.Dom.FieldDefinition field, ITextOutput output, DecompilationOptions options) public override void DecompileField(Decompiler.Metadata.FieldDefinition field, ITextOutput output, DecompilationOptions options)
{ {
var dis = CreateDisassembler(output, options); var dis = CreateDisassembler(output, options);
dis.DisassembleField(field); dis.DisassembleField(field);
} }
public override void DecompileProperty(Decompiler.Dom.PropertyDefinition property, ITextOutput output, DecompilationOptions options) public override void DecompileProperty(Decompiler.Metadata.PropertyDefinition property, ITextOutput output, DecompilationOptions options)
{ {
var dis = CreateDisassembler(output, options); var dis = CreateDisassembler(output, options);
dis.DisassembleProperty(property); dis.DisassembleProperty(property);
if (!property.GetMethod.IsNil) { var accessors = property.This().GetAccessors();
if (!accessors.Getter.IsNil) {
output.WriteLine(); output.WriteLine();
dis.DisassembleMethod(property.GetMethod); dis.DisassembleMethod(new Decompiler.Metadata.MethodDefinition(property.Module, accessors.Getter));
} }
if (!property.SetMethod.IsNil) { if (!accessors.Setter.IsNil) {
output.WriteLine(); output.WriteLine();
dis.DisassembleMethod(property.SetMethod); dis.DisassembleMethod(new Decompiler.Metadata.MethodDefinition(property.Module, accessors.Setter));
} }
foreach (var m in property.OtherMethods) { /*foreach (var m in property.OtherMethods) {
output.WriteLine(); output.WriteLine();
dis.DisassembleMethod(m); dis.DisassembleMethod(m);
} }*/
} }
public override void DecompileEvent(Decompiler.Dom.EventDefinition ev, ITextOutput output, DecompilationOptions options) public override void DecompileEvent(Decompiler.Metadata.EventDefinition ev, ITextOutput output, DecompilationOptions options)
{ {
var dis = CreateDisassembler(output, options); var dis = CreateDisassembler(output, options);
dis.DisassembleEvent(ev); dis.DisassembleEvent(ev);
if (!ev.AddMethod.IsNil) { var accessors = ev.This().GetAccessors();
if (!accessors.Adder.IsNil) {
output.WriteLine(); output.WriteLine();
dis.DisassembleMethod(ev.AddMethod); dis.DisassembleMethod(new Decompiler.Metadata.MethodDefinition(ev.Module, accessors.Adder));
} }
if (!ev.RemoveMethod.IsNil) { if (!accessors.Remover.IsNil) {
output.WriteLine(); output.WriteLine();
dis.DisassembleMethod(ev.RemoveMethod); dis.DisassembleMethod(new Decompiler.Metadata.MethodDefinition(ev.Module, accessors.Remover));
} }
foreach (var m in ev.OtherMethods) { if (!accessors.Raiser.IsNil) {
output.WriteLine(); output.WriteLine();
dis.DisassembleMethod(m); dis.DisassembleMethod(new Decompiler.Metadata.MethodDefinition(ev.Module, accessors.Raiser));
} }
/*foreach (var m in ev.OtherMethods) {
output.WriteLine();
dis.DisassembleMethod(m);
}*/
} }
public override void DecompileType(Decompiler.Dom.TypeDefinition type, ITextOutput output, DecompilationOptions options) public override void DecompileType(Decompiler.Metadata.TypeDefinition type, ITextOutput output, DecompilationOptions options)
{ {
var dis = CreateDisassembler(output, options); var dis = CreateDisassembler(output, options);
dis.DisassembleType(type); dis.DisassembleType(type);
} }
public override void DecompileNamespace(string nameSpace, IEnumerable<Decompiler.Dom.TypeDefinition> types, ITextOutput output, DecompilationOptions options) public override void DecompileNamespace(string nameSpace, IEnumerable<Decompiler.Metadata.TypeDefinition> types, ITextOutput output, DecompilationOptions options)
{ {
var dis = CreateDisassembler(output, options); var dis = CreateDisassembler(output, options);
dis.DisassembleNamespace(nameSpace, types); dis.DisassembleNamespace(nameSpace, types);
@ -138,7 +145,7 @@ namespace ICSharpCode.ILSpy
} }
} }
public override string TypeToString(Decompiler.Dom.ITypeReference type, bool includeNamespace, Decompiler.Dom.ICustomAttributeProvider typeAttributes = null) public override string TypeToString(Entity type, bool includeNamespace, CustomAttributeHandleCollection typeAttributes = default(CustomAttributeHandleCollection))
{ {
PlainTextOutput output = new PlainTextOutput(); PlainTextOutput output = new PlainTextOutput();
type.WriteTo(output, GenericContext.Empty, includeNamespace ? ILNameSyntax.TypeName : ILNameSyntax.ShortTypeName); type.WriteTo(output, GenericContext.Empty, includeNamespace ? ILNameSyntax.TypeName : ILNameSyntax.ShortTypeName);

86
ILSpy/Languages/ITypeProvider.cs

@ -1,86 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection.Metadata;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.Dom;
namespace ICSharpCode.ILSpy
{
public sealed class CSharpSignatureTypeProvider : ISignatureTypeProvider<string, GenericContext>
{
public string GetArrayType(string elementType, ArrayShape shape)
{
throw new NotImplementedException();
}
public string GetByReferenceType(string elementType)
{
throw new NotImplementedException();
}
public string GetFunctionPointerType(MethodSignature<string> signature)
{
throw new NotImplementedException();
}
public string GetGenericInstantiation(string genericType, ImmutableArray<string> typeArguments)
{
throw new NotImplementedException();
}
public string GetGenericMethodParameter(GenericContext genericContext, int index)
{
throw new NotImplementedException();
}
public string GetGenericTypeParameter(GenericContext genericContext, int index)
{
throw new NotImplementedException();
}
public string GetModifiedType(string modifier, string unmodifiedType, bool isRequired)
{
throw new NotImplementedException();
}
public string GetPinnedType(string elementType)
{
throw new NotImplementedException();
}
public string GetPointerType(string elementType)
{
throw new NotImplementedException();
}
public string GetPrimitiveType(PrimitiveTypeCode typeCode)
{
throw new NotImplementedException();
}
public string GetSZArrayType(string elementType)
{
throw new NotImplementedException();
}
public string GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind)
{
throw new NotImplementedException();
}
public string GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind)
{
throw new NotImplementedException();
}
public string GetTypeFromSpecification(MetadataReader reader, GenericContext genericContext, TypeSpecificationHandle handle, byte rawTypeKind)
{
throw new NotImplementedException();
}
}
}

80
ILSpy/Languages/Language.cs

@ -21,7 +21,8 @@ using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Reflection.PortableExecutable; using System.Reflection.PortableExecutable;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Metadata;
using static System.Reflection.Metadata.PEReaderExtensions; using static System.Reflection.Metadata.PEReaderExtensions;
using SRM = System.Reflection.Metadata; using SRM = System.Reflection.Metadata;
@ -61,22 +62,30 @@ namespace ICSharpCode.ILSpy
public virtual void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options) public virtual void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options)
{ {
WriteCommentLine(output, TypeToString(method.DeclaringType, true) + "." + method.Name); WriteCommentLine(output, TypeToString(new Entity(method.Module, method.This().GetDeclaringType()), true) + "." + method.Name);
} }
public virtual void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilationOptions options) public virtual void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilationOptions options)
{ {
WriteCommentLine(output, TypeToString(property.DeclaringType, true) + "." + property.Name); var metadata = property.Module.GetMetadataReader();
var propertyDefinition = metadata.GetPropertyDefinition(property.Handle);
var declaringType = metadata.GetMethodDefinition(propertyDefinition.GetAccessors().GetAny()).GetDeclaringType();
WriteCommentLine(output, TypeToString(new Entity(property.Module, declaringType), true) + "." + metadata.GetString(propertyDefinition.Name));
} }
public virtual void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options) public virtual void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options)
{ {
WriteCommentLine(output, TypeToString(field.DeclaringType, true) + "." + field.Name); var metadata = field.Module.GetMetadataReader();
var fieldDefinition = metadata.GetFieldDefinition(field.Handle);
WriteCommentLine(output, TypeToString(new Entity(field.Module, fieldDefinition.GetDeclaringType()), true) + "." + metadata.GetString(fieldDefinition.Name));
} }
public virtual void DecompileEvent(EventDefinition ev, ITextOutput output, DecompilationOptions options) public virtual void DecompileEvent(EventDefinition ev, ITextOutput output, DecompilationOptions options)
{ {
WriteCommentLine(output, TypeToString(ev.DeclaringType, true) + "." + ev.Name); var metadata = ev.Module.GetMetadataReader();
var eventDefinition = metadata.GetEventDefinition(ev.Handle);
var declaringType = metadata.GetMethodDefinition(eventDefinition.GetAccessors().GetAny()).GetDeclaringType();
WriteCommentLine(output, TypeToString(new Entity(ev.Module, declaringType), true) + "." + metadata.GetString(eventDefinition.Name));
} }
public virtual void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options) public virtual void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options)
@ -115,12 +124,14 @@ namespace ICSharpCode.ILSpy
/// <summary> /// <summary>
/// Converts a type reference into a string. This method is used by the member tree node for parameter and return types. /// Converts a type reference into a string. This method is used by the member tree node for parameter and return types.
/// </summary> /// </summary>
public virtual string TypeToString(ITypeReference type, bool includeNamespace, ICustomAttributeProvider typeAttributes = null) public virtual string TypeToString(Entity type, bool includeNamespace, SRM.CustomAttributeHandleCollection typeAttributes = default(SRM.CustomAttributeHandleCollection))
{ {
var metadata = type.Module.GetMetadataReader();
var fullName = type.Handle.GetFullTypeName(metadata);
if (includeNamespace) if (includeNamespace)
return type.FullName.ToString(); return fullName.ToString();
else else
return type.Name; return fullName.Name;
} }
public virtual SRM.ISignatureTypeProvider<string, GenericContext> CreateSignatureTypeProvider(bool includeNamespace) public virtual SRM.ISignatureTypeProvider<string, GenericContext> CreateSignatureTypeProvider(bool includeNamespace)
@ -132,54 +143,67 @@ namespace ICSharpCode.ILSpy
/// Converts a member signature to a string. /// Converts a member signature to a string.
/// This is used for displaying the tooltip on a member reference. /// This is used for displaying the tooltip on a member reference.
/// </summary> /// </summary>
public virtual string GetTooltip(IMemberReference member) public virtual string GetTooltip(Entity entity)
{ {
return member.Name; var metadata = entity.Module.GetMetadataReader();
} switch (entity.Handle.Kind) {
case SRM.HandleKind.TypeReference:
/// <summary> case SRM.HandleKind.TypeDefinition:
/// Converts a member signature to a string. case SRM.HandleKind.TypeSpecification:
/// This is used for displaying the tooltip on a member reference. return entity.Handle.GetFullTypeName(metadata).ToString();
/// </summary> case SRM.HandleKind.FieldDefinition:
public virtual string GetTooltip(ITypeReference type) var fieldDefinition = metadata.GetFieldDefinition((SRM.FieldDefinitionHandle)entity.Handle);
{ string fieldType = fieldDefinition.DecodeSignature(CreateSignatureTypeProvider(false), new GenericContext(fieldDefinition.GetDeclaringType(), entity.Module));
return TypeToString(type, true); return fieldType + " " + fieldDefinition.GetDeclaringType().GetFullTypeName(metadata) + "." + metadata.GetString(fieldDefinition.Name);
case SRM.HandleKind.MethodDefinition:
return TreeNodes.MethodTreeNode.GetText(entity, this).ToString();
case SRM.HandleKind.EventDefinition:
return TreeNodes.EventTreeNode.GetText(entity, this).ToString();
case SRM.HandleKind.PropertyDefinition:
return TreeNodes.PropertyTreeNode.GetText(entity, this).ToString();
default:
throw new NotSupportedException();
}
} }
public virtual string FormatFieldName(FieldDefinition field) public virtual string FormatFieldName(FieldDefinition field)
{ {
if (field.Handle.IsNil) if (field.Handle.IsNil)
throw new ArgumentNullException(nameof(field)); throw new ArgumentNullException(nameof(field));
return field.Name; var metadata = field.Module.GetMetadataReader();
return metadata.GetString(metadata.GetFieldDefinition(field.Handle).Name);
} }
public virtual string FormatPropertyName(PropertyDefinition property, bool? isIndexer = null) public virtual string FormatPropertyName(PropertyDefinition property, bool? isIndexer = null)
{ {
if (property.Handle.IsNil) if (property.Handle.IsNil)
throw new ArgumentNullException(nameof(property)); throw new ArgumentNullException(nameof(property));
return property.Name; var metadata = property.Module.GetMetadataReader();
return metadata.GetString(metadata.GetPropertyDefinition(property.Handle).Name);
} }
public virtual string FormatMethodName(MethodDefinition method) public virtual string FormatMethodName(MethodDefinition method)
{ {
if (method.Handle.IsNil) if (method.Handle.IsNil)
throw new ArgumentNullException(nameof(method)); throw new ArgumentNullException(nameof(method));
return method.Name; var metadata = method.Module.GetMetadataReader();
return metadata.GetString(metadata.GetMethodDefinition(method.Handle).Name);
} }
public virtual string FormatEventName(EventDefinition @event) public virtual string FormatEventName(EventDefinition @event)
{ {
if (@event.Handle.IsNil) if (@event.Handle.IsNil)
throw new ArgumentNullException(nameof(@event)); throw new ArgumentNullException(nameof(@event));
return @event.Name; var metadata = @event.Module.GetMetadataReader();
return metadata.GetString(metadata.GetEventDefinition(@event.Handle).Name);
} }
public virtual string FormatTypeName(TypeDefinition type) public virtual string FormatTypeName(TypeDefinition type)
{ {
if (type.Handle.IsNil) if (type.Handle.IsNil)
throw new ArgumentNullException(nameof(type)); throw new ArgumentNullException(nameof(type));
return type.Name; var metadata = type.Module.GetMetadataReader();
return metadata.GetString(metadata.GetTypeDefinition(type.Handle).Name);
} }
/// <summary> /// <summary>
@ -190,7 +214,7 @@ namespace ICSharpCode.ILSpy
return Name; return Name;
} }
public virtual bool ShowMember(IMemberReference member) public virtual bool ShowMember(IMetadataEntity member)
{ {
return true; return true;
} }
@ -198,7 +222,7 @@ namespace ICSharpCode.ILSpy
/// <summary> /// <summary>
/// Used by the analyzer to map compiler generated code back to the original code's location /// Used by the analyzer to map compiler generated code back to the original code's location
/// </summary> /// </summary>
public virtual IMemberReference GetOriginalCodeLocation(IMemberReference member) public virtual IMetadataEntity GetOriginalCodeLocation(IMetadataEntity member)
{ {
return member; return member;
} }

2
ILSpy/LoadedAssembly.cs

@ -23,7 +23,7 @@ using System.Reflection.PortableExecutable;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.Options; using ICSharpCode.ILSpy.Options;
using static System.Reflection.Metadata.PEReaderExtensions; using static System.Reflection.Metadata.PEReaderExtensions;

6
ILSpy/MainWindow.xaml.cs

@ -274,12 +274,12 @@ namespace ICSharpCode.ILSpy
foreach (LoadedAssembly asm in commandLineLoadedAssemblies) { foreach (LoadedAssembly asm in commandLineLoadedAssemblies) {
var def = asm.GetPEFileOrNull(); var def = asm.GetPEFileOrNull();
if (def != null) { if (def != null) {
/*MemberReference mr = XmlDocKeyProvider.FindMemberByKey(def, args.NavigateTo); var mr = XmlDocKeyProvider.FindMemberByKey(def, args.NavigateTo);
if (mr != null) { if (!mr.IsNil) {
found = true; found = true;
JumpToReference(mr); JumpToReference(mr);
break; break;
}*/ }
} }
} }
} }

4
ILSpy/SearchPane.cs

@ -26,7 +26,7 @@ using System.Windows.Controls;
using System.Windows.Input; using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Threading; using System.Windows.Threading;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
using Mono.Cecil; using Mono.Cecil;
@ -333,7 +333,7 @@ namespace ICSharpCode.ILSpy
public static readonly System.Collections.Generic.IComparer<SearchResult> Comparer = new SearchResultComparer(); public static readonly System.Collections.Generic.IComparer<SearchResult> Comparer = new SearchResultComparer();
public IMemberReference Member { get; set; } public IMetadataEntity Member { get; set; }
public float Fitness { get; set; } public float Fitness { get; set; }
public string Location { get; set; } public string Location { get; set; }

106
ILSpy/SearchStrategies.cs

@ -5,10 +5,14 @@ using System.Text.RegularExpressions;
using System.Windows.Media; using System.Windows.Media;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using System.Reflection; using System.Reflection;
using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Disassembler;
using SRM = System.Reflection.Metadata;
using ILOpCode = System.Reflection.Metadata.ILOpCode; using ILOpCode = System.Reflection.Metadata.ILOpCode;
using ICSharpCode.Decompiler;
using static System.Reflection.Metadata.PEReaderExtensions;
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
{ {
@ -38,9 +42,29 @@ namespace ICSharpCode.ILSpy
searchTerm = terms; searchTerm = terms;
} }
protected float CalculateFitness(IMemberReference member) protected float CalculateFitness(IMetadataEntity member)
{ {
string text = member.Name; var metadata = member.Module.GetMetadataReader();
string text;
switch (member) {
case TypeDefinition td:
text = metadata.GetString(metadata.GetTypeDefinition(td.Handle).Name);
break;
case FieldDefinition fd:
text = metadata.GetString(metadata.GetFieldDefinition(fd.Handle).Name);
break;
case MethodDefinition md:
text = metadata.GetString(metadata.GetMethodDefinition(md.Handle).Name);
break;
case PropertyDefinition pd:
text = metadata.GetString(metadata.GetPropertyDefinition(pd.Handle).Name);
break;
case EventDefinition ed:
text = metadata.GetString(metadata.GetEventDefinition(ed.Handle).Name);
break;
default:
throw new NotSupportedException();
}
// Probably compiler generated types without meaningful names, show them last // Probably compiler generated types without meaningful names, show them last
if (text.StartsWith("<")) { if (text.StartsWith("<")) {
@ -79,7 +103,7 @@ namespace ICSharpCode.ILSpy
return false; return false;
} }
protected virtual bool MatchName(IMemberDefinition m, Language language) protected virtual bool MatchName(IMetadataEntity m, Language language)
{ {
return IsMatch(t => GetLanguageSpecificName(language, m, regex != null ? fullNameSearch : t.Contains("."))); return IsMatch(t => GetLanguageSpecificName(language, m, regex != null ? fullNameSearch : t.Contains(".")));
} }
@ -122,25 +146,26 @@ namespace ICSharpCode.ILSpy
return true; return true;
} }
string GetLanguageSpecificName(Language language, IMemberDefinition member, bool fullName = false) string GetLanguageSpecificName(Language language, IMetadataEntity member, bool fullName = false)
{ {
var metadata = member.Module.GetMetadataReader();
switch (member) { switch (member) {
case TypeDefinition t: case TypeDefinition t:
return language.TypeToString(t, fullName); return language.TypeToString(t, fullName);
case FieldDefinition f: case FieldDefinition f:
return fullName ? language.TypeToString(f.DeclaringType, fullName) + "." + language.FormatFieldName(f) : language.FormatFieldName(f); return fullName ? language.TypeToString(new TypeDefinition(member.Module, metadata.GetFieldDefinition(f.Handle).GetDeclaringType()), fullName) + "." + language.FormatFieldName(f) : language.FormatFieldName(f);
case PropertyDefinition p: case PropertyDefinition p:
return fullName ? language.TypeToString(p.DeclaringType, fullName) + "." + language.FormatPropertyName(p) : language.FormatPropertyName(p); return fullName ? language.TypeToString(new TypeDefinition(member.Module, metadata.GetMethodDefinition(metadata.GetPropertyDefinition(p.Handle).GetAccessors().GetAny()).GetDeclaringType()), fullName) + "." + language.FormatPropertyName(p) : language.FormatPropertyName(p);
case MethodDefinition m: case MethodDefinition m:
return fullName ? language.TypeToString(m.DeclaringType, fullName) + "." + language.FormatMethodName(m) : language.FormatMethodName(m); return fullName ? language.TypeToString(new TypeDefinition(member.Module, metadata.GetMethodDefinition(m.Handle).GetDeclaringType()), fullName) + "." + language.FormatMethodName(m) : language.FormatMethodName(m);
case EventDefinition e: case EventDefinition e:
return fullName ? language.TypeToString(e.DeclaringType, fullName) + "." + language.FormatEventName(e) : language.FormatEventName(e); return fullName ? language.TypeToString(new TypeDefinition(member.Module, metadata.GetMethodDefinition(metadata.GetEventDefinition(e.Handle).GetAccessors().GetAny()).GetDeclaringType()), fullName) + "." + language.FormatEventName(e) : language.FormatEventName(e);
default: default:
throw new NotSupportedException(member?.GetType() + " not supported!"); throw new NotSupportedException(member?.GetType() + " not supported!");
} }
} }
void Add<T>(IEnumerable<T> items, TypeDefinition type, Language language, Action<SearchResult> addResult, Func<T, Language, bool> matcher, Func<T, ImageSource> image) where T : IMemberReference void Add<T>(IEnumerable<T> items, TypeDefinition type, Language language, Action<SearchResult> addResult, Func<T, Language, bool> matcher, Func<T, ImageSource> image) where T : IMetadataEntity
{ {
foreach (var item in items) { foreach (var item in items) {
if (matcher(item, language)) { if (matcher(item, language)) {
@ -149,7 +174,7 @@ namespace ICSharpCode.ILSpy
Member = item, Member = item,
Fitness = CalculateFitness(item), Fitness = CalculateFitness(item),
Image = image(item), Image = image(item),
Name = GetLanguageSpecificName(language, (IMemberDefinition)item), Name = GetLanguageSpecificName(language, item),
LocationImage = TypeTreeNode.GetIcon(type), LocationImage = TypeTreeNode.GetIcon(type),
Location = language.TypeToString(type, includeNamespace: true) Location = language.TypeToString(type, includeNamespace: true)
}); });
@ -159,19 +184,21 @@ namespace ICSharpCode.ILSpy
public virtual void Search(TypeDefinition type, Language language, Action<SearchResult> addResult) public virtual void Search(TypeDefinition type, Language language, Action<SearchResult> addResult)
{ {
Add(type.Fields, type, language, addResult, IsMatch, FieldTreeNode.GetIcon); var td = type.This();
Add(type.Properties, type, language, addResult, IsMatch, p => PropertyTreeNode.GetIcon(p)); var metadata = type.Module.GetMetadataReader();
Add(type.Events, type, language, addResult, IsMatch, EventTreeNode.GetIcon); Add(td.GetFields().Select(f => new FieldDefinition(type.Module, f)), type, language, addResult, IsMatch, FieldTreeNode.GetIcon);
Add(type.Methods.Where(NotSpecialMethod), type, language, addResult, IsMatch, MethodTreeNode.GetIcon); Add(td.GetProperties().Select(p => new PropertyDefinition(type.Module, p)), type, language, addResult, IsMatch, p => PropertyTreeNode.GetIcon(p));
Add(td.GetEvents().Select(e => new EventDefinition(type.Module, e)), type, language, addResult, IsMatch, EventTreeNode.GetIcon);
Add(td.GetMethods().Where(m => NotSpecialMethod(m, metadata)).Select(m => new MethodDefinition(type.Module, m)), type, language, addResult, IsMatch, MethodTreeNode.GetIcon);
foreach (TypeDefinition nestedType in type.NestedTypes) { foreach (var nestedType in td.GetNestedTypes()) {
Search(nestedType, language, addResult); Search(new TypeDefinition(type.Module, nestedType), language, addResult);
} }
} }
bool NotSpecialMethod(MethodDefinition arg) bool NotSpecialMethod(SRM.MethodDefinitionHandle method, SRM.MetadataReader metadata)
{ {
return (arg.GetMethodSemanticsAttributes() & ( return (method.GetMethodSemanticsAttributes(metadata) & (
MethodSemanticsAttributes.Setter MethodSemanticsAttributes.Setter
| MethodSemanticsAttributes.Getter | MethodSemanticsAttributes.Getter
| MethodSemanticsAttributes.Adder | MethodSemanticsAttributes.Adder
@ -233,17 +260,19 @@ namespace ICSharpCode.ILSpy
protected override bool IsMatch(PropertyDefinition property, Language language) protected override bool IsMatch(PropertyDefinition property, Language language)
{ {
return MethodIsLiteralMatch(property.GetMethod) || MethodIsLiteralMatch(property.SetMethod); var accessors = property.This().GetAccessors();
return MethodIsLiteralMatch(accessors.Getter, property.Module) || MethodIsLiteralMatch(accessors.Setter, property.Module);
} }
protected override bool IsMatch(EventDefinition ev, Language language) protected override bool IsMatch(EventDefinition ev, Language language)
{ {
return MethodIsLiteralMatch(ev.AddMethod) || MethodIsLiteralMatch(ev.RemoveMethod) || MethodIsLiteralMatch(ev.InvokeMethod); var accessors = ev.This().GetAccessors();
return MethodIsLiteralMatch(accessors.Adder, ev.Module) || MethodIsLiteralMatch(accessors.Remover, ev.Module) || MethodIsLiteralMatch(accessors.Raiser, ev.Module);
} }
protected override bool IsMatch(MethodDefinition m, Language language) protected override bool IsMatch(MethodDefinition m, Language language)
{ {
return MethodIsLiteralMatch(m); return MethodIsLiteralMatch(m.Handle, m.Module);
} }
bool IsLiteralMatch(object val) bool IsLiteralMatch(object val)
@ -267,11 +296,15 @@ namespace ICSharpCode.ILSpy
} }
} }
bool MethodIsLiteralMatch(MethodDefinition m) bool MethodIsLiteralMatch(SRM.MethodDefinitionHandle m, PEFile module)
{ {
if (m == null || !m.HasBody) if (module == null)
return false;
var metadata = module.GetMetadataReader();
if (m.IsNil || !m.HasBody(metadata))
return false; return false;
var blob = m.Body.GetILReader(); var methodDefinition = metadata.GetMethodDefinition(m);
var blob = module.Reader.GetMethodBody(methodDefinition.RelativeVirtualAddress).GetILReader();
if (searchTermLiteralType == TypeCode.Int64) { if (searchTermLiteralType == TypeCode.Int64) {
long val = (long)searchTermLiteralValue; long val = (long)searchTermLiteralValue;
while (blob.RemainingBytes > 0) { while (blob.RemainingBytes > 0) {
@ -365,7 +398,7 @@ namespace ICSharpCode.ILSpy
return true; return true;
break; break;
case ILOpCode.Ldstr: case ILOpCode.Ldstr:
if ((string)searchTermLiteralValue == ILParser.DecodeUserString(ref blob, m.Module)) if ((string)searchTermLiteralValue == ILParser.DecodeUserString(ref blob, module))
return true; return true;
break; break;
} }
@ -377,7 +410,7 @@ namespace ICSharpCode.ILSpy
ILParser.SkipOperand(ref blob, code); ILParser.SkipOperand(ref blob, code);
continue; continue;
} }
if (IsMatch(t => ILParser.DecodeUserString(ref blob, m.Module))) if (IsMatch(t => ILParser.DecodeUserString(ref blob, module)))
return true; return true;
} }
} }
@ -441,18 +474,20 @@ namespace ICSharpCode.ILSpy
{ {
if (MatchName(type, language)) { if (MatchName(type, language)) {
string name = language.TypeToString(type, includeNamespace: false); string name = language.TypeToString(type, includeNamespace: false);
var metadata = type.Module.GetMetadataReader();
var declaringType = type.This().GetDeclaringType();
addResult(new SearchResult { addResult(new SearchResult {
Member = type, Member = type,
Fitness = CalculateFitness(type), Fitness = CalculateFitness(type),
Image = TypeTreeNode.GetIcon(type), Image = TypeTreeNode.GetIcon(type),
Name = name, Name = name,
LocationImage = type.DeclaringType != null ? TypeTreeNode.GetIcon(type.DeclaringType) : Images.Namespace, LocationImage = !declaringType.IsNil ? TypeTreeNode.GetIcon(new TypeDefinition(type.Module, declaringType)) : Images.Namespace,
Location = type.DeclaringType != null ? language.TypeToString(type.DeclaringType, includeNamespace: true) : type.Namespace Location = !declaringType.IsNil ? language.TypeToString(new TypeDefinition(type.Module, declaringType), includeNamespace: true) : type.Handle.GetFullTypeName(metadata).TopLevelTypeName.Namespace
}); });
} }
foreach (TypeDefinition nestedType in type.NestedTypes) { foreach (var nestedType in type.This().GetNestedTypes()) {
Search(nestedType, language, addResult); Search(new TypeDefinition(type.Module, nestedType), language, addResult);
} }
} }
} }
@ -469,14 +504,15 @@ namespace ICSharpCode.ILSpy
if (MatchName(type, language)) if (MatchName(type, language))
{ {
string name = language.TypeToString(type, includeNamespace: false); string name = language.TypeToString(type, includeNamespace: false);
addResult(new SearchResult var metadata = type.Module.GetMetadataReader();
{ var declaringType = type.This().GetDeclaringType();
addResult(new SearchResult {
Member = type, Member = type,
Image = TypeTreeNode.GetIcon(type), Image = TypeTreeNode.GetIcon(type),
Fitness = CalculateFitness(type), Fitness = CalculateFitness(type),
Name = name, Name = name,
LocationImage = !type.DeclaringType.IsNil ? TypeTreeNode.GetIcon(type.DeclaringType) : Images.Namespace, LocationImage = !declaringType.IsNil ? TypeTreeNode.GetIcon(new TypeDefinition(type.Module, declaringType)) : Images.Namespace,
Location = !type.DeclaringType.IsNil ? language.TypeToString(type.DeclaringType, includeNamespace: true) : type.Namespace Location = !declaringType.IsNil ? language.TypeToString(new TypeDefinition(type.Module, declaringType), includeNamespace: true) : type.Handle.GetFullTypeName(metadata).TopLevelTypeName.Namespace
}); });
} }

18
ILSpy/TextView/DecompilerTextView.cs

@ -45,11 +45,11 @@ using ICSharpCode.AvalonEdit.Search;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.Documentation; using ICSharpCode.Decompiler.Documentation;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.AvalonEdit; using ICSharpCode.ILSpy.AvalonEdit;
using ICSharpCode.ILSpy.Options; using ICSharpCode.ILSpy.Options;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;
using Microsoft.Win32; using Microsoft.Win32;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.TextView namespace ICSharpCode.ILSpy.TextView
{ {
@ -206,20 +206,18 @@ namespace ICSharpCode.ILSpy.TextView
} }
} }
return $"{code.Name} (0x{code.Code:x})"; return $"{code.Name} (0x{code.Code:x})";
} else if (segment.Reference is MemberReference) { } else if (segment.Reference is Entity entity) {
MemberReference mr = (MemberReference)segment.Reference;
// if possible, resolve the reference // if possible, resolve the reference
if (mr is TypeReference) { if (entity.IsType()) {
mr = ((TypeReference)mr).Resolve() ?? mr; var td = entity.ResolveAsType();
} else if (mr is MethodReference) { if (!td.IsNil) entity = td;
mr = ((MethodReference)mr).Resolve() ?? mr;
} }
XmlDocRenderer renderer = new XmlDocRenderer(); XmlDocRenderer renderer = new XmlDocRenderer();
//renderer.AppendText(MainWindow.Instance.CurrentLanguage.GetTooltip(mr)); renderer.AppendText(MainWindow.Instance.CurrentLanguage.GetTooltip(entity));
try { try {
XmlDocumentationProvider docProvider = XmlDocLoader.LoadDocumentation(mr.Module); var docProvider = entity.Module.DocumentationResolver.GetProvider(); // TODO implement proper API
if (docProvider != null) { if (docProvider != null) {
string documentation = docProvider.GetDocumentation(XmlDocKeyProvider.GetKey(mr)); string documentation = docProvider.GetDocumentation(XmlDocKeyProvider.GetKey(entity));
if (documentation != null) { if (documentation != null) {
renderer.AppendText(Environment.NewLine); renderer.AppendText(Environment.NewLine);
renderer.AddXmlDocumentation(documentation); renderer.AddXmlDocumentation(documentation);

1
ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs

@ -55,7 +55,6 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
yield break; yield break;
foreach (PropertyDefinition property in type.Properties) { foreach (PropertyDefinition property in type.Properties) {
analyzedProperty.
if (TypesHierarchyHelpers.IsBaseProperty(analyzedProperty, property)) { if (TypesHierarchyHelpers.IsBaseProperty(analyzedProperty, property)) {
MethodDefinition anyAccessor = property.GetMethod ?? property.SetMethod; MethodDefinition anyAccessor = property.GetMethod ?? property.SetMethod;
bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot; bool hidesParent = !anyAccessor.IsVirtual ^ anyAccessor.IsNewSlot;

4
ILSpy/TreeNodes/Analyzer/AnalyzerEntityTreeNode.cs

@ -17,7 +17,7 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System.Collections.Generic; using System.Collections.Generic;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.TreeView; using ICSharpCode.TreeView;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
@ -27,7 +27,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
/// </summary> /// </summary>
public abstract class AnalyzerEntityTreeNode : AnalyzerTreeNode, IMemberTreeNode public abstract class AnalyzerEntityTreeNode : AnalyzerTreeNode, IMemberTreeNode
{ {
public abstract IMemberReference Member { get; } public abstract IMetadataEntity Member { get; }
public override void ActivateItem(System.Windows.RoutedEventArgs e) public override void ActivateItem(System.Windows.RoutedEventArgs e)
{ {

19
ILSpy/TreeNodes/AssemblyListTreeNode.cs

@ -25,7 +25,7 @@ using System.Linq;
using System.Reflection.PortableExecutable; using System.Reflection.PortableExecutable;
using System.Windows; using System.Windows;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.TreeView; using ICSharpCode.TreeView;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
@ -210,8 +210,9 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary> /// </summary>
public TypeTreeNode FindTypeNode(TypeDefinition def) public TypeTreeNode FindTypeNode(TypeDefinition def)
{ {
if (!def.DeclaringType.IsNil) { var declaringType = def.This().GetDeclaringType();
TypeTreeNode decl = FindTypeNode(def.DeclaringType); if (!declaringType.IsNil) {
TypeTreeNode decl = FindTypeNode(new TypeDefinition(def.Module, declaringType));
if (decl != null) { if (decl != null) {
decl.EnsureLazyChildren(); decl.EnsureLazyChildren();
return decl.Children.OfType<TypeTreeNode>().FirstOrDefault(t => t.TypeDefinition == def && !t.IsHidden); return decl.Children.OfType<TypeTreeNode>().FirstOrDefault(t => t.TypeDefinition == def && !t.IsHidden);
@ -231,7 +232,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary> /// </summary>
public ILSpyTreeNode FindMethodNode(MethodDefinition def) public ILSpyTreeNode FindMethodNode(MethodDefinition def)
{ {
TypeTreeNode typeNode = FindTypeNode(def.DeclaringType); TypeTreeNode typeNode = FindTypeNode(new TypeDefinition(def.Module, def.This().GetDeclaringType()));
if (typeNode == null) if (typeNode == null)
return null; return null;
typeNode.EnsureLazyChildren(); typeNode.EnsureLazyChildren();
@ -266,7 +267,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary> /// </summary>
public FieldTreeNode FindFieldNode(FieldDefinition def) public FieldTreeNode FindFieldNode(FieldDefinition def)
{ {
TypeTreeNode typeNode = FindTypeNode(def.DeclaringType); TypeTreeNode typeNode = FindTypeNode(new TypeDefinition(def.Module, def.This().GetDeclaringType()));
if (typeNode == null) if (typeNode == null)
return null; return null;
typeNode.EnsureLazyChildren(); typeNode.EnsureLazyChildren();
@ -279,7 +280,9 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary> /// </summary>
public PropertyTreeNode FindPropertyNode(PropertyDefinition def) public PropertyTreeNode FindPropertyNode(PropertyDefinition def)
{ {
TypeTreeNode typeNode = FindTypeNode(def.DeclaringType); var metadata = def.Module.GetMetadataReader();
var accessor = metadata.GetMethodDefinition(metadata.GetPropertyDefinition(def.Handle).GetAccessors().GetAny());
TypeTreeNode typeNode = FindTypeNode(new TypeDefinition(def.Module, accessor.GetDeclaringType()));
if (typeNode == null) if (typeNode == null)
return null; return null;
typeNode.EnsureLazyChildren(); typeNode.EnsureLazyChildren();
@ -292,7 +295,9 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary> /// </summary>
public EventTreeNode FindEventNode(EventDefinition def) public EventTreeNode FindEventNode(EventDefinition def)
{ {
TypeTreeNode typeNode = FindTypeNode(def.DeclaringType); var metadata = def.Module.GetMetadataReader();
var accessor = metadata.GetMethodDefinition(metadata.GetEventDefinition(def.Handle).GetAccessors().GetAny());
TypeTreeNode typeNode = FindTypeNode(new TypeDefinition(def.Module, accessor.GetDeclaringType()));
if (typeNode == null) if (typeNode == null)
return null; return null;
typeNode.EnsureLazyChildren(); typeNode.EnsureLazyChildren();

12
ILSpy/TreeNodes/AssemblyTreeNode.cs

@ -26,7 +26,7 @@ using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Documents; using System.Windows.Documents;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TextView;
using ICSharpCode.TreeView; using ICSharpCode.TreeView;
using Microsoft.Win32; using Microsoft.Win32;
@ -163,11 +163,13 @@ namespace ICSharpCode.ILSpy.TreeNodes
foreach (NamespaceTreeNode ns in namespaces.Values) { foreach (NamespaceTreeNode ns in namespaces.Values) {
ns.Children.Clear(); ns.Children.Clear();
} }
foreach (TypeDefinition type in metadata.GetTopLevelTypeDefinitions().Select(td => new TypeDefinition(module, td)).OrderBy(t => t.FullName.ToString(), NaturalStringComparer.Instance)) { foreach (var typeHandle in metadata.GetTopLevelTypeDefinitions().OrderBy(t => t.GetFullTypeName(metadata).ToString(), NaturalStringComparer.Instance)) {
NamespaceTreeNode ns; NamespaceTreeNode ns;
if (!namespaces.TryGetValue(type.Namespace, out ns)) { var type = new TypeDefinition(module, typeHandle);
ns = new NamespaceTreeNode(type.Namespace); var namespaceString = metadata.GetString(metadata.GetTypeDefinition(typeHandle).Namespace);
namespaces[type.Namespace] = ns; if (!namespaces.TryGetValue(namespaceString, out ns)) {
ns = new NamespaceTreeNode(namespaceString);
namespaces[namespaceString] = ns;
} }
TypeTreeNode node = new TypeTreeNode(type, this); TypeTreeNode node = new TypeTreeNode(type, this);
typeDict[type] = node; typeDict[type] = node;

41
ILSpy/TreeNodes/BaseTypesEntryNode.cs

@ -19,41 +19,46 @@
using System; using System;
using System.Linq; using System.Linq;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.TreeView; using ICSharpCode.TreeView;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
sealed class BaseTypesEntryNode : ILSpyTreeNode, IMemberTreeNode sealed class BaseTypesEntryNode : ILSpyTreeNode, IMemberTreeNode
{ {
private readonly ITypeReference tr; readonly Entity tr;
private TypeDefinition def; TypeDefinition td;
private readonly bool isInterface; readonly bool isInterface;
public BaseTypesEntryNode(ITypeReference tr, bool isInterface) public BaseTypesEntryNode(Entity entity, bool isInterface)
{ {
this.tr = tr ?? throw new ArgumentNullException(nameof(tr)); if (entity.IsNil) throw new ArgumentNullException(nameof(entity));
this.def = tr.GetDefinition(); this.tr = entity;
this.td = tr.ResolveAsType();
this.isInterface = isInterface; this.isInterface = isInterface;
this.LazyLoading = true; this.LazyLoading = true;
} }
public override bool ShowExpander public override bool ShowExpander
{ {
get { return !def.IsNil && (def.BaseType != null || def.HasInterfaces); } get {
if (td.IsNil) return false;
var typeDef = td.This();
return !typeDef.BaseType.IsNil || typeDef.GetInterfaceImplementations().Any();
}
} }
public override object Text public override object Text
{ {
get { return def.FullName + def.Handle.ToSuffixString(); } get { return tr.Handle.GetFullTypeName(tr.Module.GetMetadataReader()) + tr.Handle.ToSuffixString(); }
} }
public override object Icon public override object Icon
{ {
get get
{ {
if (def != null) if (td != null)
return TypeTreeNode.GetIcon(def); return TypeTreeNode.GetIcon(td);
else else
return isInterface ? Images.Interface : Images.Class; return isInterface ? Images.Interface : Images.Class;
} }
@ -61,20 +66,20 @@ namespace ICSharpCode.ILSpy.TreeNodes
protected override void LoadChildren() protected override void LoadChildren()
{ {
if (def != null) if (td != null)
BaseTypesTreeNode.AddBaseTypes(this.Children, def); BaseTypesTreeNode.AddBaseTypes(this.Children, td);
} }
public override void ActivateItem(System.Windows.RoutedEventArgs e) public override void ActivateItem(System.Windows.RoutedEventArgs e)
{ {
// on item activation, try to resolve once again (maybe the user loaded the assembly in the meantime) // on item activation, try to resolve once again (maybe the user loaded the assembly in the meantime)
if (def == null) { if (td.IsNil) {
def = tr.GetDefinition(); td = tr.ResolveAsType();
if (def != null) if (!td.IsNil)
this.LazyLoading = true; this.LazyLoading = true;
// re-load children // re-load children
} }
e.Handled = ActivateItem(this, def); e.Handled = ActivateItem(this, td);
} }
internal static bool ActivateItem(SharpTreeNode node, TypeDefinition def) internal static bool ActivateItem(SharpTreeNode node, TypeDefinition def)
@ -94,6 +99,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
language.WriteCommentLine(output, language.TypeToString(tr, true)); language.WriteCommentLine(output, language.TypeToString(tr, true));
} }
IMemberReference IMemberTreeNode.Member => tr; IMetadataEntity IMemberTreeNode.Member => tr;
} }
} }

13
ILSpy/TreeNodes/BaseTypesTreeNode.cs

@ -19,7 +19,7 @@
using System; using System;
using System.Windows.Threading; using System.Windows.Threading;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.TreeView; using ICSharpCode.TreeView;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
@ -48,10 +48,13 @@ namespace ICSharpCode.ILSpy.TreeNodes
internal static void AddBaseTypes(SharpTreeNodeCollection children, TypeDefinition type) internal static void AddBaseTypes(SharpTreeNodeCollection children, TypeDefinition type)
{ {
if (type.BaseType != null) var metadata = type.Module.GetMetadataReader();
children.Add(new BaseTypesEntryNode(type.BaseType, false)); var def = type.This();
foreach (var i in type.Interfaces) { if (!def.BaseType.IsNil)
children.Add(new BaseTypesEntryNode(i, true)); children.Add(new BaseTypesEntryNode(new Entity(type.Module, def.BaseType), false));
foreach (var i in def.GetInterfaceImplementations()) {
var interfaceImpl = metadata.GetInterfaceImplementation(i);
children.Add(new BaseTypesEntryNode(new Entity(type.Module, interfaceImpl.Interface), true));
} }
} }

16
ILSpy/TreeNodes/DerivedTypesEntryNode.cs

@ -21,7 +21,7 @@ using System.Reflection;
using System.Reflection.PortableExecutable; using System.Reflection.PortableExecutable;
using System.Threading; using System.Threading;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
@ -41,12 +41,12 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override bool ShowExpander public override bool ShowExpander
{ {
get { return !type.HasFlag(TypeAttributes.Sealed) && base.ShowExpander; } get { return !type.This().HasFlag(TypeAttributes.Sealed) && base.ShowExpander; }
} }
public override object Text public override object Text
{ {
get { return type.FullName + type.Handle.ToSuffixString(); } get { return type.Handle.GetFullTypeName(type.Module.GetMetadataReader()) + type.Handle.ToSuffixString(); }
} }
public override object Icon public override object Icon
@ -58,8 +58,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
{ {
if (!settings.ShowInternalApi && !IsPublicAPI) if (!settings.ShowInternalApi && !IsPublicAPI)
return FilterResult.Hidden; return FilterResult.Hidden;
if (settings.SearchTermMatches(type.Name)) { var metadata = type.Module.GetMetadataReader();
if (!type.DeclaringType.IsNil && !settings.Language.ShowMember(type)) var typeDefinition = metadata.GetTypeDefinition(type.Handle);
if (settings.SearchTermMatches(metadata.GetString(typeDefinition.Name))) {
if (!typeDefinition.GetDeclaringType().IsNil && !settings.Language.ShowMember(type))
return FilterResult.Hidden; return FilterResult.Hidden;
else else
return FilterResult.Match; return FilterResult.Match;
@ -69,7 +71,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override bool IsPublicAPI { public override bool IsPublicAPI {
get { get {
switch (type.Attributes & TypeAttributes.VisibilityMask) { switch (type.This().Attributes & TypeAttributes.VisibilityMask) {
case TypeAttributes.Public: case TypeAttributes.Public:
case TypeAttributes.NestedPublic: case TypeAttributes.NestedPublic:
case TypeAttributes.NestedFamily: case TypeAttributes.NestedFamily:
@ -102,6 +104,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
language.WriteCommentLine(output, language.TypeToString(type, true)); language.WriteCommentLine(output, language.TypeToString(type, true));
} }
IMemberReference IMemberTreeNode.Member => type; IMetadataEntity IMemberTreeNode.Member => type;
} }
} }

23
ILSpy/TreeNodes/DerivedTypesTreeNode.cs

@ -18,13 +18,14 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Reflection.PortableExecutable; using System.Reflection.PortableExecutable;
using System.Threading; using System.Threading;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using static System.Reflection.Metadata.PEReaderExtensions; using SRM = System.Reflection.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
@ -70,16 +71,18 @@ namespace ICSharpCode.ILSpy.TreeNodes
internal static IEnumerable<DerivedTypesEntryNode> FindDerivedTypes(TypeDefinition type, PEFile[] assemblies, CancellationToken cancellationToken) internal static IEnumerable<DerivedTypesEntryNode> FindDerivedTypes(TypeDefinition type, PEFile[] assemblies, CancellationToken cancellationToken)
{ {
foreach (var module in assemblies) { foreach (var module in assemblies) {
var reader = module.GetMetadataReader(); var metadata = module.GetMetadataReader();
foreach (var h in TreeTraversal.PreOrder(reader.GetTopLevelTypeDefinitions(), t => reader.GetTypeDefinition(t).GetNestedTypes())) { foreach (var h in TreeTraversal.PreOrder(metadata.GetTopLevelTypeDefinitions(), t => metadata.GetTypeDefinition(t).GetNestedTypes())) {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
var td = new TypeDefinition(module, h); var td = new TypeDefinition(module, h);
if (type.IsInterface && td.HasInterfaces) { var typeDefinition = metadata.GetTypeDefinition(h);
foreach (var iface in td.Interfaces) { if ((typeDefinition.Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface) {
if (IsSameType(iface, type)) foreach (var iface in typeDefinition.GetInterfaceImplementations()) {
var ifaceImpl = metadata.GetInterfaceImplementation(iface);
if (IsSameType(metadata, ifaceImpl.Interface, type.Handle))
yield return new DerivedTypesEntryNode(td, assemblies); yield return new DerivedTypesEntryNode(td, assemblies);
} }
} else if (!type.IsInterface && td.BaseType != null && IsSameType(td.BaseType, type)) { } else if (!typeDefinition.BaseType.IsNil && IsSameType(metadata, typeDefinition.BaseType, type.Handle)) {
yield return new DerivedTypesEntryNode(td, assemblies); yield return new DerivedTypesEntryNode(td, assemblies);
} }
} }
@ -87,10 +90,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
yield break; yield break;
} }
static bool IsSameType(ITypeReference typeRef, TypeDefinition type) static bool IsSameType(SRM.MetadataReader metadata, SRM.EntityHandle typeRef, SRM.TypeDefinitionHandle type)
{ {
// FullName contains only namespace, name and type parameter count, therefore this should suffice. // FullName contains only namespace, name and type parameter count, therefore this should suffice.
return typeRef.FullName == type.FullName; return typeRef.GetFullTypeName(metadata) == type.GetFullTypeName(metadata);
} }
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)

65
ILSpy/TreeNodes/EventTreeNode.cs

@ -19,9 +19,10 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using SRM = System.Reflection.Metadata;
using System.Windows.Media; using System.Windows.Media;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
@ -35,36 +36,51 @@ namespace ICSharpCode.ILSpy.TreeNodes
if (ev.IsNil) if (ev.IsNil)
throw new ArgumentNullException(nameof(ev)); throw new ArgumentNullException(nameof(ev));
this.EventDefinition = ev; this.EventDefinition = ev;
var metadata = ev.Module.GetMetadataReader();
if (!ev.AddMethod.IsNil) var eventDefinition = metadata.GetEventDefinition(ev.Handle);
this.Children.Add(new MethodTreeNode(ev.AddMethod)); var accessors = eventDefinition.GetAccessors();
if (!ev.RemoveMethod.IsNil) if (!accessors.Adder.IsNil)
this.Children.Add(new MethodTreeNode(ev.RemoveMethod)); this.Children.Add(new MethodTreeNode(new MethodDefinition(ev.Module, accessors.Adder)));
if (!ev.InvokeMethod.IsNil) if (!accessors.Remover.IsNil)
this.Children.Add(new MethodTreeNode(ev.InvokeMethod)); this.Children.Add(new MethodTreeNode(new MethodDefinition(ev.Module, accessors.Remover)));
foreach (var m in ev.OtherMethods) if (!accessors.Raiser.IsNil)
this.Children.Add(new MethodTreeNode(m)); this.Children.Add(new MethodTreeNode(new MethodDefinition(ev.Module, accessors.Raiser)));
//foreach (var m in ev.OtherMethods)
// this.Children.Add(new MethodTreeNode(m));
} }
public EventDefinition EventDefinition { get; } public EventDefinition EventDefinition { get; }
public override object Text => GetText(EventDefinition, this.Language) + EventDefinition.Handle.ToSuffixString(); public override object Text => GetText(EventDefinition, this.Language) + EventDefinition.Handle.ToSuffixString();
public static object GetText(EventDefinition eventDef, Language language) public static object GetText(EventDefinition ev, Language language)
{ {
var eventType = eventDef.DecodeSignature(language.CreateSignatureTypeProvider(false), new GenericContext(eventDef.DeclaringType)); var metadata = ev.Module.GetMetadataReader();
return HighlightSearchMatch(eventDef.Name, " : " + eventType); var eventDefinition = metadata.GetEventDefinition(ev.Handle);
var accessors = eventDefinition.GetAccessors();
SRM.TypeDefinitionHandle declaringType;
if (!accessors.Adder.IsNil) {
declaringType = metadata.GetMethodDefinition(accessors.Adder).GetDeclaringType();
} else if (!accessors.Remover.IsNil) {
declaringType = metadata.GetMethodDefinition(accessors.Remover).GetDeclaringType();
} else {
declaringType = metadata.GetMethodDefinition(accessors.Raiser).GetDeclaringType();
}
var eventType = eventDefinition.DecodeSignature(metadata, language.CreateSignatureTypeProvider(false), new GenericContext(declaringType, ev.Module));
return HighlightSearchMatch(metadata.GetString(eventDefinition.Name), " : " + eventType);
} }
public override object Icon => GetIcon(EventDefinition); public override object Icon => GetIcon(EventDefinition);
public static ImageSource GetIcon(EventDefinition eventDef) public static ImageSource GetIcon(EventDefinition @event)
{ {
MethodDefinition accessor = eventDef.GetAccessors().FirstOrDefault().Method; var metadata = @event.Module.GetMetadataReader();
if (!accessor.IsNil) var accessor = metadata.GetEventDefinition(@event.Handle).GetAccessors().GetAny();
return Images.GetIcon(MemberIcon.Event, GetOverlayIcon(accessor.Attributes), accessor.HasFlag(MethodAttributes.Static)); if (!accessor.IsNil) {
else var accessorMethod = metadata.GetMethodDefinition(accessor);
return Images.GetIcon(MemberIcon.Event, AccessOverlayIcon.Public, false); return Images.GetIcon(MemberIcon.Event, GetOverlayIcon(accessorMethod.Attributes), accessorMethod.HasFlag(MethodAttributes.Static));
}
return Images.GetIcon(MemberIcon.Event, AccessOverlayIcon.Public, false);
} }
private static AccessOverlayIcon GetOverlayIcon(MethodAttributes methodAttributes) private static AccessOverlayIcon GetOverlayIcon(MethodAttributes methodAttributes)
@ -93,7 +109,8 @@ namespace ICSharpCode.ILSpy.TreeNodes
{ {
if (!settings.ShowInternalApi && !IsPublicAPI) if (!settings.ShowInternalApi && !IsPublicAPI)
return FilterResult.Hidden; return FilterResult.Hidden;
if (settings.SearchTermMatches(EventDefinition.Name) && settings.Language.ShowMember(EventDefinition)) var metadata = EventDefinition.Module.GetMetadataReader();
if (settings.SearchTermMatches(metadata.GetString(metadata.GetEventDefinition(EventDefinition.Handle).Name)) && settings.Language.ShowMember(EventDefinition))
return FilterResult.Match; return FilterResult.Match;
else else
return FilterResult.Hidden; return FilterResult.Hidden;
@ -106,9 +123,11 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override bool IsPublicAPI { public override bool IsPublicAPI {
get { get {
MethodDefinition accessor = EventDefinition.GetAccessors().FirstOrDefault().Method; var metadata = EventDefinition.Module.GetMetadataReader();
var accessor = metadata.GetEventDefinition(EventDefinition.Handle).GetAccessors().GetAny();
if (accessor.IsNil) return false; if (accessor.IsNil) return false;
switch (accessor.Attributes & MethodAttributes.MemberAccessMask) { var accessorMethod = metadata.GetMethodDefinition(accessor);
switch (accessorMethod.Attributes & MethodAttributes.MemberAccessMask) {
case MethodAttributes.Public: case MethodAttributes.Public:
case MethodAttributes.FamORAssem: case MethodAttributes.FamORAssem:
case MethodAttributes.Family: case MethodAttributes.Family:
@ -119,6 +138,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
} }
} }
IMemberReference IMemberTreeNode.Member => EventDefinition; IMetadataEntity IMemberTreeNode.Member => EventDefinition;
} }
} }

62
ILSpy/TreeNodes/FieldTreeNode.cs

@ -20,7 +20,8 @@ using System;
using System.Reflection; using System.Reflection;
using System.Windows.Media; using System.Windows.Media;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
@ -33,7 +34,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public FieldTreeNode(FieldDefinition field) public FieldTreeNode(FieldDefinition field)
{ {
if (field == null) if (field.IsNil)
throw new ArgumentNullException(nameof(field)); throw new ArgumentNullException(nameof(field));
this.FieldDefinition = field; this.FieldDefinition = field;
} }
@ -42,41 +43,47 @@ namespace ICSharpCode.ILSpy.TreeNodes
public static object GetText(FieldDefinition field, Language language) public static object GetText(FieldDefinition field, Language language)
{ {
string fieldType = field.DecodeSignature(language.CreateSignatureTypeProvider(false), new GenericContext(field.DeclaringType)); var metadata = field.Module.GetMetadataReader();
return HighlightSearchMatch(field.Name, " : " + fieldType); var fieldDefinition = metadata.GetFieldDefinition(field.Handle);
string fieldType = fieldDefinition.DecodeSignature(language.CreateSignatureTypeProvider(false), new GenericContext(fieldDefinition.GetDeclaringType(), field.Module));
return HighlightSearchMatch(metadata.GetString(fieldDefinition.Name), " : " + fieldType);
} }
public override object Icon => GetIcon(FieldDefinition); public override object Icon => GetIcon(FieldDefinition);
public static ImageSource GetIcon(FieldDefinition field) public static ImageSource GetIcon(FieldDefinition field)
{ {
if (field.DeclaringType.IsEnum && !field.HasFlag(FieldAttributes.SpecialName)) var metadata = field.Module.GetMetadataReader();
return Images.GetIcon(MemberIcon.EnumValue, GetOverlayIcon(field.Attributes), false); var fieldDefinition = metadata.GetFieldDefinition(field.Handle);
if (fieldDefinition.GetDeclaringType().IsEnum(metadata) && !fieldDefinition.HasFlag(FieldAttributes.SpecialName))
return Images.GetIcon(MemberIcon.EnumValue, GetOverlayIcon(fieldDefinition.Attributes), false);
if (field.HasFlag(FieldAttributes.Literal)) if (fieldDefinition.HasFlag(FieldAttributes.Literal))
return Images.GetIcon(MemberIcon.Literal, GetOverlayIcon(field.Attributes), false); return Images.GetIcon(MemberIcon.Literal, GetOverlayIcon(fieldDefinition.Attributes), false);
else if (field.HasFlag(FieldAttributes.InitOnly)) { else if (fieldDefinition.HasFlag(FieldAttributes.InitOnly)) {
if (IsDecimalConstant(field)) if (IsDecimalConstant(field))
return Images.GetIcon(MemberIcon.Literal, GetOverlayIcon(field.Attributes), false); return Images.GetIcon(MemberIcon.Literal, GetOverlayIcon(fieldDefinition.Attributes), false);
else else
return Images.GetIcon(MemberIcon.FieldReadOnly, GetOverlayIcon(field.Attributes), field.HasFlag(FieldAttributes.Static)); return Images.GetIcon(MemberIcon.FieldReadOnly, GetOverlayIcon(fieldDefinition.Attributes), fieldDefinition.HasFlag(FieldAttributes.Static));
} else } else
return Images.GetIcon(MemberIcon.Field, GetOverlayIcon(field.Attributes), field.HasFlag(FieldAttributes.Static)); return Images.GetIcon(MemberIcon.Field, GetOverlayIcon(fieldDefinition.Attributes), fieldDefinition.HasFlag(FieldAttributes.Static));
} }
private static bool IsDecimalConstant(FieldDefinition field) private static bool IsDecimalConstant(FieldDefinition field)
{ {
/*var fieldType = field.FieldType; var metadata = field.Module.GetMetadataReader();
if (fieldType.Name == "Decimal" && fieldType.Namespace == "System") { var fieldDefinition = metadata.GetFieldDefinition(field.Handle);
if (field.HasCustomAttributes) {
var attrs = field.CustomAttributes; var fieldType = fieldDefinition.DecodeSignature(new FullTypeNameSignatureDecoder(metadata), default(Unit));
for (int i = 0; i < attrs.Count; i++) { if (fieldType.ToString() == "System.Decimal") {
var attrType = attrs[i].AttributeType; var attrs = fieldDefinition.GetCustomAttributes();
if (attrType.Name == "DecimalConstantAttribute" && attrType.Namespace == "System.Runtime.CompilerServices") foreach (var h in attrs) {
return true; var attr = metadata.GetCustomAttribute(h);
} var attrType = attr.GetAttributeType(metadata).GetFullTypeName(metadata);
if (attrType.ToString() == "System.Runtime.CompilerServices.DecimalConstantAttribute")
return true;
} }
}*/ }
return false; return false;
} }
@ -106,7 +113,9 @@ namespace ICSharpCode.ILSpy.TreeNodes
{ {
if (!settings.ShowInternalApi && !IsPublicAPI) if (!settings.ShowInternalApi && !IsPublicAPI)
return FilterResult.Hidden; return FilterResult.Hidden;
if (settings.SearchTermMatches(FieldDefinition.Name) && settings.Language.ShowMember(FieldDefinition)) var metadata = FieldDefinition.Module.GetMetadataReader();
var fieldDefinition = metadata.GetFieldDefinition(FieldDefinition.Handle);
if (settings.SearchTermMatches(metadata.GetString(fieldDefinition.Name)) && settings.Language.ShowMember(FieldDefinition))
return FilterResult.Match; return FilterResult.Match;
else else
return FilterResult.Hidden; return FilterResult.Hidden;
@ -119,7 +128,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override bool IsPublicAPI { public override bool IsPublicAPI {
get { get {
switch (FieldDefinition.Attributes & FieldAttributes.FieldAccessMask) { var metadata = FieldDefinition.Module.GetMetadataReader();
var fieldDefinition = metadata.GetFieldDefinition(FieldDefinition.Handle);
switch (fieldDefinition.Attributes & FieldAttributes.FieldAccessMask) {
case FieldAttributes.Public: case FieldAttributes.Public:
case FieldAttributes.FamORAssem: case FieldAttributes.FamORAssem:
case FieldAttributes.Family: case FieldAttributes.Family:
@ -130,6 +142,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
} }
} }
IMemberReference IMemberTreeNode.Member => FieldDefinition; IMetadataEntity IMemberTreeNode.Member => FieldDefinition;
} }
} }

4
ILSpy/TreeNodes/IMemberTreeNode.cs

@ -16,7 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
@ -27,6 +27,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary> /// </summary>
public interface IMemberTreeNode public interface IMemberTreeNode
{ {
IMemberReference Member { get; } IMetadataEntity Member { get; }
} }
} }

39
ILSpy/TreeNodes/MethodTreeNode.cs

@ -24,7 +24,7 @@ using System.Text;
using System.Windows.Media; using System.Windows.Media;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using SRM = System.Reflection.Metadata; using SRM = System.Reflection.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
@ -48,8 +48,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
public static object GetText(MethodDefinition method, Language language) public static object GetText(MethodDefinition method, Language language)
{ {
var b = new StringBuilder(); var b = new StringBuilder();
var metadata = method.Module.GetMetadataReader();
var methodDefinition = metadata.GetMethodDefinition(method.Handle);
var signatureProvider = language.CreateSignatureTypeProvider(false); var signatureProvider = language.CreateSignatureTypeProvider(false);
var signature = method.DecodeSignature(signatureProvider, new GenericContext(method)); var signature = methodDefinition.DecodeSignature(signatureProvider, new GenericContext(method));
b.Append('('); b.Append('(');
for (int i = 0; i < signature.ParameterTypes.Length; i++) { for (int i = 0; i < signature.ParameterTypes.Length; i++) {
@ -62,7 +64,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
b.Append(", "); b.Append(", ");
b.Append("..."); b.Append("...");
} }
if (method.IsConstructor) { if (methodDefinition.IsConstructor(metadata)) {
b.Append(')'); b.Append(')');
} else { } else {
b.Append(") : "); b.Append(") : ");
@ -75,28 +77,33 @@ namespace ICSharpCode.ILSpy.TreeNodes
public static ImageSource GetIcon(MethodDefinition method) public static ImageSource GetIcon(MethodDefinition method)
{ {
if (method.HasFlag(MethodAttributes.SpecialName) && method.Name.StartsWith("op_", StringComparison.Ordinal)) { var metadata = method.Module.GetMetadataReader();
return Images.GetIcon(MemberIcon.Operator, GetOverlayIcon(method.Attributes), false); var methodDefinition = metadata.GetMethodDefinition(method.Handle);
if (methodDefinition.HasFlag(MethodAttributes.SpecialName) && method.Name.StartsWith("op_", StringComparison.Ordinal)) {
return Images.GetIcon(MemberIcon.Operator, GetOverlayIcon(methodDefinition.Attributes), false);
} }
if (method.IsExtensionMethod) { if (methodDefinition.IsExtensionMethod(metadata)) {
return Images.GetIcon(MemberIcon.ExtensionMethod, GetOverlayIcon(method.Attributes), false); return Images.GetIcon(MemberIcon.ExtensionMethod, GetOverlayIcon(methodDefinition.Attributes), false);
} }
if (method.HasFlag(MethodAttributes.SpecialName) && if (methodDefinition.HasFlag(MethodAttributes.SpecialName) &&
(method.Name == ".ctor" || method.Name == ".cctor")) { (method.Name == ".ctor" || method.Name == ".cctor")) {
return Images.GetIcon(MemberIcon.Constructor, GetOverlayIcon(method.Attributes), method.HasFlag(MethodAttributes.Static)); return Images.GetIcon(MemberIcon.Constructor, GetOverlayIcon(methodDefinition.Attributes), methodDefinition.HasFlag(MethodAttributes.Static));
} }
if (method.HasPInvokeInfo) if (methodDefinition.HasFlag(MethodAttributes.PinvokeImpl) && !methodDefinition.GetImport().Module.IsNil)
return Images.GetIcon(MemberIcon.PInvokeMethod, GetOverlayIcon(method.Attributes), true); return Images.GetIcon(MemberIcon.PInvokeMethod, GetOverlayIcon(methodDefinition.Attributes), true);
bool showAsVirtual = method.HasFlag(MethodAttributes.Virtual) && !(method.HasFlag(MethodAttributes.NewSlot) && method.HasFlag(MethodAttributes.Final)) && !method.DeclaringType.IsInterface; bool showAsVirtual = methodDefinition.HasFlag(MethodAttributes.Virtual)
&& !(methodDefinition.HasFlag(MethodAttributes.NewSlot) && methodDefinition.HasFlag(MethodAttributes.Final))
&& (metadata.GetTypeDefinition(methodDefinition.GetDeclaringType()).Attributes & TypeAttributes.ClassSemanticsMask) != TypeAttributes.Interface;
return Images.GetIcon( return Images.GetIcon(
showAsVirtual ? MemberIcon.VirtualMethod : MemberIcon.Method, showAsVirtual ? MemberIcon.VirtualMethod : MemberIcon.Method,
GetOverlayIcon(method.Attributes), GetOverlayIcon(methodDefinition.Attributes),
method.HasFlag(MethodAttributes.Static)); methodDefinition.HasFlag(MethodAttributes.Static));
} }
private static AccessOverlayIcon GetOverlayIcon(MethodAttributes methodAttributes) private static AccessOverlayIcon GetOverlayIcon(MethodAttributes methodAttributes)
@ -138,7 +145,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override bool IsPublicAPI { public override bool IsPublicAPI {
get { get {
switch (MethodDefinition.Attributes & MethodAttributes.MemberAccessMask) { switch (MethodDefinition.This().Attributes & MethodAttributes.MemberAccessMask) {
case MethodAttributes.Public: case MethodAttributes.Public:
case MethodAttributes.Family: case MethodAttributes.Family:
case MethodAttributes.FamORAssem: case MethodAttributes.FamORAssem:
@ -149,6 +156,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
} }
} }
IMemberReference IMemberTreeNode.Member => MethodDefinition; IMetadataEntity IMemberTreeNode.Member => MethodDefinition;
} }
} }

68
ILSpy/TreeNodes/PropertyTreeNode.cs

@ -20,7 +20,7 @@ using System;
using System.Reflection; using System.Reflection;
using System.Windows.Media; using System.Windows.Media;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using SRM = System.Reflection.Metadata; using SRM = System.Reflection.Metadata;
@ -38,16 +38,19 @@ namespace ICSharpCode.ILSpy.TreeNodes
if (property == null) if (property == null)
throw new ArgumentNullException(nameof(property)); throw new ArgumentNullException(nameof(property));
this.PropertyDefinition = property; this.PropertyDefinition = property;
var metadata = property.Module.GetMetadataReader();
var propertyDefinition = metadata.GetPropertyDefinition(property.Handle);
var accessors = propertyDefinition.GetAccessors();
using (LoadedAssembly.DisableAssemblyLoad()) { using (LoadedAssembly.DisableAssemblyLoad()) {
this.isIndexer = property.IsIndexer; this.isIndexer = property.Handle.HasMatchingDefaultMemberAttribute(property.Module, out _);
} }
if (!property.GetMethod.IsNil) if (!accessors.Getter.IsNil)
this.Children.Add(new MethodTreeNode(property.GetMethod)); this.Children.Add(new MethodTreeNode(new MethodDefinition(property.Module, accessors.Getter)));
if (!property.SetMethod.IsNil) if (!accessors.Setter.IsNil)
this.Children.Add(new MethodTreeNode(property.SetMethod)); this.Children.Add(new MethodTreeNode(new MethodDefinition(property.Module, accessors.Setter)));
foreach (var m in property.OtherMethods) /*foreach (var m in property.OtherMethods)
this.Children.Add(new MethodTreeNode(m)); this.Children.Add(new MethodTreeNode(m));*/
} }
public PropertyDefinition PropertyDefinition { get; } public PropertyDefinition PropertyDefinition { get; }
@ -56,29 +59,28 @@ namespace ICSharpCode.ILSpy.TreeNodes
public static object GetText(PropertyDefinition property, Language language, bool? isIndexer = null) public static object GetText(PropertyDefinition property, Language language, bool? isIndexer = null)
{ {
var metadata = property.Module.GetMetadataReader();
var propertyDefinition = metadata.GetPropertyDefinition(property.Handle);
string name = language.FormatPropertyName(property, isIndexer); string name = language.FormatPropertyName(property, isIndexer);
var signature = property.DecodeSignature(language.CreateSignatureTypeProvider(false), new GenericContext(property.DeclaringType)); var signature = propertyDefinition.DecodeSignature(language.CreateSignatureTypeProvider(false), new GenericContext(propertyDefinition.GetAccessors().GetAny(), property.Module));
var b = new System.Text.StringBuilder(); var b = new System.Text.StringBuilder();
if (property.HasParameters) var hasParameters = property.Handle.HasParameters(metadata);
{ if (hasParameters) {
b.Append('('); b.Append('(');
for (int i = 0; i < signature.ParameterTypes.Length; i++) for (int i = 0; i < signature.ParameterTypes.Length; i++) {
{
if (i > 0) if (i > 0)
b.Append(", "); b.Append(", ");
b.Append(signature.ParameterTypes[i]); b.Append(signature.ParameterTypes[i]);
} }
if (signature.Header.CallingConvention == SRM.SignatureCallingConvention.VarArgs) if (signature.Header.CallingConvention == SRM.SignatureCallingConvention.VarArgs) {
{ if (hasParameters)
if (property.HasParameters)
b.Append(", "); b.Append(", ");
b.Append("..."); b.Append("...");
} }
b.Append(") : "); b.Append(") : ");
} } else {
else
{
b.Append(" : "); b.Append(" : ");
} }
b.Append(signature.ReturnType); b.Append(signature.ReturnType);
@ -129,29 +131,35 @@ namespace ICSharpCode.ILSpy.TreeNodes
// in numeric order, so we can do an integer comparison of the masked attribute // in numeric order, so we can do an integer comparison of the masked attribute
int accessLevel = 0; int accessLevel = 0;
if (!property.GetMethod.IsNil) { var metadata = property.Module.GetMetadataReader();
int methodAccessLevel = (int)(property.GetMethod.Attributes & MethodAttributes.MemberAccessMask); var propertyDefinition = metadata.GetPropertyDefinition(property.Handle);
var accessors = propertyDefinition.GetAccessors();
if (!accessors.Getter.IsNil) {
var getter = metadata.GetMethodDefinition(accessors.Getter);
int methodAccessLevel = (int)(getter.Attributes & MethodAttributes.MemberAccessMask);
if (accessLevel < methodAccessLevel) { if (accessLevel < methodAccessLevel) {
accessLevel = methodAccessLevel; accessLevel = methodAccessLevel;
result = property.GetMethod.Attributes; result = getter.Attributes;
} }
} }
if (!property.SetMethod.IsNil) { if (!accessors.Setter.IsNil) {
int methodAccessLevel = (int)(property.SetMethod.Attributes & MethodAttributes.MemberAccessMask); var setter = metadata.GetMethodDefinition(accessors.Setter);
int methodAccessLevel = (int)(setter.Attributes & MethodAttributes.MemberAccessMask);
if (accessLevel < methodAccessLevel) { if (accessLevel < methodAccessLevel) {
accessLevel = methodAccessLevel; accessLevel = methodAccessLevel;
result = property.SetMethod.Attributes; result = setter.Attributes;
} }
} }
foreach (var m in property.OtherMethods) { /*foreach (var m in property.OtherMethods) {
int methodAccessLevel = (int)(m.Attributes & MethodAttributes.MemberAccessMask); int methodAccessLevel = (int)(m.Attributes & MethodAttributes.MemberAccessMask);
if (accessLevel < methodAccessLevel) { if (accessLevel < methodAccessLevel) {
accessLevel = methodAccessLevel; accessLevel = methodAccessLevel;
result = m.Attributes; result = m.Attributes;
} }
} }*/
return result; return result;
} }
@ -160,7 +168,9 @@ namespace ICSharpCode.ILSpy.TreeNodes
{ {
if (!settings.ShowInternalApi && !IsPublicAPI) if (!settings.ShowInternalApi && !IsPublicAPI)
return FilterResult.Hidden; return FilterResult.Hidden;
if (settings.SearchTermMatches(PropertyDefinition.Name) && settings.Language.ShowMember(PropertyDefinition)) var metadata = PropertyDefinition.Module.GetMetadataReader();
var propertyDefinition = metadata.GetPropertyDefinition(PropertyDefinition.Handle);
if (settings.SearchTermMatches(metadata.GetString(propertyDefinition.Name)) && settings.Language.ShowMember(PropertyDefinition))
return FilterResult.Match; return FilterResult.Match;
else else
return FilterResult.Hidden; return FilterResult.Hidden;
@ -184,6 +194,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
} }
} }
IMemberReference IMemberTreeNode.Member => PropertyDefinition; IMetadataEntity IMemberTreeNode.Member => PropertyDefinition;
} }
} }

2
ILSpy/TreeNodes/ResourceListTreeNode.cs

@ -20,7 +20,7 @@ using System;
using System.Linq; using System.Linq;
using System.Windows.Threading; using System.Windows.Threading;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {

2
ILSpy/TreeNodes/ResourceNodes/CursorResourceEntryNode.cs

@ -21,7 +21,7 @@ using System.ComponentModel.Composition;
using System.IO; using System.IO;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TextView;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes

2
ILSpy/TreeNodes/ResourceNodes/IResourceNodeFactory.cs

@ -16,7 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {

2
ILSpy/TreeNodes/ResourceNodes/IconResourceEntryNode.cs

@ -21,7 +21,7 @@ using System.ComponentModel.Composition;
using System.IO; using System.IO;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TextView;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes

2
ILSpy/TreeNodes/ResourceNodes/ImageListResourceEntryNode.cs

@ -20,7 +20,7 @@ using System.ComponentModel.Composition;
using System.Drawing; using System.Drawing;
using System.Windows.Forms; using System.Windows.Forms;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {

2
ILSpy/TreeNodes/ResourceNodes/ImageResourceEntryNode.cs

@ -21,7 +21,7 @@ using System.ComponentModel.Composition;
using System.IO; using System.IO;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TextView;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes

2
ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs

@ -23,7 +23,7 @@ using System.Text;
using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.AvalonEdit.Utils; using ICSharpCode.AvalonEdit.Utils;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TextView;
using Microsoft.Win32; using Microsoft.Win32;

2
ILSpy/TreeNodes/ResourceNodes/ResourcesFileTreeNode.cs

@ -26,7 +26,7 @@ using System.Linq;
using System.Resources; using System.Resources;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.Controls; using ICSharpCode.ILSpy.Controls;
using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TextView;
using Microsoft.Win32; using Microsoft.Win32;

2
ILSpy/TreeNodes/ResourceNodes/XamlResourceNode.cs

@ -22,7 +22,7 @@ using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;

2
ILSpy/TreeNodes/ResourceNodes/XmlResourceNode.cs

@ -22,7 +22,7 @@ using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.TreeNodes;

57
ILSpy/TreeNodes/TypeTreeNode.cs

@ -17,19 +17,21 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Windows.Media; using System.Windows.Media;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Dom; using ICSharpCode.Decompiler.Metadata;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes namespace ICSharpCode.ILSpy.TreeNodes
{ {
public sealed class TypeTreeNode : ILSpyTreeNode, IMemberTreeNode public sealed class TypeTreeNode : ILSpyTreeNode, IMemberTreeNode
{ {
readonly TypeDefinition typeDefinition; readonly TypeDefinition typeDefinition;
readonly SRM.TypeDefinition metadataTypeDefinition;
public TypeTreeNode(TypeDefinition typeDefinition, AssemblyTreeNode parentAssemblyNode) public TypeTreeNode(TypeDefinition typeDefinition, AssemblyTreeNode parentAssemblyNode)
{ {
@ -37,6 +39,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
throw new ArgumentNullException(nameof(typeDefinition)); throw new ArgumentNullException(nameof(typeDefinition));
this.ParentAssemblyNode = parentAssemblyNode ?? throw new ArgumentNullException(nameof(parentAssemblyNode)); this.ParentAssemblyNode = parentAssemblyNode ?? throw new ArgumentNullException(nameof(parentAssemblyNode));
this.typeDefinition = typeDefinition; this.typeDefinition = typeDefinition;
this.metadataTypeDefinition = typeDefinition.This();
this.LazyLoading = true; this.LazyLoading = true;
} }
@ -48,7 +51,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override bool IsPublicAPI { public override bool IsPublicAPI {
get { get {
switch (TypeDefinition.Attributes & TypeAttributes.VisibilityMask) { switch (metadataTypeDefinition.Attributes & TypeAttributes.VisibilityMask) {
case TypeAttributes.Public: case TypeAttributes.Public:
case TypeAttributes.NestedPublic: case TypeAttributes.NestedPublic:
case TypeAttributes.NestedFamily: case TypeAttributes.NestedFamily:
@ -64,7 +67,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
{ {
if (!settings.ShowInternalApi && !IsPublicAPI) if (!settings.ShowInternalApi && !IsPublicAPI)
return FilterResult.Hidden; return FilterResult.Hidden;
if (settings.SearchTermMatches(TypeDefinition.Name)) { if (settings.SearchTermMatches(TypeDefinition.Module.GetMetadataReader().GetString(metadataTypeDefinition.Name))) {
if (settings.Language.ShowMember(TypeDefinition)) if (settings.Language.ShowMember(TypeDefinition))
return FilterResult.Match; return FilterResult.Match;
else else
@ -76,26 +79,27 @@ namespace ICSharpCode.ILSpy.TreeNodes
protected override void LoadChildren() protected override void LoadChildren()
{ {
//if (TypeDefinition.BaseType != null || TypeDefinition.HasInterfaces) var metadata = TypeDefinition.Module.GetMetadataReader();
if (!metadataTypeDefinition.BaseType.IsNil || metadataTypeDefinition.GetInterfaceImplementations().Any())
this.Children.Add(new BaseTypesTreeNode(TypeDefinition)); this.Children.Add(new BaseTypesTreeNode(TypeDefinition));
if (!TypeDefinition.HasFlag(TypeAttributes.Sealed)) if (!metadataTypeDefinition.HasFlag(TypeAttributes.Sealed))
this.Children.Add(new DerivedTypesTreeNode(ParentAssemblyNode.AssemblyList, TypeDefinition)); this.Children.Add(new DerivedTypesTreeNode(ParentAssemblyNode.AssemblyList, TypeDefinition));
foreach (TypeDefinition nestedType in TypeDefinition.NestedTypes.OrderBy(m => m.Name, NaturalStringComparer.Instance)) { foreach (var nestedType in metadataTypeDefinition.GetNestedTypes().OrderBy(m => metadata.GetString(metadata.GetTypeDefinition(m).Name), NaturalStringComparer.Instance)) {
this.Children.Add(new TypeTreeNode(nestedType, ParentAssemblyNode)); this.Children.Add(new TypeTreeNode(new TypeDefinition(TypeDefinition.Module, nestedType), ParentAssemblyNode));
} }
foreach (FieldDefinition field in TypeDefinition.Fields.OrderBy(m => m.Name, NaturalStringComparer.Instance)) { foreach (var field in metadataTypeDefinition.GetFields().OrderBy(m => metadata.GetString(metadata.GetFieldDefinition(m).Name), NaturalStringComparer.Instance)) {
this.Children.Add(new FieldTreeNode(field)); this.Children.Add(new FieldTreeNode(new FieldDefinition(TypeDefinition.Module, field)));
} }
foreach (PropertyDefinition property in TypeDefinition.Properties.OrderBy(m => m.Name, NaturalStringComparer.Instance)) { foreach (var property in metadataTypeDefinition.GetProperties().OrderBy(m => metadata.GetString(metadata.GetPropertyDefinition(m).Name), NaturalStringComparer.Instance)) {
this.Children.Add(new PropertyTreeNode(property)); this.Children.Add(new PropertyTreeNode(new PropertyDefinition(TypeDefinition.Module, property)));
} }
foreach (EventDefinition ev in TypeDefinition.Events.OrderBy(m => m.Name, NaturalStringComparer.Instance)) { foreach (var ev in metadataTypeDefinition.GetEvents().OrderBy(m => metadata.GetString(metadata.GetEventDefinition(m).Name), NaturalStringComparer.Instance)) {
this.Children.Add(new EventTreeNode(ev)); this.Children.Add(new EventTreeNode(new EventDefinition(TypeDefinition.Module, ev)));
} }
foreach (MethodDefinition method in TypeDefinition.Methods.OrderBy(m => m.Name, NaturalStringComparer.Instance)) { foreach (var method in metadataTypeDefinition.GetMethods().OrderBy(m => metadata.GetString(metadata.GetMethodDefinition(m).Name), NaturalStringComparer.Instance)) {
if (method.GetMethodSemanticsAttributes() == 0) { if (method.GetMethodSemanticsAttributes(metadata) == 0) {
this.Children.Add(new MethodTreeNode(method)); this.Children.Add(new MethodTreeNode(new MethodDefinition(TypeDefinition.Module, method)));
} }
} }
} }
@ -119,17 +123,19 @@ namespace ICSharpCode.ILSpy.TreeNodes
static TypeIcon GetTypeIcon(TypeDefinition type) static TypeIcon GetTypeIcon(TypeDefinition type)
{ {
if (type.IsValueType) { var metadata = type.Module.GetMetadataReader();
if (type.IsEnum) var typeDefinition = metadata.GetTypeDefinition(type.Handle);
if (typeDefinition.IsValueType(metadata)) {
if (typeDefinition.IsEnum(metadata))
return TypeIcon.Enum; return TypeIcon.Enum;
else else
return TypeIcon.Struct; return TypeIcon.Struct;
} else { } else {
if (type.IsInterface) if ((typeDefinition.Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface)
return TypeIcon.Interface; return TypeIcon.Interface;
else if (type.IsDelegate) else if (typeDefinition.IsDelegate(metadata))
return TypeIcon.Delegate; return TypeIcon.Delegate;
else if (IsStaticClass(type)) else if (IsStaticClass(typeDefinition))
return TypeIcon.StaticClass; return TypeIcon.StaticClass;
else else
return TypeIcon.Class; return TypeIcon.Class;
@ -138,8 +144,9 @@ namespace ICSharpCode.ILSpy.TreeNodes
private static AccessOverlayIcon GetOverlayIcon(TypeDefinition type) private static AccessOverlayIcon GetOverlayIcon(TypeDefinition type)
{ {
var def = type.This();
AccessOverlayIcon overlay; AccessOverlayIcon overlay;
switch (type.Attributes & TypeAttributes.VisibilityMask) { switch (def.Attributes & TypeAttributes.VisibilityMask) {
case TypeAttributes.Public: case TypeAttributes.Public:
case TypeAttributes.NestedPublic: case TypeAttributes.NestedPublic:
overlay = AccessOverlayIcon.Public; overlay = AccessOverlayIcon.Public;
@ -164,11 +171,11 @@ namespace ICSharpCode.ILSpy.TreeNodes
return overlay; return overlay;
} }
private static bool IsStaticClass(TypeDefinition type) static bool IsStaticClass(SRM.TypeDefinition type)
{ {
return type.HasFlag(TypeAttributes.Sealed) && type.HasFlag(TypeAttributes.Abstract); return type.HasFlag(TypeAttributes.Sealed) && type.HasFlag(TypeAttributes.Abstract);
} }
IMemberReference IMemberTreeNode.Member => TypeDefinition; IMetadataEntity IMemberTreeNode.Member => TypeDefinition;
} }
} }

Loading…
Cancel
Save