Browse Source

Detect compiler-generated code that is still needed after decompilation.

pull/2684/head
Siegfried Pammer 3 years ago
parent
commit
b7edf2eb59
  1. 48
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 2
      ICSharpCode.Decompiler/Util/MultiDictionary.cs

48
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -1244,7 +1244,8 @@ namespace ICSharpCode.Decompiler.CSharp
{ {
Debug.Assert(decompilationContext.CurrentTypeDefinition == typeDef); Debug.Assert(decompilationContext.CurrentTypeDefinition == typeDef);
var watch = System.Diagnostics.Stopwatch.StartNew(); var watch = System.Diagnostics.Stopwatch.StartNew();
MultiDictionary<IEntity, EntityDeclaration> entityMap = new(); var entityMap = new MultiDictionary<IEntity, EntityDeclaration>();
var workList = new Queue<IEntity>();
TypeSystemAstBuilder typeSystemAstBuilder; TypeSystemAstBuilder typeSystemAstBuilder;
try try
{ {
@ -1305,11 +1306,29 @@ namespace ICSharpCode.Decompiler.CSharp
var allOrderedEntities = typeDef.NestedTypes.Concat<IEntity>(allOrderedMembers); var allOrderedEntities = typeDef.NestedTypes.Concat<IEntity>(allOrderedMembers);
foreach (var member in allOrderedEntities) // Decompile members that are not compiler-generated.
foreach (var entity in allOrderedEntities)
{
if (entity.MetadataToken.IsNil || MemberIsHidden(module.PEFile, entity.MetadataToken, settings))
{
continue;
}
DoDecompileMember(entity, recordDecompiler);
}
// Decompile compiler-generated members that are still needed.
while (workList.Count > 0)
{ {
DoDecompileMember(member, recordDecompiler); var entity = workList.Dequeue();
if (entityMap.Contains(entity) || entity.MetadataToken.IsNil)
{
// Member is already decompiled.
continue;
}
DoDecompileMember(entity, recordDecompiler);
} }
// Add all decompiled members to syntax tree in the correct order.
foreach (var member in allOrderedEntities) foreach (var member in allOrderedEntities)
{ {
typeDecl.Members.AddRange(entityMap[member]); typeDecl.Members.AddRange(entityMap[member]);
@ -1377,10 +1396,6 @@ namespace ICSharpCode.Decompiler.CSharp
void DoDecompileMember(IEntity entity, RecordDecompiler recordDecompiler) void DoDecompileMember(IEntity entity, RecordDecompiler recordDecompiler)
{ {
EntityDeclaration entityDecl; EntityDeclaration entityDecl;
if (entity.MetadataToken.IsNil || MemberIsHidden(module.PEFile, entity.MetadataToken, settings))
{
return;
}
switch (entity) switch (entity)
{ {
case IField field: case IField field:
@ -1416,13 +1431,26 @@ namespace ICSharpCode.Decompiler.CSharp
entityMap.Add(@event, entityDecl); entityMap.Add(@event, entityDecl);
break; break;
case ITypeDefinition type: case ITypeDefinition type:
var nestedType = DoDecompile(type, decompileRun, decompilationContext.WithCurrentTypeDefinition(type)); entityDecl = DoDecompile(type, decompileRun, decompilationContext.WithCurrentTypeDefinition(type));
SetNewModifier(nestedType); SetNewModifier(entityDecl);
entityMap.Add(type, nestedType); entityMap.Add(type, entityDecl);
break; break;
default: default:
throw new ArgumentOutOfRangeException("Unexpected member type"); throw new ArgumentOutOfRangeException("Unexpected member type");
} }
foreach (var node in entityDecl.Descendants)
{
var rr = node.GetResolveResult();
if (rr is MemberResolveResult mrr && mrr.Member.DeclaringTypeDefinition == typeDef)
{
workList.Enqueue(mrr.Member);
}
else if (rr is TypeResolveResult trr && trr.Type.GetDefinition()?.DeclaringTypeDefinition == typeDef)
{
workList.Enqueue(trr.Type.GetDefinition());
}
}
} }
} }

2
ICSharpCode.Decompiler/Util/MultiDictionary.cs

@ -105,7 +105,7 @@ namespace ICSharpCode.Decompiler.Util
get { return this[key]; } get { return this[key]; }
} }
bool ILookup<TKey, TValue>.Contains(TKey key) public bool Contains(TKey key)
{ {
return dict.ContainsKey(key); return dict.ContainsKey(key);
} }

Loading…
Cancel
Save