Browse Source

Use TypeSystem for ILSpy UI:

Most important tree nodes and search ported,
Currently only ILLanguage is active
pull/1198/head
Siegfried Pammer 7 years ago
parent
commit
9acc372a68
  1. 5
      ICSharpCode.Decompiler/CSharp/Transforms/AddXmlDocumentationTransform.cs
  2. 15
      ICSharpCode.Decompiler/Disassembler/DomExtensions.cs
  3. 138
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  4. 591
      ICSharpCode.Decompiler/Documentation/XmlDocKeyProvider.cs
  5. 2
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  6. 402
      ICSharpCode.Decompiler/Metadata/Dom.cs
  7. 36
      ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs
  8. 50
      ICSharpCode.Decompiler/Metadata/MetadataResolver.cs
  9. 1
      ICSharpCode.Decompiler/Metadata/PEFile.cs
  10. 3
      ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs
  11. 25
      ICSharpCode.Decompiler/Output/ITextOutput.cs
  12. 3
      ICSharpCode.Decompiler/Output/PlainTextOutput.cs
  13. 82
      ICSharpCode.Decompiler/Output/TextTokenWriter.cs
  14. 3
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs
  15. 2
      ICSharpCode.Decompiler/TypeSystem/MetadataAssembly.cs
  16. 1
      ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs
  17. 34
      ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs
  18. 4
      ILSpy/AnalyzerTreeView.cs
  19. 2
      ILSpy/Commands/DecompileAllCommand.cs
  20. 14
      ILSpy/DebugSteps.xaml.cs
  21. 14
      ILSpy/ILSpy.csproj
  22. 3
      ILSpy/Languages/CodeMappingInfo.cs
  23. 46
      ILSpy/Languages/ILLanguage.cs
  24. 208
      ILSpy/Languages/Language.cs
  25. 2
      ILSpy/Languages/Languages.cs
  26. 20
      ILSpy/LoadedAssembly.cs
  27. 34
      ILSpy/MainWindow.xaml.cs
  28. 9
      ILSpy/SearchPane.cs
  29. 157
      ILSpy/SearchStrategies.cs
  30. 9
      ILSpy/TextView/DecompilerTextView.cs
  31. 13
      ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs
  32. 97
      ILSpy/TreeNodes/AssemblyListTreeNode.cs
  33. 16
      ILSpy/TreeNodes/AssemblyTreeNode.cs
  34. 55
      ILSpy/TreeNodes/BaseTypesEntryNode.cs
  35. 33
      ILSpy/TreeNodes/BaseTypesTreeNode.cs
  36. 52
      ILSpy/TreeNodes/CopyFullyQualifiedNameContextMenuEntry.cs
  37. 11
      ILSpy/TreeNodes/DerivedTypesEntryNode.cs
  38. 6
      ILSpy/TreeNodes/DerivedTypesTreeNode.cs
  39. 52
      ILSpy/TreeNodes/EventTreeNode.cs
  40. 54
      ILSpy/TreeNodes/FieldTreeNode.cs
  41. 6
      ILSpy/TreeNodes/IMemberTreeNode.cs
  42. 35
      ILSpy/TreeNodes/MethodTreeNode.cs
  43. 44
      ILSpy/TreeNodes/PropertyTreeNode.cs
  44. 111
      ILSpy/TreeNodes/TypeTreeNode.cs
  45. 9
      TestPlugin/CustomLanguage.cs

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

