Browse Source

Move CodeMappingInfo to Decompiler.

pull/1030/head
Siegfried Pammer 7 years ago
parent
commit
27cf62d710
  1. 55
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 28
      ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs
  3. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  4. 14
      ICSharpCode.Decompiler/Metadata/CodeMappingInfo.cs
  5. 1
      ILSpy/Analyzers/IAnalyzer.cs
  6. 1
      ILSpy/ILSpy.csproj
  7. 50
      ILSpy/Languages/CSharpLanguage.cs
  8. 2
      ILSpy/Languages/Language.cs

55
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -41,6 +41,8 @@ using ICSharpCode.Decompiler.Metadata;
using System.Reflection.PortableExecutable; using System.Reflection.PortableExecutable;
using ICSharpCode.Decompiler.Documentation; using ICSharpCode.Decompiler.Documentation;
using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.Decompiler.DebugInfo;
using ICSharpCode.Decompiler.Disassembler;
using System.Reflection.Metadata.Ecma335;
namespace ICSharpCode.Decompiler.CSharp namespace ICSharpCode.Decompiler.CSharp
{ {
@ -464,6 +466,59 @@ namespace ICSharpCode.Decompiler.CSharp
}; };
} }
public static CodeMappingInfo GetCodeMappingInfo(PEFile module, EntityHandle member)
{
var declaringType = member.GetDeclaringType(module.Metadata);
if (declaringType.IsNil && member.Kind == HandleKind.TypeDefinition) {
declaringType = (TypeDefinitionHandle)member;
}
var info = new CodeMappingInfo(module, declaringType);
var td = module.Metadata.GetTypeDefinition(declaringType);
foreach (var method in td.GetMethods()) {
var parent = method;
var part = method;
var connectedMethods = new Queue<MethodDefinitionHandle>();
connectedMethods.Enqueue(part);
while (connectedMethods.Count > 0) {
part = connectedMethods.Dequeue();
var md = module.Metadata.GetMethodDefinition(part);
if (!md.HasBody()) {
info.AddMapping(parent, part);
} else {
// TODO : async and yield fsms
// deal with ldftn instructions, i.e., lambdas
var blob = module.Reader.GetMethodBody(md.RelativeVirtualAddress).GetILReader();
while (blob.RemainingBytes > 0) {
var code = blob.DecodeOpCode();
if (code == ILOpCode.Ldftn) {
var token = MetadataTokens.EntityHandle(blob.ReadInt32());
if (token.Kind == HandleKind.MethodDefinition) {
if (((MethodDefinitionHandle)token).IsCompilerGenerated(module.Metadata))
connectedMethods.Enqueue((MethodDefinitionHandle)token);
}
} else {
blob.SkipOperand(code);
}
}
info.AddMapping(parent, part);
}
}
}
return info;
}
/// <summary> /// <summary>
/// Decompiles the whole module into a single string. /// Decompiles the whole module into a single string.
/// </summary> /// </summary>

28
ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs

