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 @@ -1244,7 +1244,8 @@ namespace ICSharpCode.Decompiler.CSharp
{
Debug.Assert(decompilationContext.CurrentTypeDefinition == typeDef);
var watch = System.Diagnostics.Stopwatch.StartNew();
MultiDictionary<IEntity, EntityDeclaration> entityMap = new();
var entityMap = new MultiDictionary<IEntity, EntityDeclaration>();
var workList = new Queue<IEntity>();
TypeSystemAstBuilder typeSystemAstBuilder;
try
{
@ -1305,11 +1306,29 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1305,11 +1306,29 @@ namespace ICSharpCode.Decompiler.CSharp
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)
{
typeDecl.Members.AddRange(entityMap[member]);
@ -1377,10 +1396,6 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1377,10 +1396,6 @@ namespace ICSharpCode.Decompiler.CSharp
void DoDecompileMember(IEntity entity, RecordDecompiler recordDecompiler)
{
EntityDeclaration entityDecl;
if (entity.MetadataToken.IsNil || MemberIsHidden(module.PEFile, entity.MetadataToken, settings))
{
return;
}
switch (entity)
{
case IField field:
@ -1416,13 +1431,26 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1416,13 +1431,26 @@ namespace ICSharpCode.Decompiler.CSharp
entityMap.Add(@event, entityDecl);
break;
case ITypeDefinition type:
var nestedType = DoDecompile(type, decompileRun, decompilationContext.WithCurrentTypeDefinition(type));
SetNewModifier(nestedType);
entityMap.Add(type, nestedType);
entityDecl = DoDecompile(type, decompileRun, decompilationContext.WithCurrentTypeDefinition(type));
SetNewModifier(entityDecl);
entityMap.Add(type, entityDecl);
break;
default:
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 @@ -105,7 +105,7 @@ namespace ICSharpCode.Decompiler.Util
get { return this[key]; }
}
bool ILookup<TKey, TValue>.Contains(TKey key)
public bool Contains(TKey key)
{
return dict.ContainsKey(key);
}

Loading…
Cancel
Save