@ -41,10 +41,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -41,10 +41,9 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
if (xmldoc == null)
return;
foreach (var entity in rootNode.DescendantsAndSelf.OfType<EntityDeclaration>()) {
var handle = ((entity.GetSymbol() as IEntity)?.MetadataToken).Value;
if (handle.IsNil)
if (!(entity.GetSymbol() is IEntity symbolicEntity))
continue;
string doc = xmldoc.GetDocumentation(XmlDocKeyProvider.GetKey(context.TypeSystem.GetMetadata(), handle));
string doc = xmldoc.GetDocumentation(XmlDocKeyProvider.GetKey(symbolicEntity));
if (doc != null) {
InsertXmlDocumentation(entity, new StringReader(doc));
}

15
ICSharpCode.Decompiler/Disassembler/DomExtensions.cs

@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.Disassembler
switch (entity.Kind) {
case HandleKind.TypeDefinition: {
var td = metadata.GetTypeDefinition((TypeDefinitionHandle)entity);
output.WriteReference(td.GetFullTypeName(metadata).ToILNameString(), new Metadata.TypeDefinition(module, (TypeDefinitionHandle)entity));
output.WriteReference(module, entity, td.GetFullTypeName(metadata).ToILNameString());
break;
}
case HandleKind.TypeReference: {
@ -68,7 +68,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -68,7 +68,7 @@ namespace ICSharpCode.Decompiler.Disassembler
}
output.Write("]");
}
output.WriteReference(entity.GetFullTypeName(metadata).ToILNameString(), new Metadata.TypeReference(module, (TypeReferenceHandle)entity));
output.WriteReference(module, entity, entity.GetFullTypeName(metadata).ToILNameString());
break;
}
case HandleKind.TypeSpecification: {
@ -84,7 +84,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -84,7 +84,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write(' ');
((EntityHandle)fd.GetDeclaringType()).WriteTo(module, output, GenericContext.Empty, ILNameSyntax.TypeName);
output.Write("::");
output.WriteReference(DisassemblerHelpers.Escape(metadata.GetString(fd.Name)), new Metadata.FieldDefinition(module, (FieldDefinitionHandle)entity));
output.WriteReference(module, entity, DisassemblerHelpers.Escape(metadata.GetString(fd.Name)));
break;
}
case HandleKind.MethodDefinition: {
@ -106,11 +106,10 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -106,11 +106,10 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write("::");
}
bool isCompilerControlled = (md.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope;
var reference = new Metadata.MethodDefinition(module, (MethodDefinitionHandle)entity);
if (isCompilerControlled) {
output.WriteReference(DisassemblerHelpers.Escape(metadata.GetString(md.Name) + "$PST" + MetadataTokens.GetToken(entity).ToString("X8")), reference);
output.WriteReference(module, entity, DisassemblerHelpers.Escape(metadata.GetString(md.Name) + "$PST" + MetadataTokens.GetToken(entity).ToString("X8")));
} else {
output.WriteReference(DisassemblerHelpers.Escape(metadata.GetString(md.Name)), reference);
output.WriteReference(module, entity, DisassemblerHelpers.Escape(metadata.GetString(md.Name)));
}
var genericParameters = md.GetGenericParameters();
if (genericParameters.Count > 0) {
@ -174,7 +173,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -174,7 +173,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write(' ');
WriteParent(output, module, metadata, mr.Parent, genericContext, syntax);
output.Write("::");
output.WriteReference(DisassemblerHelpers.Escape(memberName), new Metadata.MemberReference(module, (MemberReferenceHandle)entity));
output.WriteReference(module, entity, DisassemblerHelpers.Escape(memberName));
output.Write("(");
for (int i = 0; i < methodSignature.ParameterTypes.Length; ++i) {
if (i > 0)
@ -191,7 +190,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -191,7 +190,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write(' ');
WriteParent(output, module, metadata, mr.Parent, genericContext, syntax);
output.Write("::");
output.WriteReference(DisassemblerHelpers.Escape(memberName), new Metadata.MemberReference(module, (MemberReferenceHandle)entity));
output.WriteReference(module, entity, DisassemblerHelpers.Escape(memberName));
break;
}
break;

138
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -125,25 +125,27 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -125,25 +125,27 @@ namespace ICSharpCode.Decompiler.Disassembler
public void DisassembleMethod(PEFile module, MethodDefinitionHandle handle)
{
var metadata = module.Metadata;
var genericContext = new GenericContext(handle, module);
// write method header
output.WriteDefinition(".method ", new Metadata.MethodDefinition(module, handle));
DisassembleMethodHeaderInternal(module, handle, metadata, genericContext);
DisassembleMethodBlock(module, handle, metadata, genericContext);
output.WriteReference(module, handle, ".method", isDefinition: true);
output.Write(" ");
DisassembleMethodHeaderInternal(module, handle, genericContext);
DisassembleMethodBlock(module, handle, genericContext);
}
public void DisassembleMethodHeader(PEFile module, MethodDefinitionHandle handle)
{
var metadata = module.Metadata;
var genericContext = new GenericContext(handle, module);
// write method header
output.WriteDefinition(".method ", new Metadata.MethodDefinition(module, handle));
DisassembleMethodHeaderInternal(module, handle, metadata, genericContext);
output.WriteReference(module, handle, ".method", isDefinition: true);
output.Write(" ");
DisassembleMethodHeaderInternal(module, handle, genericContext);
}
void DisassembleMethodHeaderInternal(PEFile module, MethodDefinitionHandle handle, MetadataReader metadata, GenericContext genericContext)
void DisassembleMethodHeaderInternal(PEFile module, MethodDefinitionHandle handle, GenericContext genericContext)
{
var metadata = module.Metadata;
WriteMetadataToken(handle, spaceAfter:true);
var methodDefinition = metadata.GetMethodDefinition(handle);
// .method public hidebysig specialname
@ -272,8 +274,9 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -272,8 +274,9 @@ namespace ICSharpCode.Decompiler.Disassembler
}
}
void DisassembleMethodBlock(PEFile module, MethodDefinitionHandle handle, MetadataReader metadata, GenericContext genericContext)
void DisassembleMethodBlock(PEFile module, MethodDefinitionHandle handle, GenericContext genericContext)
{
var metadata = module.Metadata;
var methodDefinition = metadata.GetMethodDefinition(handle);
OpenBlock(defaultCollapsed: isInType);
@ -481,7 +484,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -481,7 +484,7 @@ namespace ICSharpCode.Decompiler.Disassembler
}
}
PrimitiveSerializationTypeCode ResolveEnumUnderlyingType(string typeName, PEFile module, out Metadata.TypeDefinition typeDefinition)
PrimitiveSerializationTypeCode ResolveEnumUnderlyingType(string typeName, PEFile module, out (PEFile Module, EntityHandle Handle) typeDefinition)
{
typeDefinition = default;
@ -529,7 +532,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -529,7 +532,7 @@ namespace ICSharpCode.Decompiler.Disassembler
var metadata = containingModule.Metadata;
if (handle.IsNil || !handle.IsEnum(metadata, out var typeCode))
throw new NotSupportedException();
typeDefinition = new Metadata.TypeDefinition(containingModule, handle);
typeDefinition = (containingModule, handle);
return (PrimitiveSerializationTypeCode)typeCode;
} else {
// just fully-qualified name, try current assembly
@ -545,7 +548,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -545,7 +548,7 @@ namespace ICSharpCode.Decompiler.Disassembler
var metadata = module.Metadata;
if (handle.IsNil || !handle.IsEnum(metadata, out var typeCode))
throw new NotSupportedException();
typeDefinition = new Metadata.TypeDefinition(module, handle);
typeDefinition = (module, handle);
return (PrimitiveSerializationTypeCode)typeCode;
}
}
@ -625,14 +628,14 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -625,14 +628,14 @@ namespace ICSharpCode.Decompiler.Disassembler
}
var typeInfo = ReadArgumentType(ref blob);
var typeCode = typeInfo.TypeCode;
var typeDefinition = default(Metadata.TypeDefinition);
var typeDefinition = default((PEFile Module, EntityHandle Handle));
if (typeInfo.Kind == TypeKind.Enum) {
typeCode = ResolveEnumUnderlyingType(typeInfo.TypeName, module, out typeDefinition);
}
var name = blob.ReadSerializedString();
object value = ReadArgumentValue(ref blob, typeCode, typeInfo.Kind, typeInfo.IsArray, typeInfo.TypeName);
WriteTypeInfo(typeInfo.TypeCode, typeInfo.Kind, typeInfo.IsArray, typeInfo.TypeName, typeDefinition, module);
WriteTypeInfo(module, typeInfo.TypeCode, typeInfo.Kind, typeInfo.IsArray, typeInfo.TypeName, typeDefinition.Module, typeDefinition.Handle);
output.Write(' ');
output.Write(DisassemblerHelpers.Escape(name));
@ -645,7 +648,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -645,7 +648,7 @@ namespace ICSharpCode.Decompiler.Disassembler
if (typeInfo.Kind == TypeKind.Enum || typeInfo.Kind == TypeKind.Primitive) {
WritePrimitiveTypeCode(typeCode);
} else {
WriteTypeInfo(typeCode, typeInfo.Kind, typeInfo.IsArray, typeInfo.TypeName, typeDefinition, module);
WriteTypeInfo(module, typeInfo.TypeCode, typeInfo.Kind, typeInfo.IsArray, typeInfo.TypeName, typeDefinition.Module, typeDefinition.Handle);
}
output.Write('(');
DisassemblerHelpers.WriteOperand(output, value);
@ -653,7 +656,8 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -653,7 +656,8 @@ namespace ICSharpCode.Decompiler.Disassembler
}
}
private void WriteTypeInfo(PrimitiveSerializationTypeCode typeCode, TypeKind kind, bool isArray, string typeName, Metadata.TypeDefinition type, PEFile currentModule)
private void WriteTypeInfo(PEFile currentModule, PrimitiveSerializationTypeCode typeCode, TypeKind kind,
bool isArray, string typeName, PEFile referencedModule, EntityHandle type)
{
switch (kind) {
case TypeKind.Primitive:
@ -669,12 +673,11 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -669,12 +673,11 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write(DisassemblerHelpers.Escape(typeName));
break;
}
var referencedModule = type.Module;
if (referencedModule != currentModule) {
output.Write('[');
output.Write(referencedModule.Name);
output.Write(']');
output.WriteReference(type.Handle.GetFullTypeName(type.Module.Metadata).ToString(), type);
output.WriteReference(referencedModule, type, type.GetFullTypeName(referencedModule.Metadata).ToString());
} else {
output.Write(DisassemblerHelpers.Escape(typeName));
}
@ -1019,10 +1022,10 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1019,10 +1022,10 @@ namespace ICSharpCode.Decompiler.Disassembler
{ FieldAttributes.NotSerialized, "notserialized" },
};
public void DisassembleField(Metadata.FieldDefinition field)
public void DisassembleField(PEFile module, FieldDefinitionHandle field)
{
var metadata = field.Module.Metadata;
var fieldDefinition = metadata.GetFieldDefinition(field.Handle);
var metadata = module.Metadata;
var fieldDefinition = metadata.GetFieldDefinition(field);
output.WriteDefinition(".field ", field);
int offset = fieldDefinition.GetOffset();
if (offset > -1) {
@ -1032,7 +1035,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1032,7 +1035,7 @@ namespace ICSharpCode.Decompiler.Disassembler
const FieldAttributes hasXAttributes = FieldAttributes.HasDefault | FieldAttributes.HasFieldMarshal | FieldAttributes.HasFieldRVA;
WriteFlags(fieldDefinition.Attributes & ~(FieldAttributes.FieldAccessMask | hasXAttributes), fieldAttributes);
var signature = fieldDefinition.DecodeSignature(new DisassemblerSignatureProvider(field.Module, output), new GenericContext(fieldDefinition.GetDeclaringType(), field.Module));
var signature = fieldDefinition.DecodeSignature(new DisassemblerSignatureProvider(module, output), new GenericContext(fieldDefinition.GetDeclaringType(), module));
var marshallingDescriptor = fieldDefinition.GetMarshallingDescriptor();
if (!marshallingDescriptor.IsNil) {
@ -1056,7 +1059,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1056,7 +1059,7 @@ namespace ICSharpCode.Decompiler.Disassembler
var attributes = fieldDefinition.GetCustomAttributes();
if (attributes.Count > 0) {
output.MarkFoldStart();
WriteAttributes(field.Module, fieldDefinition.GetCustomAttributes());
WriteAttributes(module, fieldDefinition.GetCustomAttributes());
output.MarkFoldEnd();
}
}
@ -1069,15 +1072,16 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1069,15 +1072,16 @@ namespace ICSharpCode.Decompiler.Disassembler
{ PropertyAttributes.HasDefault, "hasdefault" },
};
public void DisassembleProperty(Metadata.PropertyDefinition property)
public void DisassembleProperty(PEFile module, PropertyDefinitionHandle property)
{
var metadata = property.Module.Metadata;
var propertyDefinition = metadata.GetPropertyDefinition(property.Handle);
output.WriteDefinition(".property ", property);
var metadata = module.Metadata;
var propertyDefinition = metadata.GetPropertyDefinition(property);
output.WriteReference(module, property, ".property", true);
output.Write(" ");
WriteFlags(propertyDefinition.Attributes, propertyAttributes);
var accessors = propertyDefinition.GetAccessors();
var declaringType = metadata.GetMethodDefinition(accessors.GetAny()).GetDeclaringType();
var signature = propertyDefinition.DecodeSignature(new DisassemblerSignatureProvider(property.Module, output), new GenericContext(declaringType, property.Module));
var signature = propertyDefinition.DecodeSignature(new DisassemblerSignatureProvider(module, output), new GenericContext(declaringType, module));
if (signature.Header.IsInstance)
output.Write("instance ");
@ -1098,23 +1102,23 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1098,23 +1102,23 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write(')');
OpenBlock(false);
WriteAttributes(property.Module, propertyDefinition.GetCustomAttributes());
WriteNestedMethod(".get", new Metadata.MethodDefinition(property.Module, accessors.Getter));
WriteNestedMethod(".set", new Metadata.MethodDefinition(property.Module, accessors.Setter));
WriteAttributes(module, propertyDefinition.GetCustomAttributes());
WriteNestedMethod(".get", module, accessors.Getter);
WriteNestedMethod(".set", module, accessors.Setter);
/*foreach (var method in property.OtherMethods) {
WriteNestedMethod(".other", method);
}*/
CloseBlock();
}
void WriteNestedMethod(string keyword, Metadata.MethodDefinition method)
void WriteNestedMethod(string keyword, PEFile module, MethodDefinitionHandle method)
{
if (method.IsNil)
return;
output.Write(keyword);
output.Write(' ');
((EntityHandle)method.Handle).WriteTo(method.Module, output, GenericContext.Empty);
((EntityHandle)method).WriteTo(module, output, GenericContext.Empty);
output.WriteLine();
}
#endregion
@ -1127,28 +1131,28 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1127,28 +1131,28 @@ namespace ICSharpCode.Decompiler.Disassembler
public void DisassembleEvent(PEFile module, EventDefinitionHandle handle)
{
var metadata = module.Metadata;
var eventDefinition = metadata.GetEventDefinition(handle);
var eventDefinition = module.Metadata.GetEventDefinition(handle);
var accessors = eventDefinition.GetAccessors();
TypeDefinitionHandle declaringType;
if (!accessors.Adder.IsNil) {
declaringType = metadata.GetMethodDefinition(accessors.Adder).GetDeclaringType();
declaringType = module.Metadata.GetMethodDefinition(accessors.Adder).GetDeclaringType();
} else if (!accessors.Remover.IsNil) {
declaringType = metadata.GetMethodDefinition(accessors.Remover).GetDeclaringType();
declaringType = module.Metadata.GetMethodDefinition(accessors.Remover).GetDeclaringType();
} else {
declaringType = metadata.GetMethodDefinition(accessors.Raiser).GetDeclaringType();
declaringType = module.Metadata.GetMethodDefinition(accessors.Raiser).GetDeclaringType();
}
output.WriteDefinition(".event ", new Metadata.EventDefinition(module, handle));
output.WriteReference(module, handle, ".event", true);
output.Write(" ");
WriteFlags(eventDefinition.Attributes, eventAttributes);
var signature = eventDefinition.DecodeSignature(metadata, new DisassemblerSignatureProvider(module, output), new GenericContext(declaringType, module));
var signature = eventDefinition.DecodeSignature(module.Metadata, new DisassemblerSignatureProvider(module, output), new GenericContext(declaringType, module));
signature(ILNameSyntax.TypeName);
output.Write(' ');
output.Write(DisassemblerHelpers.Escape(metadata.GetString(eventDefinition.Name)));
output.Write(DisassemblerHelpers.Escape(module.Metadata.GetString(eventDefinition.Name)));
OpenBlock(false);
WriteAttributes(module, eventDefinition.GetCustomAttributes());
WriteNestedMethod(".addon", new Metadata.MethodDefinition(module, accessors.Adder));
WriteNestedMethod(".removeon", new Metadata.MethodDefinition(module, accessors.Remover));
WriteNestedMethod(".fire", new Metadata.MethodDefinition(module, accessors.Raiser));
WriteNestedMethod(".addon", module, accessors.Adder);
WriteNestedMethod(".removeon", module, accessors.Remover);
WriteNestedMethod(".fire", module, accessors.Raiser);
/*foreach (var method in ev.OtherMethods) {
WriteNestedMethod(".other", method);
}*/
@ -1191,12 +1195,11 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1191,12 +1195,11 @@ namespace ICSharpCode.Decompiler.Disassembler
{ TypeAttributes.HasSecurity, null },
};
public void DisassembleType(Metadata.TypeDefinition type)
public void DisassembleType(PEFile module, TypeDefinitionHandle type)
{
var metadata = type.Module.Metadata;
var typeDefinition = metadata.GetTypeDefinition(type.Handle);
output.WriteDefinition(".class ", type);
var typeDefinition = module.Metadata.GetTypeDefinition(type);
output.WriteReference(module, type, ".class", true);
output.Write(" ");
if ((typeDefinition.Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface)
output.Write("interface ");
WriteEnum(typeDefinition.Attributes & TypeAttributes.VisibilityMask, typeVisibility);
@ -1205,15 +1208,16 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1205,15 +1208,16 @@ namespace ICSharpCode.Decompiler.Disassembler
const TypeAttributes masks = TypeAttributes.ClassSemanticsMask | TypeAttributes.VisibilityMask | TypeAttributes.LayoutMask | TypeAttributes.StringFormatMask;
WriteFlags(typeDefinition.Attributes & ~masks, typeAttributes);
output.Write(typeDefinition.GetDeclaringType().IsNil ? typeDefinition.GetFullTypeName(metadata).ToILNameString() : DisassemblerHelpers.Escape(metadata.GetString(typeDefinition.Name)));
WriteTypeParameters(output, type.Module, new GenericContext(type), typeDefinition.GetGenericParameters());
output.Write(typeDefinition.GetDeclaringType().IsNil ? typeDefinition.GetFullTypeName(module.Metadata).ToILNameString() : DisassemblerHelpers.Escape(module.Metadata.GetString(typeDefinition.Name)));
GenericContext genericContext = new GenericContext(type, module);
WriteTypeParameters(output, module, genericContext, typeDefinition.GetGenericParameters());
output.MarkFoldStart(defaultCollapsed: !ExpandMemberDefinitions && isInType);
output.WriteLine();
if (!typeDefinition.BaseType.IsNil) {
output.Indent();
output.Write("extends ");
typeDefinition.BaseType.WriteTo(type.Module, output, new GenericContext(type), ILNameSyntax.TypeName);
typeDefinition.BaseType.WriteTo(module, output, genericContext, ILNameSyntax.TypeName);
output.WriteLine();
output.Unindent();
}
@ -1229,9 +1233,9 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1229,9 +1233,9 @@ namespace ICSharpCode.Decompiler.Disassembler
else
output.Write(" ");
first = false;
var iface = metadata.GetInterfaceImplementation(i);
WriteAttributes(type.Module, iface.GetCustomAttributes());
iface.Interface.WriteTo(type.Module, output, new GenericContext(type), ILNameSyntax.TypeName);
var iface = module.Metadata.GetInterfaceImplementation(i);
WriteAttributes(module, iface.GetCustomAttributes());
iface.Interface.WriteTo(module, output, genericContext, ILNameSyntax.TypeName);
}
output.WriteLine();
output.Unindent();
@ -1241,8 +1245,8 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1241,8 +1245,8 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Indent();
bool oldIsInType = isInType;
isInType = true;
WriteAttributes(type.Module, typeDefinition.GetCustomAttributes());
WriteSecurityDeclarations(type.Module, typeDefinition.GetDeclarativeSecurityAttributes());
WriteAttributes(module, typeDefinition.GetCustomAttributes());
WriteSecurityDeclarations(module, typeDefinition.GetDeclarativeSecurityAttributes());
var layout = typeDefinition.GetLayout();
if (!layout.IsDefault) {
output.WriteLine(".pack {0}", layout.PackingSize);
@ -1254,7 +1258,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1254,7 +1258,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine("// Nested Types");
foreach (var nestedType in nestedTypes) {
cancellationToken.ThrowIfCancellationRequested();
DisassembleType(new Metadata.TypeDefinition(type.Module, nestedType));
DisassembleType(module, nestedType);
output.WriteLine();
}
output.WriteLine();
@ -1264,7 +1268,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1264,7 +1268,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine("// Fields");
foreach (var field in fields) {
cancellationToken.ThrowIfCancellationRequested();
DisassembleField(new Metadata.FieldDefinition(type.Module, field));
DisassembleField(module, field);
}
output.WriteLine();
}
@ -1273,7 +1277,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1273,7 +1277,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine("// Methods");
foreach (var m in methods) {
cancellationToken.ThrowIfCancellationRequested();
DisassembleMethod(type.Module, m);
DisassembleMethod(module, m);
output.WriteLine();
}
}
@ -1282,7 +1286,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1282,7 +1286,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine("// Events");
foreach (var ev in events) {
cancellationToken.ThrowIfCancellationRequested();
DisassembleEvent(type.Module, ev);
DisassembleEvent(module, ev);
output.WriteLine();
}
output.WriteLine();
@ -1292,11 +1296,11 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1292,11 +1296,11 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine("// Properties");
foreach (var prop in properties) {
cancellationToken.ThrowIfCancellationRequested();
DisassembleProperty(new Metadata.PropertyDefinition(type.Module, prop));
DisassembleProperty(module, prop);
}
output.WriteLine();
}
CloseBlock("end of class " + (!typeDefinition.GetDeclaringType().IsNil ? metadata.GetString(typeDefinition.Name) : typeDefinition.GetFullTypeName(metadata).ToString()));
CloseBlock("end of class " + (!typeDefinition.GetDeclaringType().IsNil ? module.Metadata.GetString(typeDefinition.Name) : typeDefinition.GetFullTypeName(module.Metadata).ToString()));
isInType = oldIsInType;
}
@ -1449,7 +1453,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1449,7 +1453,7 @@ namespace ICSharpCode.Decompiler.Disassembler
}
#endregion
public void DisassembleNamespace(string nameSpace, IEnumerable<Metadata.TypeDefinition> types)
public void DisassembleNamespace(string nameSpace, PEFile module, IEnumerable<TypeDefinitionHandle> types)
{
if (!string.IsNullOrEmpty(nameSpace)) {
output.Write(".namespace " + DisassemblerHelpers.Escape(nameSpace));
@ -1459,7 +1463,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1459,7 +1463,7 @@ namespace ICSharpCode.Decompiler.Disassembler
isInType = true;
foreach (var td in types) {
cancellationToken.ThrowIfCancellationRequested();
DisassembleType(td);
DisassembleType(module, td);
output.WriteLine();
}
if (!string.IsNullOrEmpty(nameSpace)) {
@ -1590,8 +1594,8 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1590,8 +1594,8 @@ namespace ICSharpCode.Decompiler.Disassembler
public void WriteModuleContents(PEFile module)
{
foreach (var handle in module.TopLevelTypeDefinitions) {
DisassembleType(handle);
foreach (var handle in module.Metadata.GetTopLevelTypeDefinitions()) {
DisassembleType(module, handle);
output.WriteLine();
}
}

591
ICSharpCode.Decompiler/Documentation/XmlDocKeyProvider.cs

@ -18,14 +18,10 @@ @@ -18,14 +18,10 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Metadata;
using SRM = System.Reflection.Metadata;
using ICSharpCode.Decompiler.Util;
using System.Collections.Immutable;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
namespace ICSharpCode.Decompiler.Documentation
{
@ -35,324 +31,361 @@ namespace ICSharpCode.Decompiler.Documentation @@ -35,324 +31,361 @@ namespace ICSharpCode.Decompiler.Documentation
public static class XmlDocKeyProvider
{
#region GetKey
public static string GetKey(Entity entity)
{
return GetKey(entity.Module.Metadata, entity.Handle);
}
public static string GetKey(SRM.MetadataReader metadata, SRM.EntityHandle member)
/// <summary>
/// Gets the ID string (C# 4.0 spec, §A.3.1) for the specified entity.
/// </summary>
public static string GetKey(IEntity entity)
{
StringBuilder b = new StringBuilder();
void AppendTypeName(SRM.EntityHandle type)
{
switch (type.Kind) {
case SRM.HandleKind.TypeDefinition:
b.Append("T:");
b.Append(((SRM.TypeDefinitionHandle)type).GetFullTypeName(metadata));
break;
case SRM.HandleKind.TypeReference:
b.Append("T:");
b.Append(((SRM.TypeReferenceHandle)type).GetFullTypeName(metadata));
break;
default:
throw new NotImplementedException();
/*case SRM.HandleKind.TypeSpecification:
b.Append("T:");
var typeSpec = metadata.GetTypeSpecification((SRM.TypeSpecificationHandle)type);
b.Append(typeSpec.DecodeSignature(new DocumentationKeySignatureTypeProvider(), default(Unit)));
break;*/
}
switch (entity.SymbolKind) {
case SymbolKind.TypeDefinition:
b.Append("T:");
AppendTypeName(b, (ITypeDefinition)entity, false);
return b.ToString();
case SymbolKind.Field:
b.Append("F:");
break;
case SymbolKind.Property:
case SymbolKind.Indexer:
b.Append("P:");
break;
case SymbolKind.Event:
b.Append("E:");
break;
default:
b.Append("M:");
break;
}
void AppendSignature(SRM.MethodSignature<string> signature, bool printExplicitReturnType = false)
{
if (signature.GenericParameterCount > 0) {
b.Append("``");
b.Append(signature.GenericParameterCount);
}
IMember member = (IMember)entity;
if (member.DeclaringType != null) {
AppendTypeName(b, member.DeclaringType, false);
b.Append('.');
}
if (member.IsExplicitInterfaceImplementation && member.Name.IndexOf('.') < 0 && member.ExplicitlyImplementedInterfaceMembers.Count() == 1) {
AppendTypeName(b, member.ExplicitlyImplementedInterfaceMembers.First().DeclaringType, true);
b.Append('#');
}
b.Append(member.Name.Replace('.', '#'));
IMethod method = member as IMethod;
if (method != null && method.TypeParameters.Count > 0) {
b.Append("``");
b.Append(method.TypeParameters.Count);
}
IParameterizedMember parameterizedMember = member as IParameterizedMember;
if (parameterizedMember != null && parameterizedMember.Parameters.Count > 0) {
b.Append('(');
for (int i = 0; i < signature.ParameterTypes.Length; i++) {
if (i > 0)
b.Append(',');
b.Append(signature.ParameterTypes[i]);
var parameters = parameterizedMember.Parameters;
for (int i = 0; i < parameters.Count; i++) {
if (i > 0) b.Append(',');
AppendTypeName(b, parameters[i].Type, false);
}
b.Append(')');
if (printExplicitReturnType) {
b.Append('~');
b.Append(signature.ReturnType);
}
}
if (member.SymbolKind == SymbolKind.Operator && (member.Name == "op_Implicit" || member.Name == "op_Explicit")) {
b.Append('~');
AppendTypeName(b, member.ReturnType, false);
}
return b.ToString();
}
#endregion
switch (member.Kind) {
case SRM.HandleKind.TypeDefinition:
case SRM.HandleKind.TypeReference:
case SRM.HandleKind.TypeSpecification:
b.Append("T:");
AppendTypeName(member);
break;
case SRM.HandleKind.FieldDefinition:
b.Append("F:");
var field = metadata.GetFieldDefinition((SRM.FieldDefinitionHandle)member);
AppendTypeName(field.GetDeclaringType());
b.Append('.');
b.Append(metadata.GetString(field.Name).Replace('.', '#'));
#region GetTypeName
public static string GetTypeName(IType type)
{
if (type == null)
throw new ArgumentNullException("type");
StringBuilder b = new StringBuilder();
AppendTypeName(b, type, false);
return b.ToString();
}
static void AppendTypeName(StringBuilder b, IType type, bool explicitInterfaceImpl)
{
switch (type.Kind) {
case TypeKind.Dynamic:
b.Append(explicitInterfaceImpl ? "System#Object" : "System.Object");
break;
case SRM.HandleKind.PropertyDefinition: {
b.Append("P:");
var property = metadata.GetPropertyDefinition((SRM.PropertyDefinitionHandle)member);
var accessors = property.GetAccessors();
SRM.TypeDefinitionHandle declaringType;
if (!accessors.Getter.IsNil) {
declaringType = metadata.GetMethodDefinition(accessors.Getter).GetDeclaringType();
case TypeKind.TypeParameter:
ITypeParameter tp = (ITypeParameter)type;
if (explicitInterfaceImpl) {
b.Append(tp.Name);
} else {
declaringType = metadata.GetMethodDefinition(accessors.Setter).GetDeclaringType();
b.Append('`');
if (tp.OwnerType == SymbolKind.Method)
b.Append('`');
b.Append(tp.Index);
}
AppendTypeName(declaringType);
b.Append('.');
b.Append(metadata.GetString(property.Name).Replace('.', '#'));
AppendSignature(property.DecodeSignature(new DocumentationKeySignatureTypeProvider(), default(Unit)));
break;
}
case SRM.HandleKind.MethodDefinition:
b.Append("M:");
var method = metadata.GetMethodDefinition((SRM.MethodDefinitionHandle)member);
AppendTypeName(method.GetDeclaringType());
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");
case TypeKind.Array:
ArrayType array = (ArrayType)type;
AppendTypeName(b, array.ElementType, explicitInterfaceImpl);
b.Append('[');
if (array.Dimensions > 1) {
for (int i = 0; i < array.Dimensions; i++) {
if (i > 0)
b.Append(explicitInterfaceImpl ? '@' : ',');
if (!explicitInterfaceImpl)
b.Append("0:");
}
}
b.Append(']');
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();
case TypeKind.Pointer:
AppendTypeName(b, ((PointerType)type).ElementType, explicitInterfaceImpl);
b.Append('*');
break;
case TypeKind.ByReference:
AppendTypeName(b, ((ByReferenceType)type).ElementType, explicitInterfaceImpl);
b.Append('@');
break;
default:
IType declType = type.DeclaringType;
if (declType != null) {
AppendTypeName(b, declType, explicitInterfaceImpl);
b.Append(explicitInterfaceImpl ? '#' : '.');
b.Append(type.Name);
AppendTypeParameters(b, type, declType.TypeParameterCount, explicitInterfaceImpl);
} else {
declaringType = metadata.GetMethodDefinition(accessors.Raiser).GetDeclaringType();
if (explicitInterfaceImpl)
b.Append(type.FullName.Replace('.', '#'));
else
b.Append(type.FullName);
AppendTypeParameters(b, type, 0, explicitInterfaceImpl);
}
AppendTypeName(declaringType);
b.Append('.');
b.Append(metadata.GetString(@event.Name).Replace('.', '#'));
break;
}
default:
throw new NotImplementedException();
}
return b.ToString();
}
public sealed class DocumentationKeySignatureTypeProvider : SRM.ISignatureTypeProvider<string, Unit>
static void AppendTypeParameters(StringBuilder b, IType type, int outerTypeParameterCount, bool explicitInterfaceImpl)
{
public string GetArrayType(string elementType, SRM.ArrayShape shape)
{
string shapeString = "";
for (int i = 0; i < shape.Rank; i++) {
if (i > 0)
shapeString += ',';
int? lowerBound = i < shape.LowerBounds.Length ? (int?)shape.LowerBounds[i] : null;
int? size = i < shape.Sizes.Length ? (int?)shape.Sizes[i] : null;
if (lowerBound != null || size != null) {
shapeString += lowerBound.ToString();
shapeString += ':';
shapeString += (lowerBound + size - 1).ToString();
int tpc = type.TypeParameterCount - outerTypeParameterCount;
if (tpc > 0) {
ParameterizedType pt = type as ParameterizedType;
if (pt != null) {
b.Append('{');
var ta = pt.TypeArguments;
for (int i = outerTypeParameterCount; i < ta.Count; i++) {
if (i > outerTypeParameterCount)
b.Append(explicitInterfaceImpl ? '@' : ',');
AppendTypeName(b, ta[i], explicitInterfaceImpl);
}
b.Append('}');
} else {
b.Append('`');
b.Append(tpc);
}
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)
{
return unmodifiedType;
}
public string GetPinnedType(string elementType)
{
return elementType;
}
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();
}
}
#endregion
public string GetTypeFromSpecification(SRM.MetadataReader reader, Unit genericContext, SRM.TypeSpecificationHandle handle, byte rawTypeKind)
{
return handle.GetFullTypeName(reader).ToString();
}
#region ParseMemberName
/// <summary>
/// Parse the ID string into a member reference.
/// </summary>
/// <param name="memberIdString">The ID string representing the member (with "M:", "F:", "P:" or "E:" prefix).</param>
/// <returns>A member reference that represents the ID string.</returns>
/// <exception cref="ReflectionNameParseException">The syntax of the ID string is invalid</exception>
/// <remarks>
/// The member reference will look in <see cref="ITypeResolveContext.CurrentAssembly"/> first,
/// and if the member is not found there,
/// it will look in all other assemblies of the compilation.
/// </remarks>
public static IMemberReference ParseMemberIdString(string memberIdString)
{
if (memberIdString == null)
throw new ArgumentNullException("memberIdString");
if (memberIdString.Length < 2 || memberIdString[1] != ':')
throw new ReflectionNameParseException(0, "Missing type tag");
char typeChar = memberIdString[0];
int parenPos = memberIdString.IndexOf('(');
if (parenPos < 0)
parenPos = memberIdString.LastIndexOf('~');
if (parenPos < 0)
parenPos = memberIdString.Length;
int dotPos = memberIdString.LastIndexOf('.', parenPos - 1);
if (dotPos < 0)
throw new ReflectionNameParseException(0, "Could not find '.' separating type name from member name");
string typeName = memberIdString.Substring(0, dotPos);
int pos = 2;
ITypeReference typeReference = ParseTypeName(typeName, ref pos);
if (pos != typeName.Length)
throw new ReflectionNameParseException(pos, "Expected end of type name");
// string memberName = memberIDString.Substring(dotPos + 1, parenPos - (dotPos + 1));
// pos = memberName.LastIndexOf("``");
// if (pos > 0)
// memberName = memberName.Substring(0, pos);
// memberName = memberName.Replace('#', '.');
return new IdStringMemberReference(typeReference, typeChar, memberIdString);
}
#endregion
#region FindMemberByKey
public static Entity FindMemberByKey(PEFile module, string key)
#region ParseTypeName
/// <summary>
/// Parse the ID string type name into a type reference.
/// </summary>
/// <param name="typeName">The ID string representing the type (the "T:" prefix is optional).</param>
/// <returns>A type reference that represents the ID string.</returns>
/// <exception cref="ReflectionNameParseException">The syntax of the ID string is invalid</exception>
/// <remarks>
/// <para>
/// The type reference will look in <see cref="ITypeResolveContext.CurrentAssembly"/> first,
/// and if the type is not found there,
/// it will look in all other assemblies of the compilation.
/// </para>
/// <para>
/// If the type is open (contains type parameters '`0' or '``0'),
/// an <see cref="ITypeResolveContext"/> with the appropriate CurrentTypeDefinition/CurrentMember is required
/// to resolve the reference to the ITypeParameter.
/// </para>
/// </remarks>
public static ITypeReference ParseTypeName(string typeName)
{
if (module == null)
throw new ArgumentNullException(nameof(module));
if (key == null || key.Length < 2 || key[1] != ':')
return default(Entity);
switch (key[0]) {
case 'T':
return FindType(module, key.Substring(2));
case 'F':
return FindMember(module, key, type => module.Metadata.GetTypeDefinition(type.Handle).GetFields().Select(f => new Entity(module, f)));
case 'P':
return FindMember(module, key, type => module.Metadata.GetTypeDefinition(type.Handle).GetProperties().Select(p => new Entity(module, p)));
case 'E':
return FindMember(module, key, type => module.Metadata.GetTypeDefinition(type.Handle).GetEvents().Select(e => new Entity(module, e)));
case 'M':
return FindMember(module, key, type => module.Metadata.GetTypeDefinition(type.Handle).GetMethods().Select(m => new Entity(module, m)));
if (typeName == null)
throw new ArgumentNullException("typeName");
int pos = 0;
if (typeName.StartsWith("T:", StringComparison.Ordinal))
pos = 2;
ITypeReference r = ParseTypeName(typeName, ref pos);
if (pos < typeName.Length)
throw new ReflectionNameParseException(pos, "Expected end of type name");
return r;
}
static bool IsIDStringSpecialCharacter(char c)
{
switch (c) {
case ':':
case '{':
case '}':
case '[':
case ']':
case '(':
case ')':
case '`':
case '*':
case '@':
case ',':
return true;
default:
return default(Entity);
return false;
}
}
static Entity FindMember(PEFile module, string key, Func<TypeDefinition, IEnumerable<Entity>> memberSelector)
static ITypeReference ParseTypeName(string typeName, ref int pos)
{
Debug.WriteLine("Looking for member " + key);
int parenPos = key.IndexOf('(');
int dotPos;
if (parenPos > 0) {
dotPos = key.LastIndexOf('.', parenPos - 1, parenPos);
} else {
dotPos = key.LastIndexOf('.');
}
if (dotPos < 0)
return default(Entity);
TypeDefinition type = FindType(module, key.Substring(2, dotPos - 2));
if (type == null)
return default(Entity);
string shortName;
if (parenPos > 0) {
shortName = key.Substring(dotPos + 1, parenPos - (dotPos + 1));
string reflectionTypeName = typeName;
if (pos == typeName.Length)
throw new ReflectionNameParseException(pos, "Unexpected end");
ITypeReference result;
if (reflectionTypeName[pos] == '`') {
// type parameter reference
pos++;
if (pos == reflectionTypeName.Length)
throw new ReflectionNameParseException(pos, "Unexpected end");
if (reflectionTypeName[pos] == '`') {
// method type parameter reference
pos++;
int index = ReflectionHelper.ReadTypeParameterCount(reflectionTypeName, ref pos);
result = TypeParameterReference.Create(SymbolKind.Method, index);
} else {
// class type parameter reference
int index = ReflectionHelper.ReadTypeParameterCount(reflectionTypeName, ref pos);
result = TypeParameterReference.Create(SymbolKind.TypeDefinition, index);
}
} else {
shortName = key.Substring(dotPos + 1);
// not a type parameter reference: read the actual type name
List<ITypeReference> typeArguments = new List<ITypeReference>();
int typeParameterCount;
string typeNameWithoutSuffix = ReadTypeName(typeName, ref pos, true, out typeParameterCount, typeArguments);
result = new GetPotentiallyNestedClassTypeReference(typeNameWithoutSuffix, typeParameterCount);
while (pos < typeName.Length && typeName[pos] == '.') {
pos++;
string nestedTypeName = ReadTypeName(typeName, ref pos, false, out typeParameterCount, typeArguments);
result = new NestedTypeReference(result, nestedTypeName, typeParameterCount);
}
if (typeArguments.Count > 0) {
result = new ParameterizedTypeReference(result, typeArguments);
}
}
var metadata = module.Metadata;
Debug.WriteLine("Searching in type {0} for {1}", type.Handle.GetFullTypeName(metadata), shortName);
Entity shortNameMatch = default(Entity);
foreach (var member in memberSelector(type)) {
string memberKey = GetKey(member);
Debug.WriteLine(memberKey);
if (memberKey == key)
return member;
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);
while (pos < typeName.Length) {
switch (typeName[pos]) {
case '[':
int dimensions = 1;
do {
pos++;
if (pos == typeName.Length)
throw new ReflectionNameParseException(pos, "Unexpected end");
if (typeName[pos] == ',')
dimensions++;
} while (typeName[pos] != ']');
result = new ArrayTypeReference(result, dimensions);
break;
case SRM.HandleKind.PropertyDefinition:
name = metadata.GetString(metadata.GetPropertyDefinition((SRM.PropertyDefinitionHandle)member.Handle).Name);
case '*':
result = new PointerTypeReference(result);
break;
case SRM.HandleKind.EventDefinition:
name = metadata.GetString(metadata.GetEventDefinition((SRM.EventDefinitionHandle)member.Handle).Name);
case '@':
result = new ByReferenceTypeReference(result);
break;
default:
throw new NotSupportedException();
return result;
}
if (shortName == name.Replace('.', '#'))
shortNameMatch = member;
pos++;
}
// if there's no match by ID string (key), return the match by name.
return shortNameMatch;
return result;
}
static TypeDefinition FindType(PEFile module, string name)
static string ReadTypeName(string typeName, ref int pos, bool allowDottedName, out int typeParameterCount, List<ITypeReference> typeArguments)
{
var metadata = module.Metadata;
string[] segments = name.Split('.');
var currentNamespace = metadata.GetNamespaceDefinitionRoot();
int i = 0;
while (i < segments.Length) {
string part = segments[i];
var next = currentNamespace.NamespaceDefinitions.FirstOrDefault(ns => metadata.GetString(metadata.GetNamespaceDefinition(ns).Name) == part);
if (next.IsNil)
break;
currentNamespace = metadata.GetNamespaceDefinition(next);
i++;
int startPos = pos;
// skip the simple name portion:
while (pos < typeName.Length && !IsIDStringSpecialCharacter(typeName[pos]) && (allowDottedName || typeName[pos] != '.'))
pos++;
if (pos == startPos)
throw new ReflectionNameParseException(pos, "Expected type name");
string shortTypeName = typeName.Substring(startPos, pos - startPos);
// read type arguments:
typeParameterCount = 0;
if (pos < typeName.Length && typeName[pos] == '`') {
// unbound generic type
pos++;
typeParameterCount = ReflectionHelper.ReadTypeParameterCount(typeName, ref pos);
} else if (pos < typeName.Length && typeName[pos] == '{') {
// bound generic type
typeArguments = new List<ITypeReference>();
do {
pos++;
typeArguments.Add(ParseTypeName(typeName, ref pos));
typeParameterCount++;
if (pos == typeName.Length)
throw new ReflectionNameParseException(pos, "Unexpected end");
} while (typeName[pos] == ',');
if (typeName[pos] != '}')
throw new ReflectionNameParseException(pos, "Expected '}'");
pos++;
}
if (i == segments.Length)
return default(TypeDefinition);
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 shortTypeName;
}
#endregion
#region FindEntity
/// <summary>
/// Finds the entity in the given type resolve context.
/// </summary>
/// <param name="idString">ID string of the entity.</param>
/// <param name="context">Type resolve context</param>
/// <returns>Returns the entity, or null if it is not found.</returns>
/// <exception cref="ReflectionNameParseException">The syntax of the ID string is invalid</exception>
public static IEntity FindEntity(string idString, ITypeResolveContext context)
{
if (idString == null)
throw new ArgumentNullException("idString");
if (context == null)
throw new ArgumentNullException("context");
if (idString.StartsWith("T:", StringComparison.Ordinal)) {
return ParseTypeName(idString.Substring(2)).Resolve(context).GetDefinition();
} else {
return ParseMemberIdString(idString).Resolve(context);
}
// TODO : add support for type forwarders
//foreach (var h in metadata.ExportedTypes) {
// var exportedType = metadata.GetExportedType(h);
// if (metadata.StringComparer.Equals(exportedType.Name, name) && exportedType.Namespace == ns) {
// type = exportedType.Resolve();
// break;
// }
//}
return default;
}
#endregion
}

2
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -270,6 +270,7 @@ @@ -270,6 +270,7 @@
<Compile Include="DecompileRun.cs" />
<Compile Include="Disassembler\DomExtensions.cs" />
<Compile Include="Metadata\AssemblyReferences.cs" />
<Compile Include="Metadata\MetadataResolver.cs" />
<Compile Include="Metadata\MetadataTokenHelpers.cs" />
<Compile Include="Disassembler\OpCodeInfo.cs" />
<Compile Include="Documentation\GetPotentiallyNestedClassTypeReference.cs" />
@ -283,7 +284,6 @@ @@ -283,7 +284,6 @@
<Compile Include="IL\ControlFlow\YieldReturnDecompiler.cs" />
<Compile Include="Metadata\CustomAttributeDecoder.cs" />
<Compile Include="Metadata\Dom.cs" />
<Compile Include="Metadata\MetadataResolver.cs" />
<Compile Include="Metadata\DotNetCorePathFinder.cs" />
<Compile Include="Metadata\DotNetCorePathFinderExtensions.cs" />
<Compile Include="Metadata\LightJson\JsonArray.cs" />

402
ICSharpCode.Decompiler/Metadata/Dom.cs

@ -15,31 +15,11 @@ using ICSharpCode.Decompiler.Util; @@ -15,31 +15,11 @@ using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.Metadata
{
using SRMMemberRef = System.Reflection.Metadata.MemberReference;
using SRMMethod = System.Reflection.Metadata.MethodDefinition;
using SRMMethodSpec = System.Reflection.Metadata.MethodSpecification;
using SRMProperty = System.Reflection.Metadata.PropertyDefinition;
using SRMEvent = System.Reflection.Metadata.EventDefinition;
using SRMField = System.Reflection.Metadata.FieldDefinition;
using SRMTypeDef = System.Reflection.Metadata.TypeDefinition;
using SRMTypeRef = System.Reflection.Metadata.TypeReference;
using SRMTypeSpec = System.Reflection.Metadata.TypeSpecification;
using SRMAssemblyReference = System.Reflection.Metadata.AssemblyReference;
public interface IAssemblyDocumentationResolver
{
XmlDocumentationProvider GetProvider();
}
public interface IMetadataEntity
{
PEFile Module { get; }
EntityHandle Handle { get; }
bool IsNil { get; }
}
public struct Variable
{
public string Name { get; set; }
@ -136,378 +116,6 @@ namespace ICSharpCode.Decompiler.Metadata @@ -136,378 +116,6 @@ namespace ICSharpCode.Decompiler.Metadata
}
}
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 FieldDefinition ResolveAsField()
{
return MetadataResolver.ResolveAsField(Handle, new SimpleMetadataResolveContext(Module));
}
public MethodDefinition ResolveAsMethod()
{
return MetadataResolver.ResolveAsMethod(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 MethodDefinitionHandle Handle { get; }
public bool IsNil => Handle.IsNil;
EntityHandle IMetadataEntity.Handle => Handle;
public MethodDefinition(PEFile module, MethodDefinitionHandle handle) : this()
{
this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle;
}
public bool Equals(MethodDefinition other)
{
return Module == other.Module && Handle == other.Handle;
}
public override bool Equals(object obj)
{
if (obj is MethodDefinition md)
return Equals(md);
return false;
}
public override int GetHashCode()
{
return unchecked(982451629 * Module.GetHashCode() + 982451653 * MetadataTokens.GetToken(Handle));
}
public static bool operator ==(MethodDefinition lhs, MethodDefinition rhs) => lhs.Equals(rhs);
public static bool operator !=(MethodDefinition lhs, MethodDefinition rhs) => !lhs.Equals(rhs);
public IList<SequencePoint> GetSequencePoints()
{
return Module.DebugInfo?.GetSequencePoints(Handle) ?? EmptyList<SequencePoint>.Instance;
}
public IList<Variable> GetVariables()
{
return Module.DebugInfo?.GetVariables(Handle) ?? EmptyList<Variable>.Instance;
}
}
public struct PropertyDefinition : IEquatable<PropertyDefinition>, IMetadataEntity
{
public PEFile Module { get; }
public PropertyDefinitionHandle Handle { get; }
public bool IsNil => Handle.IsNil;
EntityHandle IMetadataEntity.Handle => Handle;
public PropertyDefinition(PEFile module, PropertyDefinitionHandle handle) : this()
{
this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle;
}
public bool Equals(PropertyDefinition other)
{
return Module == other.Module && Handle == other.Handle;
}
public override bool Equals(object obj)
{
if (obj is PropertyDefinition pd)
return Equals(pd);
return false;
}
public override int GetHashCode()
{
return unchecked(982451629 * Module.GetHashCode() + 982451653 * MetadataTokens.GetToken(Handle));
}
public static bool operator ==(PropertyDefinition lhs, PropertyDefinition rhs) => lhs.Equals(rhs);
public static bool operator !=(PropertyDefinition lhs, PropertyDefinition rhs) => !lhs.Equals(rhs);
}
public struct FieldDefinition : IEquatable<FieldDefinition>, IMetadataEntity
{
public PEFile Module { get; }
public FieldDefinitionHandle Handle { get; }
public bool IsNil => Handle.IsNil;
EntityHandle IMetadataEntity.Handle => Handle;
public FieldDefinition(PEFile module, FieldDefinitionHandle handle) : this()
{
this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle;
}
public bool Equals(FieldDefinition other)
{
return Module == other.Module && Handle == other.Handle;
}
public override bool Equals(object obj)
{
if (obj is FieldDefinition fd)
return Equals(fd);
return false;
}
public override int GetHashCode()
{
return unchecked(982451629 * Module.GetHashCode() + 982451653 * MetadataTokens.GetToken(Handle));
}
public static bool operator ==(FieldDefinition lhs, FieldDefinition rhs) => lhs.Equals(rhs);
public static bool operator !=(FieldDefinition lhs, FieldDefinition rhs) => !lhs.Equals(rhs);
public object DecodeConstant()
{
var metadata = Module.Metadata;
var constant = metadata.GetConstant(metadata.GetFieldDefinition(Handle).GetDefaultValue());
var blob = metadata.GetBlobReader(constant.Value);
switch (constant.TypeCode) {
case ConstantTypeCode.Boolean:
return blob.ReadBoolean();
case ConstantTypeCode.Char:
return blob.ReadChar();
case ConstantTypeCode.SByte:
return blob.ReadSByte();
case ConstantTypeCode.Byte:
return blob.ReadByte();
case ConstantTypeCode.Int16:
return blob.ReadInt16();
case ConstantTypeCode.UInt16:
return blob.ReadUInt16();
case ConstantTypeCode.Int32:
return blob.ReadInt32();
case ConstantTypeCode.UInt32:
return blob.ReadUInt32();
case ConstantTypeCode.Int64:
return blob.ReadInt64();
case ConstantTypeCode.UInt64:
return blob.ReadUInt64();
case ConstantTypeCode.Single:
return blob.ReadSingle();
case ConstantTypeCode.Double:
return blob.ReadDouble();
case ConstantTypeCode.String:
return blob.ReadSerializedString();
case ConstantTypeCode.NullReference:
return null;
default:
throw new NotSupportedException();
}
}
}
public struct EventDefinition : IEquatable<EventDefinition>, IMetadataEntity
{
public PEFile Module { get; }
public EventDefinitionHandle Handle { get; }
public bool IsNil => Handle.IsNil;
EntityHandle IMetadataEntity.Handle => Handle;
public EventDefinition(PEFile module, EventDefinitionHandle handle)
{
this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle;
}
public bool Equals(EventDefinition other)
{
return Module == other.Module && Handle == other.Handle;
}
public override bool Equals(object obj)
{
if (obj is EventDefinition ed)
return Equals(ed);
return false;
}
public override int GetHashCode()
{
return unchecked(982451629 * Module.GetHashCode() + 982451653 * MetadataTokens.GetToken(Handle));
}
public static bool operator ==(EventDefinition lhs, EventDefinition rhs) => lhs.Equals(rhs);
public static bool operator !=(EventDefinition lhs, EventDefinition rhs) => !lhs.Equals(rhs);
}
public struct TypeDefinition : IEquatable<TypeDefinition>, IMetadataEntity
{
public PEFile Module { get; }
public TypeDefinitionHandle Handle { get; }
public bool IsNil => Handle.IsNil;
EntityHandle IMetadataEntity.Handle => Handle;
public TypeDefinition(PEFile module, TypeDefinitionHandle handle)
{
this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle;
}
public bool Equals(TypeDefinition other)
{
return Module == other.Module && Handle == other.Handle;
}
public override bool Equals(object obj)
{
if (obj is TypeDefinition td)
return Equals(td);
return false;
}
public override int GetHashCode()
{
return unchecked(982451629 * Module.GetHashCode() + 982451653 * MetadataTokens.GetToken(Handle));
}
public static bool operator ==(TypeDefinition lhs, TypeDefinition rhs) => lhs.Equals(rhs);
public static bool operator !=(TypeDefinition lhs, TypeDefinition rhs) => !lhs.Equals(rhs);
}
public struct TypeReference
{
public PEFile Module { get; }
public TypeReferenceHandle Handle { get; }
public bool IsNil => Handle.IsNil;
public TypeReference(PEFile module, TypeReferenceHandle handle)
{
this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle;
}
}
public struct TypeSpecification
{
public PEFile Module { get; }
public TypeSpecificationHandle Handle { get; }
public bool IsNil => Handle.IsNil;
public TypeSpecification(PEFile module, TypeSpecificationHandle handle)
{
this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle;
}
}
public struct MethodSpecification
{
public PEFile Module { get; }
public MethodSpecificationHandle Handle { get; }
public bool IsNil => Handle.IsNil;
public MethodSpecification(PEFile module, MethodSpecificationHandle handle)
{
this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle;
}
}
public struct MemberReference
{
public PEFile Module { get; }
public MemberReferenceHandle Handle { get; }
public bool IsNil => Handle.IsNil;
public MemberReference(PEFile module, MemberReferenceHandle handle)
{
this.Module = module ?? throw new ArgumentNullException(nameof(module));
this.Handle = handle;
}
}
public sealed class FullTypeNameSignatureDecoder : ISignatureTypeProvider<FullTypeName, Unit>
{
readonly MetadataReader metadata;
@ -606,22 +214,12 @@ namespace ICSharpCode.Decompiler.Metadata @@ -606,22 +214,12 @@ namespace ICSharpCode.Decompiler.Metadata
this.declaringType = module.Metadata.GetMethodDefinition(method).GetDeclaringType();
}
public GenericContext(MethodDefinition method)
: this(method.Handle, method.Module)
{
}
public GenericContext(TypeDefinitionHandle declaringType, PEFile module)
{
this.module = module;
this.declaringType = declaringType;
}
public GenericContext(TypeDefinition declaringType)
: this(declaringType.Handle, declaringType.Module)
{
}
public string GetGenericTypeParameterName(int index)
{
GenericParameterHandle genericParameter = GetGenericTypeParameterHandleOrNull(index);

36
ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs

@ -104,42 +104,6 @@ namespace ICSharpCode.Decompiler.Metadata @@ -104,42 +104,6 @@ namespace ICSharpCode.Decompiler.Metadata
&& (name == ".cctor" || name == ".ctor");
}
public static bool HasMatchingDefaultMemberAttribute(this PropertyDefinitionHandle handle, PEFile module, out CustomAttributeHandle defaultMemberAttribute)
{
defaultMemberAttribute = default(CustomAttributeHandle);
var metadata = module.Metadata;
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)
{
return type.GetDefaultMemberName(reader, out var attr);

50
ICSharpCode.Decompiler/Metadata/MetadataResolver.cs

@ -68,13 +68,13 @@ namespace ICSharpCode.Decompiler.Metadata @@ -68,13 +68,13 @@ namespace ICSharpCode.Decompiler.Metadata
public static class MetadataResolver
{
public static TypeDefinition ResolveType(EntityHandle handle, IMetadataResolveContext context)
public static (PEFile Module, TypeDefinitionHandle Handle) ResolveType(EntityHandle handle, IMetadataResolveContext context)
{
if (handle.IsNil)
return default;
switch (handle.Kind) {
case HandleKind.TypeDefinition:
return new TypeDefinition(context.CurrentModule, (TypeDefinitionHandle)handle);
return (context.CurrentModule, (TypeDefinitionHandle)handle);
case HandleKind.TypeReference:
return Resolve((TypeReferenceHandle)handle, context);
case HandleKind.TypeSpecification:
@ -84,39 +84,39 @@ namespace ICSharpCode.Decompiler.Metadata @@ -84,39 +84,39 @@ namespace ICSharpCode.Decompiler.Metadata
}
}
public static MethodDefinition ResolveAsMethod(EntityHandle handle, IMetadataResolveContext context)
public static (PEFile Module, MethodDefinitionHandle Handle) ResolveAsMethod(EntityHandle handle, IMetadataResolveContext context)
{
if (handle.IsNil)
return default;
switch (handle.Kind) {
case HandleKind.MethodDefinition:
return new MethodDefinition(context.CurrentModule, (MethodDefinitionHandle)handle);
return (context.CurrentModule, (MethodDefinitionHandle)handle);
case HandleKind.MemberReference:
var resolved = ((MemberReferenceHandle)handle).Resolve(context);
if (resolved is MethodDefinition m)
return m;
if (resolved.Handle.Kind == HandleKind.MethodDefinition)
return (resolved.Module, (MethodDefinitionHandle)resolved.Handle);
return default;
case HandleKind.MethodSpecification:
resolved = ((MethodSpecificationHandle)handle).Resolve(context);
if (resolved is MethodDefinition m2)
return m2;
if (resolved.Handle.Kind == HandleKind.MethodDefinition)
return (resolved.Module, (MethodDefinitionHandle)resolved.Handle);
return default;
default:
throw new NotSupportedException();
}
}
public static FieldDefinition ResolveAsField(EntityHandle handle, IMetadataResolveContext context)
public static (PEFile Module, FieldDefinitionHandle Handle) ResolveAsField(EntityHandle handle, IMetadataResolveContext context)
{
if (handle.IsNil)
return default;
switch (handle.Kind) {
case HandleKind.FieldDefinition:
return new FieldDefinition(context.CurrentModule, (FieldDefinitionHandle)handle);
return (context.CurrentModule, (FieldDefinitionHandle)handle);
case HandleKind.MemberReference:
var resolved = ((MemberReferenceHandle)handle).Resolve(context);
if (resolved is FieldDefinition m)
return m;
if (resolved.Handle.Kind == HandleKind.FieldDefinition)
return (resolved.Module, (FieldDefinitionHandle)resolved.Handle);
return default;
default:
throw new NotSupportedException();
@ -126,7 +126,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -126,7 +126,7 @@ namespace ICSharpCode.Decompiler.Metadata
/// <summary>
/// Implements resolving of TypeReferences to TypeDefinitions as decribed in II.7.3 of ECMA-335 6th edition.
/// </summary>
public static TypeDefinition Resolve(this TypeReferenceHandle handle, IMetadataResolveContext context)
public static (PEFile Module, TypeDefinitionHandle Handle) Resolve(this TypeReferenceHandle handle, IMetadataResolveContext context)
{
if (handle.IsNil)
return default;
@ -150,14 +150,14 @@ namespace ICSharpCode.Decompiler.Metadata @@ -150,14 +150,14 @@ namespace ICSharpCode.Decompiler.Metadata
switch (tr.ResolutionScope.Kind) {
case HandleKind.TypeReference:
var outerType = Resolve((TypeReferenceHandle)tr.ResolutionScope, context);
if (outerType == null)
if (outerType.Module == null)
throw new NotSupportedException();
var td = outerType.Module.Metadata.GetTypeDefinition(outerType.Handle);
var name = metadata.GetString(tr.Name);
foreach (var nestedType in td.GetNestedTypes()) {
var nestedTypeDef = outerType.Module.Metadata.GetTypeDefinition(nestedType);
if (outerType.Module.Metadata.GetString(nestedTypeDef.Name) == name)
return new TypeDefinition(outerType.Module, nestedType);
return (outerType.Module, nestedType);
}
break;
case HandleKind.ModuleReference:
@ -167,7 +167,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -167,7 +167,7 @@ namespace ICSharpCode.Decompiler.Metadata
}
throw new NotSupportedException();
TypeDefinition ResolveTypeInOtherAssembly(AssemblyReferenceHandle asm, string ns, string typeName)
(PEFile Module, TypeDefinitionHandle Handle) ResolveTypeInOtherAssembly(AssemblyReferenceHandle asm, string ns, string typeName)
{
var module = context.ResolveAssembly(new AssemblyReference(context.CurrentModule, asm));
if (module == null)
@ -176,7 +176,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -176,7 +176,7 @@ namespace ICSharpCode.Decompiler.Metadata
Debug.Assert(@namespace != null);
var type = FindTypeInNamespace(module.Metadata, @namespace.Value, typeName);
Debug.Assert(!type.IsNil);
return new TypeDefinition(module, type);
return (module, type);
}
}
@ -210,7 +210,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -210,7 +210,7 @@ namespace ICSharpCode.Decompiler.Metadata
return default;
}
public static IMetadataEntity Resolve(this MemberReferenceHandle handle, IMetadataResolveContext context)
static (PEFile Module, EntityHandle Handle) Resolve(this MemberReferenceHandle handle, IMetadataResolveContext context)
{
var metadata = context.CurrentModule.Metadata;
var mr = metadata.GetMemberReference(handle);
@ -225,7 +225,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -225,7 +225,7 @@ namespace ICSharpCode.Decompiler.Metadata
break;
case HandleKind.TypeReference:
var resolvedTypeReference = Resolve((TypeReferenceHandle)mr.Parent, context);
if (resolvedTypeReference.IsNil)
if (resolvedTypeReference.Module == null)
return default;
targetModule = resolvedTypeReference.Module;
targetMetadata = targetModule.Metadata;
@ -233,7 +233,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -233,7 +233,7 @@ namespace ICSharpCode.Decompiler.Metadata
break;
case HandleKind.TypeSpecification:
resolvedTypeReference = Resolve((TypeSpecificationHandle)mr.Parent, context);
if (resolvedTypeReference.IsNil)
if (resolvedTypeReference.Module == null)
return default;
targetModule = resolvedTypeReference.Module;
targetMetadata = targetModule.Metadata;
@ -251,7 +251,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -251,7 +251,7 @@ namespace ICSharpCode.Decompiler.Metadata
foreach (var f in declaringType.GetFields()) {
var fd = targetMetadata.GetFieldDefinition(f);
if (targetMetadata.StringComparer.Equals(fd.Name, name))
return new FieldDefinition(targetModule, f);
return (targetModule, f);
}
return default;
case MemberReferenceKind.Method:
@ -263,7 +263,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -263,7 +263,7 @@ namespace ICSharpCode.Decompiler.Metadata
}
foreach (var (method, signature) in candidates) {
if (SignatureBlobComparer.EqualsMethodSignature(targetMetadata.GetBlobReader(signature), metadata.GetBlobReader(mr.Signature), targetMetadata, metadata))
return new MethodDefinition(targetModule, method);
return (targetModule, method);
}
return default;
default:
@ -271,7 +271,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -271,7 +271,7 @@ namespace ICSharpCode.Decompiler.Metadata
}
}
public static TypeDefinition Resolve(this TypeSpecificationHandle handle, IMetadataResolveContext context)
public static (PEFile Module, TypeDefinitionHandle Handle) Resolve(this TypeSpecificationHandle handle, IMetadataResolveContext context)
{
var metadata = context.CurrentModule.Metadata;
var ts = metadata.GetTypeSpecification(handle);
@ -280,7 +280,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -280,7 +280,7 @@ namespace ICSharpCode.Decompiler.Metadata
return default;
switch (unspecialized.Kind) {
case HandleKind.TypeDefinition:
return new TypeDefinition(context.CurrentModule, (TypeDefinitionHandle)unspecialized);
return (context.CurrentModule, (TypeDefinitionHandle)unspecialized);
case HandleKind.TypeReference:
return Resolve((TypeReferenceHandle)unspecialized, context);
default:
@ -288,7 +288,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -288,7 +288,7 @@ namespace ICSharpCode.Decompiler.Metadata
}
}
public static MethodDefinition Resolve(this MethodSpecificationHandle handle, IMetadataResolveContext context)
public static (PEFile Module, MethodDefinitionHandle Handle) Resolve(this MethodSpecificationHandle handle, IMetadataResolveContext context)
{
var metadata = context.CurrentModule.Metadata;
var ms = metadata.GetMethodSpecification(handle);

1
ICSharpCode.Decompiler/Metadata/PEFile.cs

@ -85,7 +85,6 @@ namespace ICSharpCode.Decompiler.Metadata @@ -85,7 +85,6 @@ namespace ICSharpCode.Decompiler.Metadata
}
public ImmutableArray<AssemblyReference> AssemblyReferences => Metadata.AssemblyReferences.Select(r => new AssemblyReference(this, r)).ToImmutableArray();
public ImmutableArray<TypeDefinition> TopLevelTypeDefinitions => Metadata.GetTopLevelTypeDefinitions().Select(t => new TypeDefinition(this, t)).ToImmutableArray();
public ImmutableArray<Resource> Resources => GetResources().ToImmutableArray();
IEnumerable<Resource> GetResources()

3
ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs

@ -69,7 +69,8 @@ namespace ICSharpCode.Decompiler.Metadata @@ -69,7 +69,8 @@ namespace ICSharpCode.Decompiler.Metadata
public string TargetFramework { get; }
public UniversalAssemblyResolver(string mainAssemblyFileName, bool throwOnError, string targetFramework, PEStreamOptions options)
public UniversalAssemblyResolver(string mainAssemblyFileName, bool throwOnError, string targetFramework,
PEStreamOptions options = PEStreamOptions.Default)
{
this.options = options;
this.TargetFramework = targetFramework;

25
ICSharpCode.Decompiler/Output/ITextOutput.cs

@ -17,6 +17,10 @@ @@ -17,6 +17,10 @@
// DEALINGS IN THE SOFTWARE.
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler
{
public interface ITextOutput
@ -50,5 +54,26 @@ namespace ICSharpCode.Decompiler @@ -50,5 +54,26 @@ namespace ICSharpCode.Decompiler
{
output.WriteLine(string.Format(format, args));
}
public static void WriteReference(this ITextOutput output, PEFile module, EntityHandle handle, string text, bool isDefinition = false)
{
output.Write(text);
}
public static void WriteReference(this ITextOutput output, IType type, string text, bool isDefinition = false)
{
output.Write(text);
}
public static void WriteReference(this ITextOutput output, IMember member, string text, bool isDefinition = false)
{
output.Write(text);
}
public static void WriteLocalReference(this ITextOutput output, string text, object reference, bool isDefinition = false)
{
output.Write(text);
}
}
}

3
ICSharpCode.Decompiler/Output/PlainTextOutput.cs

@ -18,7 +18,10 @@ @@ -18,7 +18,10 @@
using System;
using System.IO;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler
{

82
ICSharpCode.Decompiler/Output/TextTokenWriter.cs

@ -63,21 +63,23 @@ namespace ICSharpCode.Decompiler @@ -63,21 +63,23 @@ namespace ICSharpCode.Decompiler
}
var definition = GetCurrentDefinition();
if (definition != null) {
IMetadataEntity entity = SymbolToMetadata(definition);
if (entity != null) {
output.WriteDefinition(identifier.Name, entity, false);
switch (definition) {
case IType t:
output.WriteReference(t, identifier.Name, true);
return;
case IMember m:
output.WriteReference(m, identifier.Name, true);
return;
}
}
var member = GetCurrentMemberReference();
if (member != null) {
IMetadataEntity entity = SymbolToMetadata(member);
if (entity != null) {
output.WriteReference(identifier.Name, entity);
switch (member) {
case IType t:
output.WriteReference(t, identifier.Name, false);
return;
case IMember m:
output.WriteReference(m, identifier.Name, false);
return;
}
}
var localDefinition = GetCurrentLocalDefinition();
@ -100,35 +102,6 @@ namespace ICSharpCode.Decompiler @@ -100,35 +102,6 @@ namespace ICSharpCode.Decompiler
output.Write(identifier.Name);
}
IMetadataEntity SymbolToMetadata(ISymbol symbol)
{
switch (symbol) {
case IType type:
var definition = type.GetDefinition();
if (definition == null || definition.MetadataToken.IsNil)
return null;
return new TypeDefinition(typeSystem.GetModuleDefinition(definition.ParentAssembly), (SRM.TypeDefinitionHandle)definition.MetadataToken);
case IMethod method:
if (method.MetadataToken.IsNil)
return null;
return new MethodDefinition(typeSystem.GetModuleDefinition(method.ParentAssembly), (SRM.MethodDefinitionHandle)method.MetadataToken);
case IProperty property:
if (property.MetadataToken.IsNil)
return null;
return new PropertyDefinition(typeSystem.GetModuleDefinition(property.ParentAssembly), (SRM.PropertyDefinitionHandle)property.MetadataToken);
case IEvent @event:
if (@event.MetadataToken.IsNil)
return null;
return new EventDefinition(typeSystem.GetModuleDefinition(@event.ParentAssembly), (SRM.EventDefinitionHandle)@event.MetadataToken);
case IField field:
if (field.MetadataToken.IsNil)
return null;
return new FieldDefinition(typeSystem.GetModuleDefinition(field.ParentAssembly), (SRM.FieldDefinitionHandle)field.MetadataToken);
default:
return null;
}
}
ISymbol GetCurrentMemberReference()
{
AstNode node = nodeStack.Peek();
@ -219,11 +192,8 @@ namespace ICSharpCode.Decompiler @@ -219,11 +192,8 @@ namespace ICSharpCode.Decompiler
//To make reference for 'this' and 'base' keywords in the ClassName():this() expression
if (role == ConstructorInitializer.ThisKeywordRole || role == ConstructorInitializer.BaseKeywordRole) {
if (nodeStack.Peek() is ConstructorInitializer initializer && initializer.GetSymbol() is IMember member) {
var entity = SymbolToMetadata(member);
if (entity != null) {
output.WriteReference(keyword, entity);
return;
}
output.WriteReference(member, keyword);
return;
}
}
output.Write(keyword);
@ -254,11 +224,18 @@ namespace ICSharpCode.Decompiler @@ -254,11 +224,18 @@ namespace ICSharpCode.Decompiler
break;
default:
// Attach member reference to token only if there's no identifier in the current node.
var member = SymbolToMetadata(GetCurrentMemberReference());
var member = GetCurrentMemberReference();
var node = nodeStack.Peek();
if (member != null && node.GetChildByRole(Roles.Identifier).IsNull)
output.WriteReference(token, member);
else
if (member != null && node.GetChildByRole(Roles.Identifier).IsNull) {
switch (member) {
case IType t:
output.WriteReference(t, token, false);
return;
case IMember m:
output.WriteReference(m, token, false);
return;
}
} else
output.Write(token);
break;
}
@ -368,7 +345,14 @@ namespace ICSharpCode.Decompiler @@ -368,7 +345,14 @@ namespace ICSharpCode.Decompiler
symbol = nodeStack.Peek().GetSymbol();
}
if (symbol == null) goto default;
output.WriteReference(type, SymbolToMetadata(symbol));
switch (symbol) {
case IType t:
output.WriteReference(t, type, false);
return;
case IMember m:
output.WriteReference(m, type, false);
return;
}
break;
default:
output.Write(type);

3
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataTypeDefinition.cs

@ -213,9 +213,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -213,9 +213,10 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
var metadata = assembly.metadata;
var methodsCollection = metadata.GetTypeDefinition(handle).GetMethods();
var methodsList = new List<IMethod>(methodsCollection.Count);
var methodSemantics = assembly.PEFile.MethodSemanticsLookup;
foreach (MethodDefinitionHandle h in methodsCollection) {
var md = metadata.GetMethodDefinition(h);
if (assembly.IsVisible(md.Attributes)) {
if (methodSemantics.GetSemantics(h).Item2 == 0 && assembly.IsVisible(md.Attributes)) {
methodsList.Add(assembly.GetDefinition(h));
}
}

2
ICSharpCode.Decompiler/TypeSystem/MetadataAssembly.cs

@ -38,7 +38,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -38,7 +38,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
public class MetadataAssembly : IAssembly
{
public ICompilation Compilation { get; }
internal readonly Metadata.PEFile PEFile;
public readonly Metadata.PEFile PEFile;
internal readonly MetadataReader metadata;
readonly TypeSystemOptions options;
internal readonly TypeProvider TypeProvider;

1
ILSpy.BamlDecompiler.Tests/BamlTestRunner.cs

@ -123,7 +123,6 @@ namespace ILSpy.BamlDecompiler.Tests @@ -123,7 +123,6 @@ namespace ILSpy.BamlDecompiler.Tests
XDocument document = BamlResourceEntryNode.LoadIntoDocument(module, bamlStream, CancellationToken.None);
XamlIsEqual(File.ReadAllText(sourcePath), document.ToString());
}
}

34
ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs

@ -3,16 +3,14 @@ @@ -3,16 +3,14 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection.Metadata;
using System.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.Documentation;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.IL.Transforms;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util;
using Metadata = ICSharpCode.Decompiler.Metadata;
@ -31,36 +29,34 @@ namespace ILSpy.BamlDecompiler @@ -31,36 +29,34 @@ namespace ILSpy.BamlDecompiler
/// </summary>
sealed class ConnectMethodDecompiler
{
public List<(LongSet, EventRegistration[])> DecompileEventMappings(Metadata.PEFile module, string fullTypeName, CancellationToken cancellationToken)
public List<(LongSet, EventRegistration[])> DecompileEventMappings(Metadata.PEFile module,
string fullTypeName, CancellationToken cancellationToken)
{
var result = new List<(LongSet, EventRegistration[])>();
var typeSystem = new DecompilerTypeSystem(module);
var typeDefinition = (Metadata.TypeDefinition)XmlDocKeyProvider.FindMemberByKey(module, "T:" + fullTypeName);
if (typeDefinition.IsNil)
var typeDefinition = typeSystem.Compilation.FindType(new FullTypeName(fullTypeName)).GetDefinition();
if (typeDefinition == null)
return result;
var metadata = module.Metadata;
TypeDefinition type = metadata.GetTypeDefinition(typeDefinition.Handle);
MethodDefinition method = default;
MethodDefinitionHandle handle = default;
IMethod method = null;
MethodDefinition metadataEntry = default;
foreach (var h in type.GetMethods()) {
var m = metadata.GetMethodDefinition(h);
if (metadata.GetString(m.Name) == "System.Windows.Markup.IComponentConnector.Connect") {
handle = h;
foreach (var m in typeDefinition.GetMethods()) {
if (m.Name == "System.Windows.Markup.IComponentConnector.Connect") {
method = m;
metadataEntry = module.Metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken);
break;
}
}
if (handle.IsNil)
if (method == null || metadataEntry.RelativeVirtualAddress <= 0)
return result;
// decompile method and optimize the switch
var typeSystem = new DecompilerTypeSystem(typeDefinition.Module);
var ilReader = new ILReader(typeSystem);
var function = ilReader.ReadIL(typeDefinition.Module, handle, typeDefinition.Module.Reader.GetMethodBody(method.RelativeVirtualAddress), cancellationToken);
var function = ilReader.ReadIL(module, (MethodDefinitionHandle)method.MetadataToken,
module.Reader.GetMethodBody(metadataEntry.RelativeVirtualAddress), cancellationToken);
var context = new ILTransformContext(function, typeSystem) {
CancellationToken = cancellationToken

4
ILSpy/AnalyzerTreeView.cs

@ -86,7 +86,7 @@ namespace ICSharpCode.ILSpy @@ -86,7 +86,7 @@ namespace ICSharpCode.ILSpy
public void ShowOrFocus(AnalyzerTreeNode node)
{
if (node is AnalyzerEntityTreeNode) {
/*if (node is AnalyzerEntityTreeNode) {
var an = node as AnalyzerEntityTreeNode;
var found = this.Root.Children.OfType<AnalyzerEntityTreeNode>().FirstOrDefault(n => n.Member == an.Member);
if (found != null) {
@ -98,7 +98,7 @@ namespace ICSharpCode.ILSpy @@ -98,7 +98,7 @@ namespace ICSharpCode.ILSpy
return;
}
}
Show(node);
Show(node);*/
}
void IPane.Closed()

2
ILSpy/Commands/DecompileAllCommand.cs

@ -45,7 +45,7 @@ namespace ICSharpCode.ILSpy @@ -45,7 +45,7 @@ namespace ICSharpCode.ILSpy
Exception exception = null;
using (var writer = new System.IO.StreamWriter("c:\\temp\\decompiled\\" + asm.ShortName + ".cs")) {
try {
new CSharpLanguage().DecompileAssembly(asm, new Decompiler.PlainTextOutput(writer), new DecompilationOptions() { FullDecompilation = true, CancellationToken = ct });
//new CSharpLanguage().DecompileAssembly(asm, new Decompiler.PlainTextOutput(writer), new DecompilationOptions() { FullDecompilation = true, CancellationToken = ct });
}
catch (Exception ex) {
writer.WriteLine(ex.ToString());

14
ILSpy/DebugSteps.xaml.cs

@ -7,10 +7,6 @@ using ICSharpCode.Decompiler.IL.Transforms; @@ -7,10 +7,6 @@ using ICSharpCode.Decompiler.IL.Transforms;
namespace ICSharpCode.ILSpy
{
/// <summary>
/// Interaktionslogik für DebugSteps.xaml
/// </summary>
public partial class DebugSteps : UserControl, IPane
{
static readonly ILAstWritingOptions writingOptions = new ILAstWritingOptions {
@ -20,7 +16,7 @@ namespace ICSharpCode.ILSpy @@ -20,7 +16,7 @@ namespace ICSharpCode.ILSpy
public static ILAstWritingOptions Options => writingOptions;
#if DEBUG
#if false
ILAstLanguage language;
#endif
@ -28,7 +24,7 @@ namespace ICSharpCode.ILSpy @@ -28,7 +24,7 @@ namespace ICSharpCode.ILSpy
{
InitializeComponent();
#if DEBUG
#if false
MainWindow.Instance.SessionSettings.FilterSettings.PropertyChanged += FilterSettings_PropertyChanged;
MainWindow.Instance.SelectionChanged += SelectionChanged;
writingOptions.PropertyChanged += WritingOptions_PropertyChanged;
@ -56,7 +52,7 @@ namespace ICSharpCode.ILSpy @@ -56,7 +52,7 @@ namespace ICSharpCode.ILSpy
private void FilterSettings_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
#if DEBUG
#if false
if (e.PropertyName == "Language") {
if (language != null) {
language.StepperUpdated -= ILAstStepperUpdated;
@ -72,7 +68,7 @@ namespace ICSharpCode.ILSpy @@ -72,7 +68,7 @@ namespace ICSharpCode.ILSpy
private void ILAstStepperUpdated(object sender, EventArgs e)
{
#if DEBUG
#if false
if (language == null) return;
Dispatcher.Invoke(() => {
tree.ItemsSource = language.Stepper.Steps;
@ -88,7 +84,7 @@ namespace ICSharpCode.ILSpy @@ -88,7 +84,7 @@ namespace ICSharpCode.ILSpy
void IPane.Closed()
{
#if DEBUG
#if false
MainWindow.Instance.SessionSettings.FilterSettings.PropertyChanged -= FilterSettings_PropertyChanged;
MainWindow.Instance.SelectionChanged -= SelectionChanged;
writingOptions.PropertyChanged -= WritingOptions_PropertyChanged;

14
ILSpy/ILSpy.csproj

@ -113,8 +113,6 @@ @@ -113,8 +113,6 @@
</Compile>
<Compile Include="ILSpyTraceListener.cs" />
<Compile Include="Languages\CodeMappingInfo.cs" />
<Compile Include="Languages\CSharpILMixedLanguage.cs" />
<Compile Include="Languages\CSharpLanguage.cs" />
<Compile Include="DecompilationOptions.cs" />
<Compile Include="ExtensionMethods.cs" />
<Compile Include="FilterSettings.cs" />
@ -124,7 +122,6 @@ @@ -124,7 +122,6 @@
<Compile Include="ContextMenuEntry.cs" />
<Compile Include="Languages\CSharpLexer.cs" />
<Compile Include="Languages\CSharpHighlightingTokenWriter.cs" />
<Compile Include="Languages\ILAstLanguage.cs" />
<Compile Include="ILSpySettings.cs" />
<Compile Include="Images\AccessOverlayIcon.cs" />
<Compile Include="Images\MemberIcon.cs" />
@ -190,17 +187,6 @@ @@ -190,17 +187,6 @@
<Compile Include="TextView\FoldingCommands.cs" />
<Compile Include="TextView\XmlDocRenderer.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzeContextMenuEntry.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedFieldAccessTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedFieldTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedMethodTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedMethodUsedByTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedMethodUsesTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedPropertyAccessorTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedPropertyTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedTypeInstantiationsTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedTypeTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzedTypeUsedByTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzerEntityTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzerSearchTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\AnalyzerTreeNode.cs" />
<Compile Include="TreeNodes\Analyzer\Extensions.cs" />

3
ILSpy/Languages/CodeMappingInfo.cs

@ -30,7 +30,8 @@ namespace ICSharpCode.ILSpy @@ -30,7 +30,8 @@ namespace ICSharpCode.ILSpy
public bool ShowMember(EntityHandle entity)
{
return Language.ShowMember(new Decompiler.Metadata.Entity(Module, entity));
throw null;
//return Language.ShowMember(new Decompiler.Metadata.Entity(Module, entity));
}
public IEnumerable<MethodDefinitionHandle> GetMethodParts(MethodDefinitionHandle method)

46
ILSpy/Languages/ILLanguage.cs

@ -26,6 +26,7 @@ using System.IO; @@ -26,6 +26,7 @@ using System.IO;
using System.Reflection.Metadata.Ecma335;
using System.Linq;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy
{
@ -59,32 +60,33 @@ namespace ICSharpCode.ILSpy @@ -59,32 +60,33 @@ namespace ICSharpCode.ILSpy
};
}
public override void DecompileMethod(Decompiler.Metadata.MethodDefinition method, ITextOutput output, DecompilationOptions options)
public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options)
{
var dis = CreateDisassembler(output, options);
dis.DisassembleMethod(method.Module, method.Handle);
dis.DisassembleMethod(((MetadataAssembly)method.ParentAssembly).PEFile, (MethodDefinitionHandle)method.MetadataToken);
}
public override void DecompileField(Decompiler.Metadata.FieldDefinition field, ITextOutput output, DecompilationOptions options)
public override void DecompileField(IField field, ITextOutput output, DecompilationOptions options)
{
var dis = CreateDisassembler(output, options);
dis.DisassembleField(field);
dis.DisassembleField(((MetadataAssembly)field.ParentAssembly).PEFile, (FieldDefinitionHandle)field.MetadataToken);
}
public override void DecompileProperty(Decompiler.Metadata.PropertyDefinition property, ITextOutput output, DecompilationOptions options)
public override void DecompileProperty(IProperty property, ITextOutput output, DecompilationOptions options)
{
var dis = CreateDisassembler(output, options);
dis.DisassembleProperty(property);
var pd = property.Module.Metadata.GetPropertyDefinition(property.Handle);
PEFile module = ((MetadataAssembly)property.ParentAssembly).PEFile;
dis.DisassembleProperty(module, (PropertyDefinitionHandle)property.MetadataToken);
var pd = module.Metadata.GetPropertyDefinition((PropertyDefinitionHandle)property.MetadataToken);
var accessors = pd.GetAccessors();
if (!accessors.Getter.IsNil) {
output.WriteLine();
dis.DisassembleMethod(property.Module, accessors.Getter);
dis.DisassembleMethod(module, accessors.Getter);
}
if (!accessors.Setter.IsNil) {
output.WriteLine();
dis.DisassembleMethod(property.Module, accessors.Setter);
dis.DisassembleMethod(module, accessors.Setter);
}
/*foreach (var m in property.OtherMethods) {
output.WriteLine();
@ -92,25 +94,25 @@ namespace ICSharpCode.ILSpy @@ -92,25 +94,25 @@ namespace ICSharpCode.ILSpy
}*/
}
public override void DecompileEvent(Decompiler.Metadata.EventDefinition ev, ITextOutput output, DecompilationOptions options)
public override void DecompileEvent(IEvent ev, ITextOutput output, DecompilationOptions options)
{
var dis = CreateDisassembler(output, options);
var metadata = ev.Module.Metadata;
dis.DisassembleEvent(ev.Module, ev.Handle);
PEFile module = ((MetadataAssembly)ev.ParentAssembly).PEFile;
dis.DisassembleEvent(module, (EventDefinitionHandle)ev.MetadataToken);
var ed = metadata.GetEventDefinition(ev.Handle);
var ed = ((MetadataReader)module.Metadata).GetEventDefinition((EventDefinitionHandle)ev.MetadataToken);
var accessors = ed.GetAccessors();
if (!accessors.Adder.IsNil) {
output.WriteLine();
dis.DisassembleMethod(ev.Module, accessors.Adder);
dis.DisassembleMethod(module, accessors.Adder);
}
if (!accessors.Remover.IsNil) {
output.WriteLine();
dis.DisassembleMethod(ev.Module, accessors.Remover);
dis.DisassembleMethod(module, accessors.Remover);
}
if (!accessors.Raiser.IsNil) {
output.WriteLine();
dis.DisassembleMethod(ev.Module, accessors.Raiser);
dis.DisassembleMethod(module, accessors.Raiser);
}
/*foreach (var m in ev.OtherMethods) {
output.WriteLine();
@ -118,16 +120,18 @@ namespace ICSharpCode.ILSpy @@ -118,16 +120,18 @@ namespace ICSharpCode.ILSpy
}*/
}
public override void DecompileType(Decompiler.Metadata.TypeDefinition type, ITextOutput output, DecompilationOptions options)
public override void DecompileType(ITypeDefinition type, ITextOutput output, DecompilationOptions options)
{
var dis = CreateDisassembler(output, options);
dis.DisassembleType(type);
PEFile module = ((MetadataAssembly)type.ParentAssembly).PEFile;
dis.DisassembleType(module, (TypeDefinitionHandle)type.MetadataToken);
}
public override void DecompileNamespace(string nameSpace, IEnumerable<Decompiler.Metadata.TypeDefinition> types, ITextOutput output, DecompilationOptions options)
public override void DecompileNamespace(string nameSpace, IEnumerable<ITypeDefinition> types, ITextOutput output, DecompilationOptions options)
{
var dis = CreateDisassembler(output, options);
dis.DisassembleNamespace(nameSpace, types);
PEFile module = ((MetadataAssembly)types.FirstOrDefault()?.ParentAssembly)?.PEFile;
dis.DisassembleNamespace(nameSpace, module, types.Select(t => (TypeDefinitionHandle)t.MetadataToken));
}
public override void DecompileAssembly(LoadedAssembly assembly, ITextOutput output, DecompilationOptions options)

208
ILSpy/Languages/Language.cs

@ -20,11 +20,10 @@ using System; @@ -20,11 +20,10 @@ using System;
using System.Collections.Generic;
using System.Reflection.PortableExecutable;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Util;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
using static System.Reflection.Metadata.PEReaderExtensions;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.ILSpy
@ -96,42 +95,32 @@ namespace ICSharpCode.ILSpy @@ -96,42 +95,32 @@ namespace ICSharpCode.ILSpy
}
}
public virtual void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options)
public virtual void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options)
{
var metadata = method.Module.Metadata;
var methodDefinition = metadata.GetMethodDefinition(method.Handle);
WriteCommentLine(output, TypeToString(new TypeDefinition(method.Module, methodDefinition.GetDeclaringType()), includeNamespace: true) + "." + metadata.GetString(methodDefinition.Name));
WriteCommentLine(output, TypeToString(method.DeclaringTypeDefinition, includeNamespace: true) + "." + method.Name);
}
public virtual void DecompileProperty(PropertyDefinition property, ITextOutput output, DecompilationOptions options)
public virtual void DecompileProperty(IProperty property, ITextOutput output, DecompilationOptions options)
{
var metadata = property.Module.Metadata;
var propertyDefinition = metadata.GetPropertyDefinition(property.Handle);
var declaringType = metadata.GetMethodDefinition(propertyDefinition.GetAccessors().GetAny()).GetDeclaringType();
WriteCommentLine(output, TypeToString(new TypeDefinition(property.Module, declaringType), includeNamespace: true) + "." + metadata.GetString(propertyDefinition.Name));
WriteCommentLine(output, TypeToString(property.DeclaringTypeDefinition, includeNamespace: true) + "." + property.Name);
}
public virtual void DecompileField(FieldDefinition field, ITextOutput output, DecompilationOptions options)
public virtual void DecompileField(IField field, ITextOutput output, DecompilationOptions options)
{
var metadata = field.Module.Metadata;
var fieldDefinition = metadata.GetFieldDefinition(field.Handle);
WriteCommentLine(output, TypeToString(new TypeDefinition(field.Module, fieldDefinition.GetDeclaringType()), includeNamespace: true) + "." + metadata.GetString(fieldDefinition.Name));
WriteCommentLine(output, TypeToString(field.DeclaringTypeDefinition, includeNamespace: true) + "." + field.Name);
}
public virtual void DecompileEvent(EventDefinition ev, ITextOutput output, DecompilationOptions options)
public virtual void DecompileEvent(IEvent @event, ITextOutput output, DecompilationOptions options)
{
var metadata = ev.Module.Metadata;
var eventDefinition = metadata.GetEventDefinition(ev.Handle);
var declaringType = metadata.GetMethodDefinition(eventDefinition.GetAccessors().GetAny()).GetDeclaringType();
WriteCommentLine(output, TypeToString(new TypeDefinition(ev.Module, declaringType), includeNamespace: true) + "." + metadata.GetString(eventDefinition.Name));
WriteCommentLine(output, TypeToString(@event.DeclaringTypeDefinition, includeNamespace: true) + "." + @event.Name);
}
public virtual void DecompileType(TypeDefinition type, ITextOutput output, DecompilationOptions options)
public virtual void DecompileType(ITypeDefinition type, ITextOutput output, DecompilationOptions options)
{
WriteCommentLine(output, TypeToString(type, includeNamespace: true));
}
public virtual void DecompileNamespace(string nameSpace, IEnumerable<TypeDefinition> types, ITextOutput output, DecompilationOptions options)
public virtual void DecompileNamespace(string nameSpace, IEnumerable<ITypeDefinition> types, ITextOutput output, DecompilationOptions options)
{
WriteCommentLine(output, nameSpace);
}
@ -162,125 +151,52 @@ namespace ICSharpCode.ILSpy @@ -162,125 +151,52 @@ namespace ICSharpCode.ILSpy
/// <summary>
/// Converts a type definition, reference or specification into a string. This method is used by the type tree nodes and search results.
/// </summary>
public virtual string TypeToString(Entity type, GenericContext genericContext = null, bool includeNamespace = true)
public virtual string TypeToString(IType type, bool includeNamespace)
{
var provider = includeNamespace ? ILSignatureProvider.WithNamespace : ILSignatureProvider.WithoutNamespace;
var metadata = type.Module.Metadata;
switch (type.Handle.Kind) {
case SRM.HandleKind.TypeReference:
return provider.GetTypeFromReference(metadata, (SRM.TypeReferenceHandle)type.Handle, 0);
case SRM.HandleKind.TypeDefinition:
var td = metadata.GetTypeDefinition((SRM.TypeDefinitionHandle)type.Handle);
if (includeNamespace) {
var buffer = new System.Text.StringBuilder();
if (!td.GetDeclaringType().IsNil) {
buffer.Append(TypeToString(new TypeDefinition(type.Module, td.GetDeclaringType()), genericContext, includeNamespace));
buffer.Append('+');
} else if (!td.Namespace.IsNil) {
buffer.Append(metadata.GetString(td.Namespace));
buffer.Append('.');
}
buffer.Append(metadata.GetString(td.Name));
return buffer.ToString();
} else {
return metadata.GetString(td.Name);
}
case SRM.HandleKind.TypeSpecification:
return provider.GetTypeFromSpecification(metadata, genericContext ?? GenericContext.Empty, (SRM.TypeSpecificationHandle)type.Handle, 0);
default:
throw new NotSupportedException();
}
if (includeNamespace)
return type.FullName;
else
return type.Name;
}
/// <summary>
/// Converts a member signature to a string.
/// This is used for displaying the tooltip on a member reference.
/// </summary>
public virtual string GetTooltip(Entity entity)
public virtual string GetTooltip(IEntity entity)
{
var metadata = entity.Module.Metadata;
switch (entity.Handle.Kind) {
case SRM.HandleKind.TypeReference:
case SRM.HandleKind.TypeDefinition:
case SRM.HandleKind.TypeSpecification:
return entity.Handle.GetFullTypeName(metadata).ToString();
case SRM.HandleKind.FieldDefinition:
var fieldDefinition = metadata.GetFieldDefinition((SRM.FieldDefinitionHandle)entity.Handle);
string fieldType = fieldDefinition.DecodeSignature(ILSignatureProvider.WithoutNamespace, new GenericContext(fieldDefinition.GetDeclaringType(), entity.Module));
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();
}
return GetDisplayName(entity, true, true);
}
public virtual string FieldToString(FieldDefinition field, bool includeTypeName, bool includeNamespace)
public virtual string FieldToString(IField field, bool includeTypeName, bool includeNamespace)
{
if (field.Handle.IsNil)
if (field == null)
throw new ArgumentNullException(nameof(field));
var metadata = field.Module.Metadata;
var fd = metadata.GetFieldDefinition(field.Handle);
string fieldType = fd.DecodeSignature(ILSignatureProvider.WithoutNamespace, new GenericContext(fd.GetDeclaringType(), field.Module));
string simple = metadata.GetString(fd.Name) + " : " + fieldType;
if (!includeTypeName)
return simple;
var typeName = fd.GetDeclaringType().GetFullTypeName(metadata);
if (!includeNamespace)
return typeName.Name + "." + simple;
return typeName + "." + simple;
return GetDisplayName(field, includeTypeName, includeNamespace) + " : " + TypeToString(field.ReturnType, includeNamespace);
}
public virtual string PropertyToString(PropertyDefinition property, bool includeTypeName, bool includeNamespace, bool? isIndexer = null)
public virtual string PropertyToString(IProperty property, bool includeTypeName, bool includeNamespace, bool? isIndexer = null)
{
if (property.Handle.IsNil)
if (property == null)
throw new ArgumentNullException(nameof(property));
var metadata = property.Module.Metadata;
var pd = metadata.GetPropertyDefinition(property.Handle);
var declaringType = metadata.GetMethodDefinition(pd.GetAccessors().GetAny()).GetDeclaringType();
var signature = pd.DecodeSignature(!includeNamespace ? ILSignatureProvider.WithoutNamespace : ILSignatureProvider.WithNamespace, new GenericContext(declaringType, property.Module));
string simple = metadata.GetString(metadata.GetPropertyDefinition(property.Handle).Name) + " : " + signature.ReturnType;
if (!includeTypeName)
return simple;
var typeName = declaringType.GetFullTypeName(metadata);
if (!includeNamespace)
return typeName.Name + "." + simple;
return typeName + "." + simple;
return GetDisplayName(property, includeTypeName, includeNamespace) + " : " + TypeToString(property.ReturnType, includeNamespace);
}
public virtual string MethodToString(MethodDefinition method, bool includeTypeName, bool includeNamespace)
public virtual string MethodToString(IMethod method, bool includeTypeName, bool includeNamespace)
{
if (method.IsNil)
if (method == null)
throw new ArgumentNullException(nameof(method));
var metadata = method.Module.Metadata;
var md = metadata.GetMethodDefinition(method.Handle);
string name;
if (includeTypeName) {
if (includeNamespace) {
name = md.GetDeclaringType().GetFullTypeName(metadata) + ".";
} else {
name = md.GetDeclaringType().GetFullTypeName(metadata).Name + ".";
}
name += metadata.GetString(md.Name);
} else {
name = metadata.GetString(md.Name);
}
var signature = md.DecodeSignature(includeNamespace ? ILSignatureProvider.WithNamespace : ILSignatureProvider.WithoutNamespace, new GenericContext(method));
int i = 0;
var buffer = new System.Text.StringBuilder(name);
var genericParams = md.GetGenericParameters();
if (genericParams.Count > 0) {
var buffer = new System.Text.StringBuilder();
buffer.Append(GetDisplayName(method, includeTypeName, includeNamespace));
var typeParameters = method.TypeParameters;
if (typeParameters.Count > 0) {
buffer.Append('<');
foreach (var h in genericParams) {
var gp = metadata.GetGenericParameter(h);
foreach (var tp in typeParameters) {
if (i > 0)
buffer.Append(", ");
buffer.Append(metadata.GetString(gp.Name));
buffer.Append(tp.Name);
i++;
}
buffer.Append('>');
@ -288,51 +204,45 @@ namespace ICSharpCode.ILSpy @@ -288,51 +204,45 @@ namespace ICSharpCode.ILSpy
buffer.Append('(');
i = 0;
var parameterHandles = md.GetParameters();
if (signature.RequiredParameterCount > parameterHandles.Count) {
foreach (var type in signature.ParameterTypes) {
if (i > 0)
buffer.Append(", ");
buffer.Append(signature.ParameterTypes[i]);
i++;
}
} else {
foreach (var h in parameterHandles) {
var p = metadata.GetParameter(h);
if (p.SequenceNumber > 0 && i < signature.ParameterTypes.Length) {
if (i > 0)
buffer.Append(", ");
buffer.Append(signature.ParameterTypes[i]);
i++;
}
}
}
if (signature.Header.CallingConvention == SRM.SignatureCallingConvention.VarArgs) {
if (signature.ParameterTypes.Length > 0)
var parameters = method.Parameters;
foreach (var param in parameters) {
if (i > 0)
buffer.Append(", ");
buffer.Append("...");
buffer.Append(TypeToString(param.Type, includeNamespace));
i++;
}
buffer.Append(')');
buffer.Append(" : ");
buffer.Append(signature.ReturnType);
buffer.Append(TypeToString(method.ReturnType, includeNamespace));
return buffer.ToString();
}
public virtual string EventToString(EventDefinition @event, bool includeTypeName, bool includeNamespace)
public virtual string EventToString(IEvent @event, bool includeTypeName, bool includeNamespace)
{
if (@event.IsNil)
if (@event == null)
throw new ArgumentNullException(nameof(@event));
var metadata = @event.Module.Metadata;
var ed = metadata.GetEventDefinition(@event.Handle);
var accessorHandle = ed.GetAccessors().GetAny();
var signature = ed.DecodeSignature(metadata, includeNamespace ? ILSignatureProvider.WithNamespace : ILSignatureProvider.WithoutNamespace, new GenericContext(accessorHandle, @event.Module));
var buffer = new System.Text.StringBuilder();
buffer.Append(metadata.GetString(ed.Name));
buffer.Append(GetDisplayName(@event, includeTypeName, includeNamespace));
buffer.Append(" : ");
buffer.Append(signature);
buffer.Append(TypeToString(@event.ReturnType, includeNamespace));
return buffer.ToString();
}
protected string GetDisplayName(IEntity entity, bool includeTypeName, bool includeNamespace)
{
if (includeTypeName) {
string name;
if (includeNamespace) {
name = entity.DeclaringTypeDefinition.FullName;
} else {
name = entity.DeclaringTypeDefinition.Name;
}
return name + "." + entity.Name;
} else {
return entity.Name;
}
}
/// <summary>
/// Used for WPF keyboard navigation.
/// </summary>
@ -341,7 +251,7 @@ namespace ICSharpCode.ILSpy @@ -341,7 +251,7 @@ namespace ICSharpCode.ILSpy
return Name;
}
public virtual bool ShowMember(IMetadataEntity member)
public virtual bool ShowMember(IEntity member)
{
return true;
}

2
ILSpy/Languages/Languages.cs

@ -45,7 +45,7 @@ namespace ICSharpCode.ILSpy @@ -45,7 +45,7 @@ namespace ICSharpCode.ILSpy
List<Language> languages = new List<Language>();
languages.AddRange(ep.GetExportedValues<Language>());
languages.Sort((a, b) => a.Name.CompareTo(b.Name));
#if DEBUG
#if false
languages.AddRange(ILAstLanguage.GetDebugLanguages());
languages.AddRange(CSharpLanguage.GetDebugLanguages());
#endif

20
ILSpy/LoadedAssembly.cs

@ -25,6 +25,8 @@ using System.Threading; @@ -25,6 +25,8 @@ using System.Threading;
using System.Threading.Tasks;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.ILSpy.DebugInfo;
using ICSharpCode.ILSpy.Options;
@ -85,6 +87,14 @@ namespace ICSharpCode.ILSpy @@ -85,6 +87,14 @@ namespace ICSharpCode.ILSpy
}
}
public ICompilation GetTypeSystem()
{
var module = GetPEFileOrNull();
if (module == null)
return null;
return new SimpleCompilation(module, MinimalCorlib.Instance);
}
public AssemblyList AssemblyList => assemblyList;
public string FileName => fileName;
@ -193,7 +203,7 @@ namespace ICSharpCode.ILSpy @@ -193,7 +203,7 @@ namespace ICSharpCode.ILSpy
}
}
sealed class MyAssemblyResolver : IAssemblyResolver
sealed class MyAssemblyResolver : Decompiler.Metadata.IAssemblyResolver
{
readonly LoadedAssembly parent;
@ -202,7 +212,7 @@ namespace ICSharpCode.ILSpy @@ -202,7 +212,7 @@ namespace ICSharpCode.ILSpy
this.parent = parent;
}
public PEFile Resolve(IAssemblyReference reference)
public PEFile Resolve(Decompiler.Metadata.IAssemblyReference reference)
{
return parent.LookupReferencedAssembly(reference)?.GetPEFileOrNull();
}
@ -213,7 +223,7 @@ namespace ICSharpCode.ILSpy @@ -213,7 +223,7 @@ namespace ICSharpCode.ILSpy
return new MyAssemblyResolver(this);
}
public LoadedAssembly LookupReferencedAssembly(IAssemblyReference reference)
public LoadedAssembly LookupReferencedAssembly(Decompiler.Metadata.IAssemblyReference reference)
{
if (reference == null)
throw new ArgumentNullException(nameof(reference));
@ -234,9 +244,9 @@ namespace ICSharpCode.ILSpy @@ -234,9 +244,9 @@ namespace ICSharpCode.ILSpy
static Dictionary<string, LoadedAssembly> loadingAssemblies = new Dictionary<string, LoadedAssembly>();
LoadedAssembly LookupReferencedAssemblyInternal(IAssemblyReference fullName, bool isWinRT)
LoadedAssembly LookupReferencedAssemblyInternal(Decompiler.Metadata.IAssemblyReference fullName, bool isWinRT)
{
string GetName(IAssemblyReference name) => isWinRT ? name.Name : name.FullName;
string GetName(Decompiler.Metadata.IAssemblyReference name) => isWinRT ? name.Name : name.FullName;
string file;
LoadedAssembly asm;

34
ILSpy/MainWindow.xaml.cs

@ -34,6 +34,8 @@ using System.Windows.Threading; @@ -34,6 +34,8 @@ using System.Windows.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Documentation;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.TreeView;
@ -287,8 +289,8 @@ namespace ICSharpCode.ILSpy @@ -287,8 +289,8 @@ namespace ICSharpCode.ILSpy
foreach (LoadedAssembly asm in commandLineLoadedAssemblies) {
var def = asm.GetPEFileOrNull();
if (def != null) {
var mr = XmlDocKeyProvider.FindMemberByKey(def, args.NavigateTo);
if (!mr.IsNil) {
var mr = XmlDocKeyProvider.FindEntity(args.NavigateTo, new SimpleCompilation(def, MinimalCorlib.Instance).TypeResolveContext);
if (mr != null) {
found = true;
// Defer JumpToReference call to allow an assembly that was loaded while
// resolving a type-forwarder in FindMemberByKey to appear in the assembly list.
@ -599,21 +601,17 @@ namespace ICSharpCode.ILSpy @@ -599,21 +601,17 @@ namespace ICSharpCode.ILSpy
return assemblyListTreeNode.FindAssemblyNode(asm);
case Resource res:
return assemblyListTreeNode.FindResourceNode(res);
case IMetadataEntity entity:
switch (entity) {
case TypeDefinition td:
return assemblyListTreeNode.FindTypeNode(td);
case FieldDefinition fd:
return assemblyListTreeNode.FindFieldNode(fd);
case MethodDefinition md:
return assemblyListTreeNode.FindMethodNode(md);
case PropertyDefinition pd:
return assemblyListTreeNode.FindPropertyNode(pd);
case EventDefinition ed:
return assemblyListTreeNode.FindEventNode(ed);
default:
throw new NotSupportedException();
}
case ITypeDefinition type:
return assemblyListTreeNode.FindTypeNode(type);
case IField fd:
return assemblyListTreeNode.FindFieldNode(fd);
case IMethod md:
return assemblyListTreeNode.FindMethodNode(md);
case IProperty pd:
return assemblyListTreeNode.FindPropertyNode(pd);
case IEvent ed:
return assemblyListTreeNode.FindEventNode(ed);
/*
case TypeReference tr:
var resolved = tr.Handle.Resolve(new SimpleMetadataResolveContext(tr.Module));
if (resolved != null && !resolved.IsNil)
@ -647,7 +645,7 @@ namespace ICSharpCode.ILSpy @@ -647,7 +645,7 @@ namespace ICSharpCode.ILSpy
throw new NotSupportedException();
}
}
return null;
return null;*/
default:
return null;
}

9
ILSpy/SearchPane.cs

@ -27,6 +27,7 @@ using System.Windows.Input; @@ -27,6 +27,7 @@ using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy
@ -216,12 +217,12 @@ namespace ICSharpCode.ILSpy @@ -216,12 +217,12 @@ namespace ICSharpCode.ILSpy
try {
var searcher = GetSearchStrategy(searchMode, searchTerm);
foreach (var loadedAssembly in assemblies) {
var module = loadedAssembly.GetPEFileOrNull();
if (module == null)
var typeSystem = loadedAssembly.GetTypeSystem();
if (typeSystem == null)
continue;
CancellationToken cancellationToken = cts.Token;
foreach (var type in module.TopLevelTypeDefinitions) {
foreach (var type in typeSystem.GetTopLevelTypeDefinitions()) {
cancellationToken.ThrowIfCancellationRequested();
searcher.Search(type, language, AddResult);
}
@ -333,7 +334,7 @@ namespace ICSharpCode.ILSpy @@ -333,7 +334,7 @@ namespace ICSharpCode.ILSpy
{
public static readonly System.Collections.Generic.IComparer<SearchResult> Comparer = new SearchResultComparer();
public IMetadataEntity Member { get; set; }
public IEntity Member { get; set; }
public float Fitness { get; set; }
public string Location { get; set; }

157
ILSpy/SearchStrategies.cs

@ -14,6 +14,7 @@ using ILOpCode = System.Reflection.Metadata.ILOpCode; @@ -14,6 +14,7 @@ using ILOpCode = System.Reflection.Metadata.ILOpCode;
using ICSharpCode.Decompiler;
using static System.Reflection.Metadata.PEReaderExtensions;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy
{
@ -43,29 +44,9 @@ namespace ICSharpCode.ILSpy @@ -43,29 +44,9 @@ namespace ICSharpCode.ILSpy
searchTerm = terms;
}
protected float CalculateFitness(IMetadataEntity member)
protected float CalculateFitness(IEntity member)
{
var metadata = member.Module.Metadata;
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();
}
string text = member.Name;
// Probably compiler generated types without meaningful names, show them last
if (text.StartsWith("<")) {
@ -75,36 +56,36 @@ namespace ICSharpCode.ILSpy @@ -75,36 +56,36 @@ namespace ICSharpCode.ILSpy
// Constructors always have the same name in IL:
// Use type name instead
if (text == ".cctor" || text == ".ctor") {
//text = member.DeclaringType.Name;
text = member.DeclaringType.Name;
}
// Ignore generic arguments, it not possible to search based on them either
text = Decompiler.TypeSystem.ReflectionHelper.SplitTypeParameterCountFromReflectionName(text);
text = ReflectionHelper.SplitTypeParameterCountFromReflectionName(text);
return 1.0f / text.Length;
}
protected virtual bool IsMatch(FieldDefinition field, Language language)
protected virtual bool IsMatch(IField field, Language language)
{
return false;
}
protected virtual bool IsMatch(PropertyDefinition property, Language language)
protected virtual bool IsMatch(IProperty property, Language language)
{
return false;
}
protected virtual bool IsMatch(EventDefinition ev, Language language)
protected virtual bool IsMatch(IEvent ev, Language language)
{
return false;
}
protected virtual bool IsMatch(MethodDefinition m, Language language)
protected virtual bool IsMatch(IMethod m, Language language)
{
return false;
}
protected virtual bool MatchName(IMetadataEntity m, Language language)
protected virtual bool MatchName(IEntity m, Language language)
{
return IsMatch(t => GetLanguageSpecificName(language, m, regex != null ? fullNameSearch : t.Contains(".")));
}
@ -178,26 +159,25 @@ namespace ICSharpCode.ILSpy @@ -178,26 +159,25 @@ namespace ICSharpCode.ILSpy
return false;
}
string GetLanguageSpecificName(Language language, IMetadataEntity member, bool fullName = false)
string GetLanguageSpecificName(Language language, IEntity member, bool fullName = false)
{
var metadata = member.Module.Metadata;
switch (member) {
case TypeDefinition t:
case ITypeDefinition t:
return language.TypeToString(t, includeNamespace: fullName);
case FieldDefinition f:
case IField f:
return language.FieldToString(f, fullName, fullName);
case PropertyDefinition p:
return language.PropertyToString(p, fullName, fullName, p.Handle.HasMatchingDefaultMemberAttribute(member.Module, out _));
case MethodDefinition m:
case IProperty p:
return language.PropertyToString(p, fullName, fullName, p.IsIndexer);
case IMethod m:
return language.MethodToString(m, fullName, fullName);
case EventDefinition e:
case IEvent e:
return language.EventToString(e, fullName, fullName);
default:
throw new NotSupportedException(member?.GetType() + " not supported!");
}
}
void Add<T>(Func<IEnumerable<T>> itemsGetter, TypeDefinition type, Language language, Action<SearchResult> addResult, Func<T, Language, bool> matcher, Func<T, ImageSource> image) where T : IMetadataEntity
void Add<T>(Func<IEnumerable<T>> itemsGetter, ITypeDefinition type, Language language, Action<SearchResult> addResult, Func<T, Language, bool> matcher, Func<T, ImageSource> image) where T : IEntity
{
IEnumerable<T> items = Enumerable.Empty<T>();
try {
@ -219,30 +199,18 @@ namespace ICSharpCode.ILSpy @@ -219,30 +199,18 @@ namespace ICSharpCode.ILSpy
}
}
public virtual void Search(TypeDefinition type, Language language, Action<SearchResult> addResult)
public virtual void Search(ITypeDefinition type, Language language, Action<SearchResult> addResult)
{
var metadata = type.Module.Metadata;
var td = metadata.GetTypeDefinition(type.Handle);
Add(() => td.GetFields().Select(f => new FieldDefinition(type.Module, f)), type, language, addResult, IsMatch, FieldTreeNode.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);
Add(() => type.Fields, type, language, addResult, IsMatch, FieldTreeNode.GetIcon);
Add(() => type.Properties, type, language, addResult, IsMatch, p => PropertyTreeNode.GetIcon(p));
Add(() => type.Events, type, language, addResult, IsMatch, EventTreeNode.GetIcon);
Add(() => type.Methods.Where(m => !m.IsAccessor), type, language, addResult, IsMatch, MethodTreeNode.GetIcon);
foreach (var nestedType in td.GetNestedTypes()) {
Search(new TypeDefinition(type.Module, nestedType), language, addResult);
foreach (var nestedType in type.NestedTypes) {
Search(nestedType, language, addResult);
}
}
bool NotSpecialMethod(SRM.MethodDefinitionHandle method, SRM.MetadataReader metadata)
{
return (method.GetMethodSemanticsAttributes(metadata) & (
MethodSemanticsAttributes.Setter
| MethodSemanticsAttributes.Getter
| MethodSemanticsAttributes.Adder
| MethodSemanticsAttributes.Remover
| MethodSemanticsAttributes.Raiser)) == 0;
}
Regex SafeNewRegex(string unsafePattern)
{
try {
@ -265,9 +233,9 @@ namespace ICSharpCode.ILSpy @@ -265,9 +233,9 @@ namespace ICSharpCode.ILSpy
}
}
protected override bool MatchName(IMetadataEntity m, Language language)
protected override bool MatchName(IEntity m, Language language)
{
return SRM.Ecma335.MetadataTokens.GetToken(m.Handle) == searchTermToken;
return SRM.Ecma335.MetadataTokens.GetToken(m.MetadataToken) == searchTermToken;
}
}
@ -308,26 +276,24 @@ namespace ICSharpCode.ILSpy @@ -308,26 +276,24 @@ namespace ICSharpCode.ILSpy
}
}
protected override bool IsMatch(FieldDefinition field, Language language)
protected override bool IsMatch(IField field, Language language)
{
return IsLiteralMatch(field.DecodeConstant());
return IsLiteralMatch(field.ConstantValue);
}
protected override bool IsMatch(PropertyDefinition property, Language language)
protected override bool IsMatch(IProperty property, Language language)
{
var accessors = property.Module.Metadata.GetPropertyDefinition(property.Handle).GetAccessors();
return MethodIsLiteralMatch(accessors.Getter, property.Module) || MethodIsLiteralMatch(accessors.Setter, property.Module);
return MethodIsLiteralMatch(property.Getter) || MethodIsLiteralMatch(property.Setter);
}
protected override bool IsMatch(EventDefinition ev, Language language)
protected override bool IsMatch(IEvent ev, Language language)
{
var accessors = ev.Module.Metadata.GetEventDefinition(ev.Handle).GetAccessors();
return MethodIsLiteralMatch(accessors.Adder, ev.Module) || MethodIsLiteralMatch(accessors.Remover, ev.Module) || MethodIsLiteralMatch(accessors.Raiser, ev.Module);
return MethodIsLiteralMatch(ev.AddAccessor) || MethodIsLiteralMatch(ev.RemoveAccessor) || MethodIsLiteralMatch(ev.InvokeAccessor);
}
protected override bool IsMatch(MethodDefinition m, Language language)
protected override bool IsMatch(IMethod m, Language language)
{
return MethodIsLiteralMatch(m.Handle, m.Module);
return MethodIsLiteralMatch(m);
}
bool IsLiteralMatch(object val)
@ -351,14 +317,15 @@ namespace ICSharpCode.ILSpy @@ -351,14 +317,15 @@ namespace ICSharpCode.ILSpy
}
}
bool MethodIsLiteralMatch(SRM.MethodDefinitionHandle m, PEFile module)
bool MethodIsLiteralMatch(IMethod method)
{
if (module == null)
if (method == null)
return false;
var metadata = module.Metadata;
var module = ((MetadataAssembly)method.ParentAssembly).PEFile;
var m = (SRM.MethodDefinitionHandle)method.MetadataToken;
if (m.IsNil)
return false;
var methodDefinition = metadata.GetMethodDefinition(m);
var methodDefinition = module.Metadata.GetMethodDefinition(m);
if (!methodDefinition.HasBody())
return false;
var blob = module.Reader.GetMethodBody(methodDefinition.RelativeVirtualAddress).GetILReader();
@ -455,7 +422,7 @@ namespace ICSharpCode.ILSpy @@ -455,7 +422,7 @@ namespace ICSharpCode.ILSpy
return true;
break;
case ILOpCode.Ldstr:
if ((string)searchTermLiteralValue == ILParser.DecodeUserString(ref blob, metadata))
if ((string)searchTermLiteralValue == ILParser.DecodeUserString(ref blob, module.Metadata))
return true;
break;
}
@ -467,7 +434,7 @@ namespace ICSharpCode.ILSpy @@ -467,7 +434,7 @@ namespace ICSharpCode.ILSpy
ILParser.SkipOperand(ref blob, code);
continue;
}
if (IsMatch(t => ILParser.DecodeUserString(ref blob, metadata)))
if (base.IsMatch(t => ILParser.DecodeUserString(ref blob, module.Metadata)))
return true;
}
}
@ -499,22 +466,22 @@ namespace ICSharpCode.ILSpy @@ -499,22 +466,22 @@ namespace ICSharpCode.ILSpy
this.searchKind = searchKind;
}
protected override bool IsMatch(FieldDefinition field, Language language)
protected override bool IsMatch(IField field, Language language)
{
return (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Field) && MatchName(field, language);
}
protected override bool IsMatch(PropertyDefinition property, Language language)
protected override bool IsMatch(IProperty property, Language language)
{
return (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Property) && MatchName(property, language);
}
protected override bool IsMatch(EventDefinition ev, Language language)
protected override bool IsMatch(IEvent ev, Language language)
{
return (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Event) && MatchName(ev, language);
}
protected override bool IsMatch(MethodDefinition m, Language language)
protected override bool IsMatch(IMethod m, Language language)
{
return (searchKind == MemberSearchKind.All || searchKind == MemberSearchKind.Method) && MatchName(m, language);
}
@ -527,26 +494,23 @@ namespace ICSharpCode.ILSpy @@ -527,26 +494,23 @@ namespace ICSharpCode.ILSpy
{
}
public override void Search(TypeDefinition type, Language language, Action<SearchResult> addResult)
public override void Search(ITypeDefinition type, Language language, Action<SearchResult> addResult)
{
var metadata = type.Module.Metadata;
var td = metadata.GetTypeDefinition(type.Handle);
if (MatchName(type, language)) {
string name = language.TypeToString(type, includeNamespace: false);
var declaringType = td.GetDeclaringType();
var declaringType = type.DeclaringTypeDefinition;
addResult(new SearchResult {
Member = type,
Fitness = CalculateFitness(type),
Image = TypeTreeNode.GetIcon(type),
Name = name,
LocationImage = !declaringType.IsNil ? TypeTreeNode.GetIcon(new TypeDefinition(type.Module, declaringType)) : Images.Namespace,
Location = !declaringType.IsNil ? language.TypeToString(new TypeDefinition(type.Module, declaringType), includeNamespace: true) : type.Handle.GetFullTypeName(metadata).TopLevelTypeName.Namespace
LocationImage = declaringType != null ? TypeTreeNode.GetIcon(declaringType) : Images.Namespace,
Location = declaringType != null ? language.TypeToString(declaringType, includeNamespace: true) : type.Namespace
});
}
foreach (var nestedType in td.GetNestedTypes()) {
Search(new TypeDefinition(type.Module, nestedType), language, addResult);
foreach (var nestedType in type.NestedTypes) {
Search(nestedType, language, addResult);
}
}
}
@ -558,42 +522,41 @@ namespace ICSharpCode.ILSpy @@ -558,42 +522,41 @@ namespace ICSharpCode.ILSpy
{
}
public override void Search(TypeDefinition type, Language language, Action<SearchResult> addResult)
public override void Search(ITypeDefinition type, Language language, Action<SearchResult> addResult)
{
if (MatchName(type, language))
{
string name = language.TypeToString(type, includeNamespace: false);
var metadata = type.Module.Metadata;
var declaringType = metadata.GetTypeDefinition(type.Handle).GetDeclaringType();
var declaringType = type.DeclaringTypeDefinition;
addResult(new SearchResult {
Member = type,
Image = TypeTreeNode.GetIcon(type),
Fitness = CalculateFitness(type),
Name = name,
LocationImage = !declaringType.IsNil ? TypeTreeNode.GetIcon(new TypeDefinition(type.Module, declaringType)) : Images.Namespace,
Location = !declaringType.IsNil ? language.TypeToString(new TypeDefinition(type.Module, declaringType), includeNamespace: true) : type.Handle.GetFullTypeName(metadata).TopLevelTypeName.Namespace
LocationImage = declaringType != null ? TypeTreeNode.GetIcon(declaringType) : Images.Namespace,
Location = declaringType != null ? language.TypeToString(declaringType, includeNamespace: true) : type.Namespace
});
}
base.Search(type, language, addResult);
}
protected override bool IsMatch(FieldDefinition field, Language language)
protected override bool IsMatch(IField field, Language language)
{
return MatchName(field, language);
}
protected override bool IsMatch(PropertyDefinition property, Language language)
protected override bool IsMatch(IProperty property, Language language)
{
return MatchName(property, language);
}
protected override bool IsMatch(EventDefinition ev, Language language)
protected override bool IsMatch(IEvent ev, Language language)
{
return MatchName(ev, language);
}
protected override bool IsMatch(MethodDefinition m, Language language)
protected override bool IsMatch(IMethod m, Language language)
{
return MatchName(m, language);
}

9
ILSpy/TextView/DecompilerTextView.cs

@ -46,6 +46,7 @@ using ICSharpCode.Decompiler; @@ -46,6 +46,7 @@ using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.Documentation;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.AvalonEdit;
using ICSharpCode.ILSpy.Options;
using ICSharpCode.ILSpy.TreeNodes;
@ -206,14 +207,14 @@ namespace ICSharpCode.ILSpy.TextView @@ -206,14 +207,14 @@ namespace ICSharpCode.ILSpy.TextView
}
}
return $"{code.Name} (0x{code.Code:x})";
} else if (segment.Reference is IMetadataEntity entity) {
} else if (segment.Reference is IEntity entity) {
XmlDocRenderer renderer = new XmlDocRenderer();
renderer.AppendText(MainWindow.Instance.CurrentLanguage.GetTooltip(new Entity(entity.Module, entity.Handle)));
renderer.AppendText(MainWindow.Instance.CurrentLanguage.GetTooltip(entity));
try {
//var docProvider = entity.Module.DocumentationResolver.GetProvider(); // TODO implement proper API
var docProvider = XmlDocLoader.LoadDocumentation(entity.Module);
var docProvider = XmlDocLoader.LoadDocumentation(((MetadataAssembly)entity.ParentAssembly).PEFile);
if (docProvider != null) {
string documentation = docProvider.GetDocumentation(XmlDocKeyProvider.GetKey(new Entity(entity.Module, entity.Handle)));
string documentation = docProvider.GetDocumentation(XmlDocKeyProvider.GetKey(entity));
if (documentation != null) {
renderer.AppendText(Environment.NewLine);
renderer.AddXmlDocumentation(documentation);

13
ILSpy/TreeNodes/Analyzer/AnalyzeContextMenuEntry.cs

@ -18,7 +18,7 @@ @@ -18,7 +18,7 @@
using System;
using System.Linq;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
@ -37,7 +37,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -37,7 +37,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
public bool IsEnabled(TextViewContext context)
{
if (context.SelectedTreeNodes == null)
return context.Reference != null && context.Reference.Reference is IMetadataEntity;
return context.Reference != null && context.Reference.Reference is IEntity;
foreach (IMemberTreeNode node in context.SelectedTreeNodes) {
if (!IsValidReference(node.Member))
return false;
@ -48,11 +48,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -48,11 +48,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
bool IsValidReference(object reference)
{
return reference is IMetadataEntity
|| reference is MemberReference
|| reference is MethodSpecification
|| reference is TypeReference
|| reference is TypeSpecification;
return reference is IEntity;
}
public void Execute(TextViewContext context)
@ -67,7 +63,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -67,7 +63,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
}
public static void Analyze(object member)
{
{/*
switch (member) {
case IMetadataEntity entity:
switch (entity) {
@ -133,6 +129,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -133,6 +129,7 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
}
break;
}
*/
}
}
}

97
ILSpy/TreeNodes/AssemblyListTreeNode.cs

@ -26,6 +26,7 @@ using System.Reflection.PortableExecutable; @@ -26,6 +26,7 @@ using System.Reflection.PortableExecutable;
using System.Windows;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.TreeView;
namespace ICSharpCode.ILSpy.TreeNodes
@ -176,6 +177,13 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -176,6 +177,13 @@ namespace ICSharpCode.ILSpy.TreeNodes
return null;
}
public AssemblyTreeNode FindAssemblyNode(IAssembly module)
{
if (!(module is MetadataAssembly assembly))
return null;
return FindAssemblyNode(assembly.PEFile);
}
public AssemblyTreeNode FindAssemblyNode(PEFile module)
{
if (module == null)
@ -204,17 +212,17 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -204,17 +212,17 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// Looks up the type node corresponding to the type definition.
/// Returns null if no matching node is found.
/// </summary>
public TypeTreeNode FindTypeNode(TypeDefinition def)
public TypeTreeNode FindTypeNode(ITypeDefinition def)
{
var declaringType = def.Module.Metadata.GetTypeDefinition(def.Handle).GetDeclaringType();
if (!declaringType.IsNil) {
TypeTreeNode decl = FindTypeNode(new TypeDefinition(def.Module, declaringType));
var declaringType = def.DeclaringTypeDefinition;
if (declaringType != null) {
TypeTreeNode decl = FindTypeNode(declaringType);
if (decl != null) {
decl.EnsureLazyChildren();
return decl.Children.OfType<TypeTreeNode>().FirstOrDefault(t => t.TypeDefinition == def && !t.IsHidden);
return decl.Children.OfType<TypeTreeNode>().FirstOrDefault(t => t.TypeDefinition.Equals(def) && !t.IsHidden);
}
} else {
AssemblyTreeNode asm = FindAssemblyNode(def.Module);
AssemblyTreeNode asm = FindAssemblyNode(def.ParentAssembly);
if (asm != null) {
return asm.FindTypeNode(def);
}
@ -226,78 +234,79 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -226,78 +234,79 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// Looks up the method node corresponding to the method definition.
/// Returns null if no matching node is found.
/// </summary>
public ILSpyTreeNode FindMethodNode(MethodDefinition def)
public ILSpyTreeNode FindMethodNode(IMethod def)
{
TypeTreeNode typeNode = FindTypeNode(new TypeDefinition(def.Module, def.Module.Metadata.GetMethodDefinition(def.Handle).GetDeclaringType()));
TypeTreeNode typeNode = FindTypeNode(def.DeclaringTypeDefinition);
if (typeNode == null)
return null;
typeNode.EnsureLazyChildren();
MethodTreeNode methodNode = typeNode.Children.OfType<MethodTreeNode>().FirstOrDefault(m => m.MethodDefinition == def && !m.IsHidden);
if (methodNode != null)
return methodNode;
foreach (var p in typeNode.Children.OfType<ILSpyTreeNode>()) {
if (p.IsHidden)
continue;
// method might be a child of a property or event
if (p is PropertyTreeNode || p is EventTreeNode) {
p.EnsureLazyChildren();
methodNode = p.Children.OfType<MethodTreeNode>().FirstOrDefault(m => m.MethodDefinition == def);
if (methodNode != null) {
// If the requested method is a property or event accessor, and accessors are
// hidden in the UI, then return the owning property or event.
if (methodNode.IsHidden)
return p;
else
return methodNode;
}
}
// method might be an accessor, must look for parent node
ILSpyTreeNode parentNode = typeNode;
MethodTreeNode methodNode;
parentNode.EnsureLazyChildren();
switch (def.AccessorOwner) {
case IProperty p:
parentNode = parentNode.Children.OfType<PropertyTreeNode>().FirstOrDefault(m => m.PropertyDefinition.Equals(p));
if (parentNode == null)
return null;
parentNode.EnsureLazyChildren();
methodNode = parentNode.Children.OfType<MethodTreeNode>().FirstOrDefault(m => m.MethodDefinition.Equals(def));
if (methodNode == null || methodNode.IsHidden)
return parentNode;
return methodNode;
case IEvent e:
parentNode = parentNode.Children.OfType<EventTreeNode>().FirstOrDefault(m => m.EventDefinition.Equals(e));
if (parentNode == null)
return null;
parentNode.EnsureLazyChildren();
methodNode = parentNode.Children.OfType<MethodTreeNode>().FirstOrDefault(m => m.MethodDefinition.Equals(def));
if (methodNode == null || methodNode.IsHidden)
return parentNode;
return methodNode;
default:
methodNode = typeNode.Children.OfType<MethodTreeNode>().FirstOrDefault(m => m.MethodDefinition.Equals(def) && !m.IsHidden);
if (methodNode != null)
return methodNode;
return null;
}
return null;
}
/// <summary>
/// Looks up the field node corresponding to the field definition.
/// Returns null if no matching node is found.
/// </summary>
public FieldTreeNode FindFieldNode(FieldDefinition def)
public FieldTreeNode FindFieldNode(IField def)
{
TypeTreeNode typeNode = FindTypeNode(new TypeDefinition(def.Module, def.Module.Metadata.GetFieldDefinition(def.Handle).GetDeclaringType()));
TypeTreeNode typeNode = FindTypeNode(def.DeclaringTypeDefinition);
if (typeNode == null)
return null;
typeNode.EnsureLazyChildren();
return typeNode.Children.OfType<FieldTreeNode>().FirstOrDefault(m => m.FieldDefinition == def && !m.IsHidden);
return typeNode.Children.OfType<FieldTreeNode>().FirstOrDefault(m => m.FieldDefinition.Equals(def) && !m.IsHidden);
}
/// <summary>
/// Looks up the property node corresponding to the property definition.
/// Returns null if no matching node is found.
/// </summary>
public PropertyTreeNode FindPropertyNode(PropertyDefinition def)
public PropertyTreeNode FindPropertyNode(IProperty def)
{
var metadata = def.Module.Metadata;
var accessor = metadata.GetMethodDefinition(metadata.GetPropertyDefinition(def.Handle).GetAccessors().GetAny());
TypeTreeNode typeNode = FindTypeNode(new TypeDefinition(def.Module, accessor.GetDeclaringType()));
TypeTreeNode typeNode = FindTypeNode(def.DeclaringTypeDefinition);
if (typeNode == null)
return null;
typeNode.EnsureLazyChildren();
return typeNode.Children.OfType<PropertyTreeNode>().FirstOrDefault(m => m.PropertyDefinition == def && !m.IsHidden);
return typeNode.Children.OfType<PropertyTreeNode>().FirstOrDefault(m => m.PropertyDefinition.Equals(def) && !m.IsHidden);
}
/// <summary>
/// Looks up the event node corresponding to the event definition.
/// Returns null if no matching node is found.
/// </summary>
public EventTreeNode FindEventNode(EventDefinition def)
public EventTreeNode FindEventNode(IEvent def)
{
var metadata = def.Module.Metadata;
var accessor = metadata.GetMethodDefinition(metadata.GetEventDefinition(def.Handle).GetAccessors().GetAny());
TypeTreeNode typeNode = FindTypeNode(new TypeDefinition(def.Module, accessor.GetDeclaringType()));
TypeTreeNode typeNode = FindTypeNode(def.DeclaringTypeDefinition);
if (typeNode == null)
return null;
typeNode.EnsureLazyChildren();
return typeNode.Children.OfType<EventTreeNode>().FirstOrDefault(m => m.EventDefinition == def && !m.IsHidden);
return typeNode.Children.OfType<EventTreeNode>().FirstOrDefault(m => m.EventDefinition.Equals(def) && !m.IsHidden);
}
#endregion
}

16
ILSpy/TreeNodes/AssemblyTreeNode.cs

@ -41,7 +41,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -41,7 +41,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public sealed class AssemblyTreeNode : ILSpyTreeNode
{
readonly Dictionary<string, NamespaceTreeNode> namespaces = new Dictionary<string, NamespaceTreeNode>();
readonly Dictionary<TypeDefinition, TypeTreeNode> typeDict = new Dictionary<TypeDefinition, TypeTreeNode>();
readonly Dictionary<ITypeDefinition, TypeTreeNode> typeDict = new Dictionary<ITypeDefinition, TypeTreeNode>();
ICompilation typeSystem;
public AssemblyTreeNode(LoadedAssembly assembly)
@ -136,6 +136,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -136,6 +136,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
return;
}
typeSystem = new SimpleCompilation(module, MinimalCorlib.Instance);
var assembly = (MetadataAssembly)typeSystem.MainAssembly;
var metadata = module.Metadata;
this.Children.Add(new ReferenceFolderTreeNode(module, this));
@ -144,13 +145,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -144,13 +145,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
foreach (NamespaceTreeNode ns in namespaces.Values) {
ns.Children.Clear();
}
foreach (var typeHandle in metadata.GetTopLevelTypeDefinitions().OrderBy(t => t.GetFullTypeName(metadata).ToString(), NaturalStringComparer.Instance)) {
NamespaceTreeNode ns;
var type = new TypeDefinition(module, typeHandle);
var namespaceString = metadata.GetString(metadata.GetTypeDefinition(typeHandle).Namespace);
if (!namespaces.TryGetValue(namespaceString, out ns)) {
ns = new NamespaceTreeNode(namespaceString);
namespaces[namespaceString] = ns;
foreach (var type in assembly.TopLevelTypeDefinitions.OrderBy(t => t.FullName, NaturalStringComparer.Instance)) {
if (!namespaces.TryGetValue(type.Namespace, out NamespaceTreeNode ns)) {
ns = new NamespaceTreeNode(type.Namespace);
namespaces[type.Namespace] = ns;
}
TypeTreeNode node = new TypeTreeNode(type, this);
typeDict[type] = node;
@ -167,7 +165,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -167,7 +165,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// <summary>
/// Finds the node for a top-level type.
/// </summary>
public TypeTreeNode FindTypeNode(TypeDefinition def)
public TypeTreeNode FindTypeNode(ITypeDefinition def)
{
if (def == null)
return null;

55
ILSpy/TreeNodes/BaseTypesEntryNode.cs

@ -18,65 +18,70 @@ @@ -18,65 +18,70 @@
using System;
using System.Linq;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.TreeView;
namespace ICSharpCode.ILSpy.TreeNodes
{
sealed class BaseTypesEntryNode : ILSpyTreeNode, IMemberTreeNode
{
readonly Entity tr;
readonly GenericContext context;
readonly PEFile module;
readonly EntityHandle handle;
readonly IType type;
readonly bool isInterface;
readonly bool showExpander;
readonly object icon;
public BaseTypesEntryNode(GenericContext context, Entity entity, bool isInterface)
public BaseTypesEntryNode(PEFile module, EntityHandle handle, IType type, bool isInterface)
{
if (entity.IsNil) throw new ArgumentNullException(nameof(entity));
this.tr = entity;
this.context = context;
if (handle.IsNil)
throw new ArgumentNullException(nameof(handle));
this.module = module ?? throw new ArgumentNullException(nameof(module));
this.handle = handle;
this.type = type;
this.isInterface = isInterface;
this.LazyLoading = true;
showExpander = true;
var td = tr.ResolveAsType();
/*var td = tr.ResolveAsType();
if (!td.IsNil) {
var typeDef = td.Module.Metadata.GetTypeDefinition(td.Handle);
showExpander = !typeDef.BaseType.IsNil || typeDef.GetInterfaceImplementations().Any();
icon = TypeTreeNode.GetIcon(td);
} else {
showExpander = false;
icon = isInterface ? Images.Interface : Images.Class;
}
}*/
}
public override bool ShowExpander => showExpander;
public override object Text
{
get { return this.Language.TypeToString(tr, context, includeNamespace: true) + tr.Handle.ToSuffixString(); }
get { return this.Language.TypeToString(type, includeNamespace: true) + handle.ToSuffixString(); }
}
public override object Icon => icon;
public override object Icon => isInterface ? Images.Interface : Images.Class;
protected override void LoadChildren()
{
var td = tr.ResolveAsType();
if (!td.IsNil) {
BaseTypesTreeNode.AddBaseTypes(this.Children, td);
DecompilerTypeSystem typeSystem = new DecompilerTypeSystem(module);
var t = typeSystem.ResolveAsType(handle).GetDefinition();
if (t != null) {
BaseTypesTreeNode.AddBaseTypes(this.Children, ((MetadataAssembly)t.ParentAssembly).PEFile, t);
}
}
public override void ActivateItem(System.Windows.RoutedEventArgs e)
{
var td = tr.ResolveAsType();
e.Handled = ActivateItem(this, td);
DecompilerTypeSystem typeSystem = new DecompilerTypeSystem(module);
var t = typeSystem.ResolveAsType(handle).GetDefinition();
e.Handled = ActivateItem(this, t);
}
internal static bool ActivateItem(SharpTreeNode node, TypeDefinition def)
internal static bool ActivateItem(SharpTreeNode node, ITypeDefinition def)
{
if (!def.IsNil) {
if (def != null) {
var assemblyListNode = node.Ancestors().OfType<AssemblyListTreeNode>().FirstOrDefault();
if (assemblyListNode != null) {
assemblyListNode.Select(assemblyListNode.FindTypeNode(def));
@ -88,9 +93,15 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -88,9 +93,15 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, language.TypeToString(tr, context, includeNamespace: true));
language.WriteCommentLine(output, language.TypeToString(type, includeNamespace: true));
}
IMetadataEntity IMemberTreeNode.Member => tr;
IEntity IMemberTreeNode.Member {
get {
DecompilerTypeSystem typeSystem = new DecompilerTypeSystem(module);
var t = typeSystem.ResolveAsType(handle).GetDefinition();
return t;
}
}
}
}

33
ILSpy/TreeNodes/BaseTypesTreeNode.cs

@ -17,9 +17,12 @@ @@ -17,9 +17,12 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Linq;
using System.Reflection.Metadata;
using System.Windows.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.TreeView;
namespace ICSharpCode.ILSpy.TreeNodes
@ -29,10 +32,12 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -29,10 +32,12 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary>
sealed class BaseTypesTreeNode : ILSpyTreeNode
{
readonly TypeDefinition type;
readonly PEFile module;
readonly ITypeDefinition type;
public BaseTypesTreeNode(TypeDefinition type)
public BaseTypesTreeNode(PEFile module, ITypeDefinition type)
{
this.module = module;
this.type = type;
this.LazyLoading = true;
}
@ -43,19 +48,23 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -43,19 +48,23 @@ namespace ICSharpCode.ILSpy.TreeNodes
protected override void LoadChildren()
{
AddBaseTypes(this.Children, type);
AddBaseTypes(this.Children, module, type);
}
internal static void AddBaseTypes(SharpTreeNodeCollection children, TypeDefinition type)
internal static void AddBaseTypes(SharpTreeNodeCollection children, PEFile module, ITypeDefinition typeDefinition)
{
var metadata = type.Module.Metadata;
var def = metadata.GetTypeDefinition(type.Handle);
var context = new GenericContext(type);
if (!def.BaseType.IsNil)
children.Add(new BaseTypesEntryNode(context, new Entity(type.Module, def.BaseType), false));
foreach (var i in def.GetInterfaceImplementations()) {
var interfaceImpl = metadata.GetInterfaceImplementation(i);
children.Add(new BaseTypesEntryNode(context, new Entity(type.Module, interfaceImpl.Interface), true));
var typeDef = module.Metadata.GetTypeDefinition((TypeDefinitionHandle)typeDefinition.MetadataToken);
var baseTypes = typeDefinition.DirectBaseTypes.ToArray();
int i = 0;
if (typeDefinition.Kind == TypeKind.Interface) {
i++;
} else if (!typeDef.BaseType.IsNil) {
children.Add(new BaseTypesEntryNode(module, typeDef.BaseType, baseTypes[i], false));
i++;
}
foreach (var h in typeDef.GetInterfaceImplementations()) {
children.Add(new BaseTypesEntryNode(module, h, baseTypes[i], true));
i++;
}
}

52
ILSpy/TreeNodes/CopyFullyQualifiedNameContextMenuEntry.cs

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
using System.Windows;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.TreeNodes
{
@ -18,60 +19,13 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -18,60 +19,13 @@ namespace ICSharpCode.ILSpy.TreeNodes
public void Execute(TextViewContext context)
{
var member = GetMemberNodeFromContext(context)?.Member;
if (member == null || member.IsNil) return;
Clipboard.SetText(GetFullyQualifiedName(member));
if (member == null) return;
Clipboard.SetText(member.ReflectionName);
}
private IMemberTreeNode GetMemberNodeFromContext(TextViewContext context)
{
return context.SelectedTreeNodes?.Length == 1 ? context.SelectedTreeNodes[0] as IMemberTreeNode : null;
}
/// <summary>
/// Resolve full type name using .NET type representation for nested types.
/// </summary>
private string GetFullyQualifiedName(IMetadataEntity member)
{
string name;
System.Reflection.Metadata.TypeDefinitionHandle declaringType;
switch (member.Handle.Kind) {
case System.Reflection.Metadata.HandleKind.TypeDefinition:
return ((System.Reflection.Metadata.TypeDefinitionHandle)member.Handle).GetFullTypeName(member.Module.Metadata).ToString();
case System.Reflection.Metadata.HandleKind.FieldDefinition:
name = "";
declaringType = member.Handle.GetDeclaringType(member.Module.Metadata);
var fd = member.Module.Metadata.GetFieldDefinition((System.Reflection.Metadata.FieldDefinitionHandle)member.Handle);
if (!declaringType.IsNil) {
name = declaringType.GetFullTypeName(member.Module.Metadata) + ".";
}
return name + member.Module.Metadata.GetString(fd.Name);
case System.Reflection.Metadata.HandleKind.MethodDefinition:
name = "";
declaringType = member.Handle.GetDeclaringType(member.Module.Metadata);
var md = member.Module.Metadata.GetMethodDefinition((System.Reflection.Metadata.MethodDefinitionHandle)member.Handle);
if (!declaringType.IsNil) {
name = declaringType.GetFullTypeName(member.Module.Metadata) + ".";
}
return name + member.Module.Metadata.GetString(md.Name);
case System.Reflection.Metadata.HandleKind.EventDefinition:
name = "";
declaringType = member.Handle.GetDeclaringType(member.Module.Metadata);
var ed = member.Module.Metadata.GetEventDefinition((System.Reflection.Metadata.EventDefinitionHandle)member.Handle);
if (!declaringType.IsNil) {
name = declaringType.GetFullTypeName(member.Module.Metadata) + ".";
}
return name + member.Module.Metadata.GetString(ed.Name);
case System.Reflection.Metadata.HandleKind.PropertyDefinition:
name = "";
declaringType = member.Handle.GetDeclaringType(member.Module.Metadata);
var pd = member.Module.Metadata.GetPropertyDefinition((System.Reflection.Metadata.PropertyDefinitionHandle)member.Handle);
if (!declaringType.IsNil) {
name = declaringType.GetFullTypeName(member.Module.Metadata) + ".";
}
return name + member.Module.Metadata.GetString(pd.Name);
default:
throw new ArgumentOutOfRangeException();
}
}
}
}

11
ILSpy/TreeNodes/DerivedTypesEntryNode.cs

@ -22,18 +22,19 @@ using System.Reflection.PortableExecutable; @@ -22,18 +22,19 @@ using System.Reflection.PortableExecutable;
using System.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes
{
class DerivedTypesEntryNode : ILSpyTreeNode, IMemberTreeNode
{
private readonly TypeDefinition type;
private readonly PEFile[] assemblies;
private readonly ITypeDefinition type;
/* private readonly PEFile[] assemblies;
private readonly ThreadingSupport threading;
private readonly SRM.TypeDefinition td;
public DerivedTypesEntryNode(TypeDefinition type, PEFile[] assemblies)
public DerivedTypesEntryNode(ITypeDefinition type, PEFile[] assemblies)
{
this.type = type;
this.td = type.Module.Metadata.GetTypeDefinition(type.Handle);
@ -100,13 +101,13 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -100,13 +101,13 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override void ActivateItem(System.Windows.RoutedEventArgs e)
{
e.Handled = BaseTypesEntryNode.ActivateItem(this, type);
}
}*/
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, language.TypeToString(type, includeNamespace: true));
}
IMetadataEntity IMemberTreeNode.Member => type;
IEntity IMemberTreeNode.Member => type;
}
}

6
ILSpy/TreeNodes/DerivedTypesTreeNode.cs

@ -26,9 +26,9 @@ using ICSharpCode.Decompiler.Util; @@ -26,9 +26,9 @@ using ICSharpCode.Decompiler.Util;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes
{
{/*
/// <summary>
/// Lists the super types of a class.
/// Lists the sub types of a class.
/// </summary>
sealed class DerivedTypesTreeNode : ILSpyTreeNode
{
@ -97,5 +97,5 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -97,5 +97,5 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
threading.Decompile(language, output, options, EnsureLazyChildren);
}
}
}*/
}

52
ILSpy/TreeNodes/EventTreeNode.cs

@ -23,6 +23,8 @@ using SRM = System.Reflection.Metadata; @@ -23,6 +23,8 @@ using SRM = System.Reflection.Metadata;
using System.Windows.Media;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using System.Reflection.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes
{
@ -31,39 +33,34 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -31,39 +33,34 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary>
public sealed class EventTreeNode : ILSpyTreeNode, IMemberTreeNode
{
public EventTreeNode(EventDefinition ev)
public EventTreeNode(IEvent @event)
{
if (ev.IsNil)
throw new ArgumentNullException(nameof(ev));
this.EventDefinition = ev;
var metadata = ev.Module.Metadata;
var eventDefinition = metadata.GetEventDefinition(ev.Handle);
var accessors = eventDefinition.GetAccessors();
if (!accessors.Adder.IsNil)
this.Children.Add(new MethodTreeNode(new MethodDefinition(ev.Module, accessors.Adder)));
if (!accessors.Remover.IsNil)
this.Children.Add(new MethodTreeNode(new MethodDefinition(ev.Module, accessors.Remover)));
if (!accessors.Raiser.IsNil)
this.Children.Add(new MethodTreeNode(new MethodDefinition(ev.Module, accessors.Raiser)));
this.EventDefinition = @event ?? throw new ArgumentNullException(nameof(@event));
if (@event.CanAdd)
this.Children.Add(new MethodTreeNode(@event.AddAccessor));
if (@event.CanRemove)
this.Children.Add(new MethodTreeNode(@event.RemoveAccessor));
if (@event.CanInvoke)
this.Children.Add(new MethodTreeNode(@event.InvokeAccessor));
//foreach (var m in ev.OtherMethods)
// this.Children.Add(new MethodTreeNode(m));
}
public EventDefinition EventDefinition { get; }
public IEvent EventDefinition { get; }
public override object Text => GetText(EventDefinition, this.Language) + EventDefinition.Handle.ToSuffixString();
public override object Text => GetText(EventDefinition, this.Language) + EventDefinition.MetadataToken.ToSuffixString();
public static object GetText(EventDefinition ev, Language language)
public static object GetText(IEvent ev, Language language)
{
return language.EventToString(ev, false, false);
}
public override object Icon => GetIcon(EventDefinition);
public static ImageSource GetIcon(EventDefinition @event)
public static ImageSource GetIcon(IEvent @event)
{
var metadata = @event.Module.Metadata;
var accessor = metadata.GetEventDefinition(@event.Handle).GetAccessors().GetAny();
var metadata = ((MetadataAssembly)@event.ParentAssembly).PEFile.Metadata;
var accessor = metadata.GetEventDefinition((EventDefinitionHandle)@event.MetadataToken).GetAccessors().GetAny();
if (!accessor.IsNil) {
var accessorMethod = metadata.GetMethodDefinition(accessor);
return Images.GetIcon(MemberIcon.Event, GetOverlayIcon(accessorMethod.Attributes), accessorMethod.HasFlag(MethodAttributes.Static));
@ -97,8 +94,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -97,8 +94,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
if (!settings.ShowInternalApi && !IsPublicAPI)
return FilterResult.Hidden;
var metadata = EventDefinition.Module.Metadata;
if (settings.SearchTermMatches(metadata.GetString(metadata.GetEventDefinition(EventDefinition.Handle).Name)) && settings.Language.ShowMember(EventDefinition))
if (settings.SearchTermMatches(EventDefinition.Name) && settings.Language.ShowMember(EventDefinition))
return FilterResult.Match;
else
return FilterResult.Hidden;
@ -111,14 +107,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -111,14 +107,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override bool IsPublicAPI {
get {
var metadata = EventDefinition.Module.Metadata;
var accessor = metadata.GetEventDefinition(EventDefinition.Handle).GetAccessors().GetAny();
if (accessor.IsNil) return false;
var accessorMethod = metadata.GetMethodDefinition(accessor);
switch (accessorMethod.Attributes & MethodAttributes.MemberAccessMask) {
case MethodAttributes.Public:
case MethodAttributes.FamORAssem:
case MethodAttributes.Family:
switch (EventDefinition.Accessibility) {
case Accessibility.Public:
case Accessibility.ProtectedOrInternal:
case Accessibility.Protected:
return true;
default:
return false;
@ -126,6 +118,6 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -126,6 +118,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
IMetadataEntity IMemberTreeNode.Member => EventDefinition;
IEntity IMemberTreeNode.Member => EventDefinition;
}
}

54
ILSpy/TreeNodes/FieldTreeNode.cs

@ -18,9 +18,11 @@ @@ -18,9 +18,11 @@
using System;
using System.Reflection;
using System.Reflection.Metadata;
using System.Windows.Media;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.ILSpy.TreeNodes
@ -30,28 +32,26 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -30,28 +32,26 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary>
public sealed class FieldTreeNode : ILSpyTreeNode, IMemberTreeNode
{
public FieldDefinition FieldDefinition { get; }
public IField FieldDefinition { get; }
public FieldTreeNode(FieldDefinition field)
public FieldTreeNode(IField field)
{
if (field.IsNil)
throw new ArgumentNullException(nameof(field));
this.FieldDefinition = field;
this.FieldDefinition = field ?? throw new ArgumentNullException(nameof(field));
}
public override object Text => GetText(FieldDefinition, Language) + FieldDefinition.Handle.ToSuffixString();
public override object Text => GetText(FieldDefinition, Language) + FieldDefinition.MetadataToken.ToSuffixString();
public static object GetText(FieldDefinition field, Language language)
public static object GetText(IField field, Language language)
{
return language.FieldToString(field, includeTypeName: false, includeNamespace: false);
}
public override object Icon => GetIcon(FieldDefinition);
public static ImageSource GetIcon(FieldDefinition field)
public static ImageSource GetIcon(IField field)
{
var metadata = field.Module.Metadata;
var fieldDefinition = metadata.GetFieldDefinition(field.Handle);
var metadata = ((MetadataAssembly)field.ParentAssembly).PEFile.Metadata;
var fieldDefinition = metadata.GetFieldDefinition((FieldDefinitionHandle)field.MetadataToken);
if (fieldDefinition.GetDeclaringType().IsEnum(metadata) && !fieldDefinition.HasFlag(FieldAttributes.SpecialName))
return Images.GetIcon(MemberIcon.EnumValue, GetOverlayIcon(fieldDefinition.Attributes), false);
@ -66,22 +66,9 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -66,22 +66,9 @@ namespace ICSharpCode.ILSpy.TreeNodes
return Images.GetIcon(MemberIcon.Field, GetOverlayIcon(fieldDefinition.Attributes), fieldDefinition.HasFlag(FieldAttributes.Static));
}
private static bool IsDecimalConstant(FieldDefinition field)
private static bool IsDecimalConstant(IField field)
{
var metadata = field.Module.Metadata;
var fieldDefinition = metadata.GetFieldDefinition(field.Handle);
var fieldType = fieldDefinition.DecodeSignature(new FullTypeNameSignatureDecoder(metadata), default(Unit));
if (fieldType.ToString() == "System.Decimal") {
var attrs = fieldDefinition.GetCustomAttributes();
foreach (var h in attrs) {
var attr = metadata.GetCustomAttribute(h);
var attrType = attr.GetAttributeType(metadata).GetFullTypeName(metadata);
if (attrType.ToString() == "System.Runtime.CompilerServices.DecimalConstantAttribute")
return true;
}
}
return false;
return field.IsConst && field.Type.IsKnownType(KnownTypeCode.Decimal) && field.ConstantValue != null;
}
private static AccessOverlayIcon GetOverlayIcon(FieldAttributes fieldAttributes)
@ -110,9 +97,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -110,9 +97,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
if (!settings.ShowInternalApi && !IsPublicAPI)
return FilterResult.Hidden;
var metadata = FieldDefinition.Module.Metadata;
var fieldDefinition = metadata.GetFieldDefinition(FieldDefinition.Handle);
if (settings.SearchTermMatches(metadata.GetString(fieldDefinition.Name)) && settings.Language.ShowMember(FieldDefinition))
if (settings.SearchTermMatches(FieldDefinition.Name) && settings.Language.ShowMember(FieldDefinition))
return FilterResult.Match;
else
return FilterResult.Hidden;
@ -125,13 +110,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -125,13 +110,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override bool IsPublicAPI {
get {
var metadata = FieldDefinition.Module.Metadata;
var fieldDefinition = metadata.GetFieldDefinition(FieldDefinition.Handle);
switch (fieldDefinition.Attributes & FieldAttributes.FieldAccessMask) {
case FieldAttributes.Public:
case FieldAttributes.FamORAssem:
case FieldAttributes.Family:
switch (FieldDefinition.Accessibility) {
case Accessibility.Public:
case Accessibility.Protected:
case Accessibility.ProtectedOrInternal:
return true;
default:
return false;
@ -139,6 +121,6 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -139,6 +121,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
IMetadataEntity IMemberTreeNode.Member => FieldDefinition;
IEntity IMemberTreeNode.Member => FieldDefinition;
}
}

6
ILSpy/TreeNodes/IMemberTreeNode.cs

@ -16,17 +16,17 @@ @@ -16,17 +16,17 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.TreeNodes
{
/// <summary>
/// Interface implemented by all tree nodes
/// (both in main tree view and in analyzer)
/// that represent Cecil members.
/// that represent TypeSystem members.
/// </summary>
public interface IMemberTreeNode
{
IMetadataEntity Member { get; }
IEntity Member { get; }
}
}

35
ILSpy/TreeNodes/MethodTreeNode.cs

@ -20,11 +20,13 @@ using System; @@ -20,11 +20,13 @@ using System;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Text;
using System.Windows.Media;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes
@ -34,30 +36,26 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -34,30 +36,26 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary>
public sealed class MethodTreeNode : ILSpyTreeNode, IMemberTreeNode
{
public MethodDefinition MethodDefinition { get; }
SRM.MethodDefinition md;
public IMethod MethodDefinition { get; }
public MethodTreeNode(MethodDefinition method)
public MethodTreeNode(IMethod method)
{
if (method.IsNil)
throw new ArgumentNullException(nameof(method));
this.MethodDefinition = method;
this.md = method.Module.Metadata.GetMethodDefinition(method.Handle);
this.MethodDefinition = method ?? throw new ArgumentNullException(nameof(method));
}
public override object Text => GetText(MethodDefinition, Language) + MethodDefinition.Handle.ToSuffixString();
public override object Text => GetText(MethodDefinition, Language) + MethodDefinition.MetadataToken.ToSuffixString();
public static object GetText(MethodDefinition method, Language language)
public static object GetText(IMethod method, Language language)
{
return language.MethodToString(method, false, false);
}
public override object Icon => GetIcon(MethodDefinition);
public static ImageSource GetIcon(MethodDefinition method)
public static ImageSource GetIcon(IMethod method)
{
var metadata = method.Module.Metadata;
var methodDefinition = metadata.GetMethodDefinition(method.Handle);
var metadata = ((MetadataAssembly)method.ParentAssembly).PEFile.Metadata;
var methodDefinition = metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken);
var methodName = metadata.GetString(methodDefinition.Name);
if (methodDefinition.HasFlag(MethodAttributes.SpecialName) && methodName.StartsWith("op_", StringComparison.Ordinal)) {
return Images.GetIcon(MemberIcon.Operator, GetOverlayIcon(methodDefinition.Attributes), false);
@ -116,8 +114,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -116,8 +114,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
if (!settings.ShowInternalApi && !IsPublicAPI)
return FilterResult.Hidden;
var metadata = MethodDefinition.Module.Metadata;
if (settings.SearchTermMatches(metadata.GetString(md.Name)) && settings.Language.ShowMember(MethodDefinition))
if (settings.SearchTermMatches(MethodDefinition.Name) && settings.Language.ShowMember(MethodDefinition))
return FilterResult.Match;
else
return FilterResult.Hidden;
@ -125,10 +122,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -125,10 +122,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override bool IsPublicAPI {
get {
switch (md.Attributes & MethodAttributes.MemberAccessMask) {
case MethodAttributes.Public:
case MethodAttributes.Family:
case MethodAttributes.FamORAssem:
switch (MethodDefinition.Accessibility) {
case Accessibility.Public:
case Accessibility.Protected:
case Accessibility.ProtectedOrInternal:
return true;
default:
return false;
@ -136,6 +133,6 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -136,6 +133,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
IMetadataEntity IMemberTreeNode.Member => MethodDefinition;
IEntity IMemberTreeNode.Member => MethodDefinition;
}
}

44
ILSpy/TreeNodes/PropertyTreeNode.cs

@ -18,10 +18,11 @@ @@ -18,10 +18,11 @@
using System;
using System.Reflection;
using System.Reflection.Metadata;
using System.Windows.Media;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes
@ -33,38 +34,31 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -33,38 +34,31 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
readonly bool isIndexer;
public PropertyTreeNode(PropertyDefinition property)
public PropertyTreeNode(IProperty property)
{
if (property == null)
throw new ArgumentNullException(nameof(property));
this.PropertyDefinition = property;
var metadata = property.Module.Metadata;
var propertyDefinition = metadata.GetPropertyDefinition(property.Handle);
var accessors = propertyDefinition.GetAccessors();
using (LoadedAssembly.DisableAssemblyLoad()) {
this.isIndexer = property.Handle.HasMatchingDefaultMemberAttribute(property.Module, out _);
}
this.PropertyDefinition = property ?? throw new ArgumentNullException(nameof(property));
this.isIndexer = property.IsIndexer;
if (!accessors.Getter.IsNil)
this.Children.Add(new MethodTreeNode(new MethodDefinition(property.Module, accessors.Getter)));
if (!accessors.Setter.IsNil)
this.Children.Add(new MethodTreeNode(new MethodDefinition(property.Module, accessors.Setter)));
if (property.CanGet)
this.Children.Add(new MethodTreeNode(property.Getter));
if (property.CanSet)
this.Children.Add(new MethodTreeNode(property.Setter));
/*foreach (var m in property.OtherMethods)
this.Children.Add(new MethodTreeNode(m));*/
}
public PropertyDefinition PropertyDefinition { get; }
public IProperty PropertyDefinition { get; }
public override object Text => GetText(PropertyDefinition, Language, isIndexer) + PropertyDefinition.Handle.ToSuffixString();
public override object Text => GetText(PropertyDefinition, Language, isIndexer) + PropertyDefinition.MetadataToken.ToSuffixString();
public static object GetText(PropertyDefinition property, Language language, bool? isIndexer = null)
public static object GetText(IProperty property, Language language, bool? isIndexer = null)
{
return language.PropertyToString(property, false, false, isIndexer);
}
public override object Icon => GetIcon(PropertyDefinition);
public static ImageSource GetIcon(PropertyDefinition property, bool isIndexer = false)
public static ImageSource GetIcon(IProperty property, bool isIndexer = false)
{
MemberIcon icon = isIndexer ? MemberIcon.Indexer : MemberIcon.Property;
MethodAttributes attributesOfMostAccessibleMethod = GetAttributesOfMostAccessibleMethod(property);
@ -94,7 +88,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -94,7 +88,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
private static MethodAttributes GetAttributesOfMostAccessibleMethod(PropertyDefinition property)
private static MethodAttributes GetAttributesOfMostAccessibleMethod(IProperty property)
{
// There should always be at least one method from which to
// obtain the result, but the compiler doesn't know this so
@ -105,8 +99,8 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -105,8 +99,8 @@ namespace ICSharpCode.ILSpy.TreeNodes
// in numeric order, so we can do an integer comparison of the masked attribute
int accessLevel = 0;
var metadata = property.Module.Metadata;
var propertyDefinition = metadata.GetPropertyDefinition(property.Handle);
var metadata = ((MetadataAssembly)property.ParentAssembly).PEFile.Metadata;
var propertyDefinition = metadata.GetPropertyDefinition((PropertyDefinitionHandle)property.MetadataToken);
var accessors = propertyDefinition.GetAccessors();
if (!accessors.Getter.IsNil) {
@ -142,9 +136,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -142,9 +136,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
if (!settings.ShowInternalApi && !IsPublicAPI)
return FilterResult.Hidden;
var metadata = PropertyDefinition.Module.Metadata;
var propertyDefinition = metadata.GetPropertyDefinition(PropertyDefinition.Handle);
if (settings.SearchTermMatches(metadata.GetString(propertyDefinition.Name)) && settings.Language.ShowMember(PropertyDefinition))
if (settings.SearchTermMatches(PropertyDefinition.Name) && settings.Language.ShowMember(PropertyDefinition))
return FilterResult.Match;
else
return FilterResult.Hidden;
@ -168,6 +160,6 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -168,6 +160,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
}
IMetadataEntity IMemberTreeNode.Member => PropertyDefinition;
IEntity IMemberTreeNode.Member => PropertyDefinition;
}
}

111
ILSpy/TreeNodes/TypeTreeNode.cs

@ -22,39 +22,32 @@ using System.Reflection; @@ -22,39 +22,32 @@ using System.Reflection;
using System.Windows.Media;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using SRM = System.Reflection.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes
{
public sealed class TypeTreeNode : ILSpyTreeNode, IMemberTreeNode
{
readonly SRM.TypeDefinition td;
public TypeTreeNode(TypeDefinition typeDefinition, AssemblyTreeNode parentAssemblyNode)
public TypeTreeNode(ITypeDefinition typeDefinition, AssemblyTreeNode parentAssemblyNode)
{
if (typeDefinition.IsNil)
throw new ArgumentNullException(nameof(typeDefinition));
this.ParentAssemblyNode = parentAssemblyNode ?? throw new ArgumentNullException(nameof(parentAssemblyNode));
this.TypeDefinition = typeDefinition;
this.td = typeDefinition.Module.Metadata.GetTypeDefinition(typeDefinition.Handle);
this.TypeDefinition = typeDefinition ?? throw new ArgumentNullException(nameof(typeDefinition));
this.LazyLoading = true;
}
public TypeDefinition TypeDefinition { get; }
public ITypeDefinition TypeDefinition { get; }
public AssemblyTreeNode ParentAssemblyNode { get; }
public override object Text => this.Language.TypeToString(TypeDefinition, includeNamespace: false) + TypeDefinition.Handle.ToSuffixString();
public override object Text => this.Language.TypeToString(TypeDefinition, includeNamespace: false) + TypeDefinition.MetadataToken.ToSuffixString();
public override bool IsPublicAPI {
get {
switch (td.Attributes & TypeAttributes.VisibilityMask) {
case TypeAttributes.Public:
case TypeAttributes.NestedPublic:
case TypeAttributes.NestedFamily:
case TypeAttributes.NestedFamORAssem:
switch (TypeDefinition.Accessibility) {
case Accessibility.Public:
case Accessibility.Protected:
case Accessibility.ProtectedOrInternal:
return true;
default:
return false;
@ -66,7 +59,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -66,7 +59,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
if (!settings.ShowInternalApi && !IsPublicAPI)
return FilterResult.Hidden;
if (settings.SearchTermMatches(TypeDefinition.Module.Metadata.GetString(td.Name))) {
if (settings.SearchTermMatches(TypeDefinition.Name)) {
if (settings.Language.ShowMember(TypeDefinition))
return FilterResult.Match;
else
@ -78,28 +71,25 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -78,28 +71,25 @@ namespace ICSharpCode.ILSpy.TreeNodes
protected override void LoadChildren()
{
var metadata = TypeDefinition.Module.Metadata;
if (!td.BaseType.IsNil || td.GetInterfaceImplementations().Any())
this.Children.Add(new BaseTypesTreeNode(TypeDefinition));
if (!td.HasFlag(TypeAttributes.Sealed))
this.Children.Add(new DerivedTypesTreeNode(ParentAssemblyNode.AssemblyList, TypeDefinition));
foreach (var nestedType in td.GetNestedTypes().OrderBy(m => metadata.GetString(metadata.GetTypeDefinition(m).Name), NaturalStringComparer.Instance)) {
this.Children.Add(new TypeTreeNode(new TypeDefinition(TypeDefinition.Module, nestedType), ParentAssemblyNode));
if (!TypeDefinition.DirectBaseTypes.Any())
this.Children.Add(new BaseTypesTreeNode(ParentAssemblyNode.LoadedAssembly.GetPEFileOrNull(), TypeDefinition));
/*if (!TypeDefinition.IsSealed)
this.Children.Add(new DerivedTypesTreeNode(ParentAssemblyNode.AssemblyList, TypeDefinition));*/
foreach (var nestedType in TypeDefinition.NestedTypes.OrderBy(t => t.Name, NaturalStringComparer.Instance)) {
this.Children.Add(new TypeTreeNode(nestedType, ParentAssemblyNode));
}
foreach (var field in td.GetFields().OrderBy(m => metadata.GetString(metadata.GetFieldDefinition(m).Name), NaturalStringComparer.Instance)) {
this.Children.Add(new FieldTreeNode(new FieldDefinition(TypeDefinition.Module, field)));
foreach (var field in TypeDefinition.Fields.OrderBy(f => f.Name, NaturalStringComparer.Instance)) {
this.Children.Add(new FieldTreeNode(field));
}
foreach (var property in td.GetProperties().OrderBy(m => metadata.GetString(metadata.GetPropertyDefinition(m).Name), NaturalStringComparer.Instance)) {
this.Children.Add(new PropertyTreeNode(new PropertyDefinition(TypeDefinition.Module, property)));
foreach (var property in TypeDefinition.Properties.OrderBy(p => p.Name, NaturalStringComparer.Instance)) {
this.Children.Add(new PropertyTreeNode(property));
}
foreach (var ev in td.GetEvents().OrderBy(m => metadata.GetString(metadata.GetEventDefinition(m).Name), NaturalStringComparer.Instance)) {
this.Children.Add(new EventTreeNode(new EventDefinition(TypeDefinition.Module, ev)));
foreach (var ev in TypeDefinition.Events.OrderBy(e => e.Name, NaturalStringComparer.Instance)) {
this.Children.Add(new EventTreeNode(ev));
}
foreach (var method in td.GetMethods().OrderBy(m => metadata.GetString(metadata.GetMethodDefinition(m).Name), NaturalStringComparer.Instance)) {
if (method.GetMethodSemanticsAttributes(metadata) == 0) {
this.Children.Add(new MethodTreeNode(new MethodDefinition(TypeDefinition.Module, method)));
}
foreach (var method in TypeDefinition.Methods.OrderBy(m => m.Name, NaturalStringComparer.Instance)) {
this.Children.Add(new MethodTreeNode(method));
}
}
@ -112,7 +102,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -112,7 +102,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override object Icon => GetIcon(TypeDefinition);
public static ImageSource GetIcon(TypeDefinition type)
public static ImageSource GetIcon(ITypeDefinition type)
{
TypeIcon typeIcon = GetTypeIcon(type);
AccessOverlayIcon overlayIcon = GetOverlayIcon(type);
@ -120,48 +110,42 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -120,48 +110,42 @@ namespace ICSharpCode.ILSpy.TreeNodes
return Images.GetIcon(typeIcon, overlayIcon);
}
static TypeIcon GetTypeIcon(TypeDefinition type)
internal static TypeIcon GetTypeIcon(IType type)
{
var metadata = type.Module.Metadata;
var typeDefinition = metadata.GetTypeDefinition(type.Handle);
if (typeDefinition.IsValueType(metadata)) {
if (typeDefinition.IsEnum(metadata))
return TypeIcon.Enum;
else
return TypeIcon.Struct;
} else {
if ((typeDefinition.Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface)
switch (type.Kind) {
case TypeKind.Interface:
return TypeIcon.Interface;
else if (typeDefinition.IsDelegate(metadata))
case TypeKind.Struct:
return TypeIcon.Struct;
case TypeKind.Delegate:
return TypeIcon.Delegate;
else if (IsStaticClass(typeDefinition))
return TypeIcon.StaticClass;
else
case TypeKind.Enum:
return TypeIcon.Enum;
default:
if (type.GetDefinition()?.IsStatic == true)
return TypeIcon.StaticClass;
return TypeIcon.Class;
}
}
private static AccessOverlayIcon GetOverlayIcon(TypeDefinition type)
private static AccessOverlayIcon GetOverlayIcon(ITypeDefinition type)
{
var def = type.Module.Metadata.GetTypeDefinition(type.Handle);
AccessOverlayIcon overlay;
switch (def.Attributes & TypeAttributes.VisibilityMask) {
case TypeAttributes.Public:
case TypeAttributes.NestedPublic:
switch (type.Accessibility) {
case Accessibility.Public:
overlay = AccessOverlayIcon.Public;
break;
case TypeAttributes.NotPublic:
case TypeAttributes.NestedAssembly:
case Accessibility.Internal:
overlay = AccessOverlayIcon.Internal;
break;
case TypeAttributes.NestedFamANDAssem:
case Accessibility.ProtectedAndInternal:
overlay = AccessOverlayIcon.PrivateProtected;
break;
case TypeAttributes.NestedFamily:
case TypeAttributes.NestedFamORAssem:
case Accessibility.Protected:
case Accessibility.ProtectedOrInternal:
overlay = AccessOverlayIcon.Protected;
break;
case TypeAttributes.NestedPrivate:
case Accessibility.Private:
overlay = AccessOverlayIcon.Private;
break;
default:
@ -170,11 +154,6 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -170,11 +154,6 @@ namespace ICSharpCode.ILSpy.TreeNodes
return overlay;
}
static bool IsStaticClass(SRM.TypeDefinition type)
{
return type.HasFlag(TypeAttributes.Sealed) && type.HasFlag(TypeAttributes.Abstract);
}
IMetadataEntity IMemberTreeNode.Member => TypeDefinition;
IEntity IMemberTreeNode.Member => TypeDefinition;
}
}

9
TestPlugin/CustomLanguage.cs

@ -6,6 +6,7 @@ using System.Reflection.Metadata; @@ -6,6 +6,7 @@ using System.Reflection.Metadata;
using System.Windows.Controls;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy;
namespace TestPlugin
@ -30,12 +31,12 @@ namespace TestPlugin @@ -30,12 +31,12 @@ namespace TestPlugin
}
// There are several methods available to override; in this sample, we deal with methods only
public override void DecompileMethod(ICSharpCode.Decompiler.Metadata.MethodDefinition method, ITextOutput output, DecompilationOptions options)
public override void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options)
{
var metadata = method.Module.Metadata;
var methodDef = metadata.GetMethodDefinition(method.Handle);
var module = ((MetadataAssembly)method.ParentAssembly).PEFile;
var methodDef = module.Metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken);
if (methodDef.HasBody()) {
var methodBody = method.Module.Reader.GetMethodBody(methodDef.RelativeVirtualAddress);
var methodBody = module.Reader.GetMethodBody(methodDef.RelativeVirtualAddress);
output.WriteLine("Size of method: {0} bytes", methodBody.GetCodeSize());
ISmartTextOutput smartOutput = output as ISmartTextOutput;

Loading…
Cancel
Save