@ -34,12 +34,15 @@ namespace ICSharpCode.Decompiler.CSharp
HandleAttributes(typeSystem.MainAssembly.GetModuleAttributes(), namespaces); HandleAttributes(typeSystem.MainAssembly.GetModuleAttributes(), namespaces);
} }
public static void CollectNamespaces(IEntity entity, DecompilerTypeSystem typeSystem, HashSet<string> namespaces, bool scanningFullType = false) public static void CollectNamespaces(IEntity entity, DecompilerTypeSystem typeSystem,
HashSet<string> namespaces, CodeMappingInfo mappingInfo = null, bool scanningFullType = false)
{ {
if (entity == null) if (entity == null || entity.MetadataToken.IsNil)
return; return;
switch (entity) { switch (entity) {
case ITypeDefinition td: case ITypeDefinition td:
if (mappingInfo == null)
mappingInfo = CSharpDecompiler.GetCodeMappingInfo(entity.ParentAssembly.PEFile, entity.MetadataToken);
namespaces.Add(td.Namespace); namespaces.Add(td.Namespace);
HandleAttributes(td.GetAttributes(), namespaces); HandleAttributes(td.GetAttributes(), namespaces);
@ -52,23 +55,23 @@ namespace ICSharpCode.Decompiler.CSharp
} }
foreach (var nestedType in td.NestedTypes) { foreach (var nestedType in td.NestedTypes) {
CollectNamespaces(nestedType, typeSystem, namespaces, scanningFullType: true); CollectNamespaces(nestedType, typeSystem, namespaces, mappingInfo, scanningFullType: true);
} }
foreach (var field in td.Fields) { foreach (var field in td.Fields) {
CollectNamespaces(field, typeSystem, namespaces, scanningFullType: true); CollectNamespaces(field, typeSystem, namespaces, mappingInfo, scanningFullType: true);
} }
foreach (var property in td.Properties) { foreach (var property in td.Properties) {
CollectNamespaces(property, typeSystem, namespaces, scanningFullType: true); CollectNamespaces(property, typeSystem, namespaces, mappingInfo, scanningFullType: true);
} }
foreach (var @event in td.Events) { foreach (var @event in td.Events) {
CollectNamespaces(@event, typeSystem, namespaces, scanningFullType: true); CollectNamespaces(@event, typeSystem, namespaces, mappingInfo, scanningFullType: true);
} }
foreach (var method in td.Methods) { foreach (var method in td.Methods) {
CollectNamespaces(method, typeSystem, namespaces, scanningFullType: true); CollectNamespaces(method, typeSystem, namespaces, mappingInfo, scanningFullType: true);
} }
break; break;
case IField field: case IField field:
@ -87,10 +90,15 @@ namespace ICSharpCode.Decompiler.CSharp
HandleAttributes(typeParam.GetAttributes(), namespaces); HandleAttributes(typeParam.GetAttributes(), namespaces);
} }
if (!method.MetadataToken.IsNil && method.HasBody) { if (!method.MetadataToken.IsNil && method.HasBody) {
if (mappingInfo == null)
mappingInfo = CSharpDecompiler.GetCodeMappingInfo(entity.ParentAssembly.PEFile, entity.MetadataToken);
var reader = typeSystem.ModuleDefinition.Reader; var reader = typeSystem.ModuleDefinition.Reader;
var methodDef = typeSystem.ModuleDefinition.Metadata.GetMethodDefinition((MethodDefinitionHandle)method.MetadataToken); var parts = mappingInfo.GetMethodParts((MethodDefinitionHandle)method.MetadataToken).ToList();
var body = reader.GetMethodBody(methodDef.RelativeVirtualAddress); foreach (var part in parts) {
CollectNamespacesFromMethodBody(body, reader, typeSystem, namespaces, scanningFullType: scanningFullType); var methodDef = typeSystem.ModuleDefinition.Metadata.GetMethodDefinition(part);
var body = reader.GetMethodBody(methodDef.RelativeVirtualAddress);
CollectNamespacesFromMethodBody(body, reader, typeSystem, namespaces, scanningFullType: scanningFullType);
}
} }
break; break;
case IProperty property: case IProperty property:

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -267,6 +267,7 @@
<Compile Include="CSharp\Transforms\AddXmlDocumentationTransform.cs" /> <Compile Include="CSharp\Transforms\AddXmlDocumentationTransform.cs" />
<Compile Include="DecompileRun.cs" /> <Compile Include="DecompileRun.cs" />
<Compile Include="Metadata\AssemblyReferences.cs" /> <Compile Include="Metadata\AssemblyReferences.cs" />
<Compile Include="Metadata\CodeMappingInfo.cs" />
<Compile Include="Metadata\EnumUnderlyingTypeResolveException.cs" /> <Compile Include="Metadata\EnumUnderlyingTypeResolveException.cs" />
<Compile Include="Metadata\MetadataTokenHelpers.cs" /> <Compile Include="Metadata\MetadataTokenHelpers.cs" />
<Compile Include="Disassembler\OpCodeInfo.cs" /> <Compile Include="Disassembler\OpCodeInfo.cs" />

14
ILSpy/Languages/CodeMappingInfo.cs → ICSharpCode.Decompiler/Metadata/CodeMappingInfo.cs

@ -5,32 +5,24 @@ using System.Linq;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
namespace ICSharpCode.ILSpy namespace ICSharpCode.Decompiler.Metadata
{ {
public class CodeMappingInfo public class CodeMappingInfo
{ {
public Decompiler.Metadata.PEFile Module { get; } public PEFile Module { get; }
public Language Language { get; }
public TypeDefinitionHandle TypeDefinition { get; } public TypeDefinitionHandle TypeDefinition { get; }
Dictionary<MethodDefinitionHandle, List<MethodDefinitionHandle>> parts; Dictionary<MethodDefinitionHandle, List<MethodDefinitionHandle>> parts;
Dictionary<MethodDefinitionHandle, MethodDefinitionHandle> parents; Dictionary<MethodDefinitionHandle, MethodDefinitionHandle> parents;
public CodeMappingInfo(Language language, Decompiler.Metadata.PEFile module, TypeDefinitionHandle type) public CodeMappingInfo(PEFile module, TypeDefinitionHandle type)
{ {
this.Language = language;
this.Module = module; this.Module = module;
this.TypeDefinition = type; this.TypeDefinition = type;
this.parts = new Dictionary<MethodDefinitionHandle, List<MethodDefinitionHandle>>(); this.parts = new Dictionary<MethodDefinitionHandle, List<MethodDefinitionHandle>>();
this.parents = new Dictionary<MethodDefinitionHandle, MethodDefinitionHandle>(); this.parents = new Dictionary<MethodDefinitionHandle, MethodDefinitionHandle>();
} }
public bool ShowMember(EntityHandle entity)
{
throw null;
//return Language.ShowMember(new Decompiler.Metadata.Entity(Module, entity));
}
public IEnumerable<MethodDefinitionHandle> GetMethodParts(MethodDefinitionHandle method) public IEnumerable<MethodDefinitionHandle> GetMethodParts(MethodDefinitionHandle method)
{ {
if (parts.TryGetValue(method, out var p)) if (parts.TryGetValue(method, out var p))

1
ILSpy/Analyzers/IAnalyzer.cs

@ -21,6 +21,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Threading; using System.Threading;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.Analyzers namespace ICSharpCode.ILSpy.Analyzers

1
ILSpy/ILSpy.csproj

@ -130,7 +130,6 @@
<DependentUpon>DebugSteps.xaml</DependentUpon> <DependentUpon>DebugSteps.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="ILSpyTraceListener.cs" /> <Compile Include="ILSpyTraceListener.cs" />
<Compile Include="Languages\CodeMappingInfo.cs" />
<Compile Include="DecompilationOptions.cs" /> <Compile Include="DecompilationOptions.cs" />
<Compile Include="ExtensionMethods.cs" /> <Compile Include="ExtensionMethods.cs" />
<Compile Include="FilterSettings.cs" /> <Compile Include="FilterSettings.cs" />

50
ILSpy/Languages/CSharpLanguage.cs

@ -564,55 +564,7 @@ namespace ICSharpCode.ILSpy
public override CodeMappingInfo GetCodeMappingInfo(PEFile module, EntityHandle member) public override CodeMappingInfo GetCodeMappingInfo(PEFile module, EntityHandle member)
{ {
var declaringType = member.GetDeclaringType(module.Metadata); return CSharpDecompiler.GetCodeMappingInfo(module, member);
if (declaringType.IsNil && member.Kind == HandleKind.TypeDefinition) {
declaringType = (TypeDefinitionHandle)member;
}
var info = new CodeMappingInfo(this, module, declaringType);
var td = module.Metadata.GetTypeDefinition(declaringType);
foreach (var method in td.GetMethods()) {
var parent = method;
var part = method;
var connectedMethods = new Queue<MethodDefinitionHandle>();
connectedMethods.Enqueue(part);
while (connectedMethods.Count > 0) {
part = connectedMethods.Dequeue();
var md = module.Metadata.GetMethodDefinition(part);
if (!md.HasBody()) {
info.AddMapping(parent, part);
} else {
// TODO : async and yield fsms
// deal with ldftn instructions, i.e., lambdas
var blob = module.Reader.GetMethodBody(md.RelativeVirtualAddress).GetILReader();
while (blob.RemainingBytes > 0) {
var code = blob.DecodeOpCode();
if (code == ILOpCode.Ldftn) {
var token = MetadataTokens.EntityHandle(blob.ReadInt32());
if (token.Kind == HandleKind.MethodDefinition) {
if (((MethodDefinitionHandle)token).IsCompilerGenerated(module.Metadata))
connectedMethods.Enqueue((MethodDefinitionHandle)token);
}
} else {
blob.SkipOperand(code);
}
}
info.AddMapping(parent, part);
}
}
}
return info;
} }
} }
} }

2
ILSpy/Languages/Language.cs

@ -274,7 +274,7 @@ namespace ICSharpCode.ILSpy
declaringType = (SRM.TypeDefinitionHandle)member; declaringType = (SRM.TypeDefinitionHandle)member;
} }
return new CodeMappingInfo(this, module, declaringType); return new CodeMappingInfo(module, declaringType);
} }
public static string GetPlatformDisplayName(PEFile module) public static string GetPlatformDisplayName(PEFile module)

Loading…
Cancel
Save