Browse Source

Fix #2807: Detect when a compiler-generated/hidden type needs to be decompiled in WholeProjectDecompiler.

pull/2828/head
Siegfried Pammer 3 years ago
parent
commit
71e4d51786
  1. 58
      ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs

58
ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs

@ -32,6 +32,7 @@ using ICSharpCode.Decompiler.CSharp.Syntax; @@ -32,6 +32,7 @@ using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.CSharp.Transforms;
using ICSharpCode.Decompiler.DebugInfo;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.Solution;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
@ -206,8 +207,28 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -206,8 +207,28 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
IEnumerable<(string itemType, string fileName)> WriteCodeFilesInProject(Metadata.PEFile module, IList<PartialTypeInfo> partialTypes, CancellationToken cancellationToken)
{
var metadata = module.Metadata;
var files = module.Metadata.GetTopLevelTypeDefinitions().Where(td => IncludeTypeWhenDecompilingProject(module, td)).GroupBy(
delegate (TypeDefinitionHandle h) {
var files = module.Metadata.GetTopLevelTypeDefinitions().Where(td => IncludeTypeWhenDecompilingProject(module, td))
.GroupBy(GetFileFileNameForHandle, StringComparer.OrdinalIgnoreCase).ToList();
var progressReporter = ProgressIndicator;
var progress = new DecompilationProgress { TotalUnits = files.Count, Title = "Exporting project..." };
DecompilerTypeSystem ts = new DecompilerTypeSystem(module, AssemblyResolver, Settings);
var workList = new HashSet<TypeDefinitionHandle>();
var processedTypes = new HashSet<TypeDefinitionHandle>();
ProcessFiles(files);
while (workList.Count > 0)
{
var additionalFiles = workList
.GroupBy(GetFileFileNameForHandle, StringComparer.OrdinalIgnoreCase).ToList();
workList.Clear();
ProcessFiles(additionalFiles);
files.AddRange(additionalFiles);
progress.TotalUnits = files.Count;
}
return files.Select(f => ("Compile", f.Key)).Concat(WriteAssemblyInfo(ts, cancellationToken));
string GetFileFileNameForHandle(TypeDefinitionHandle h)
{
var type = metadata.GetTypeDefinition(h);
string file = CleanUpFileName(metadata.GetString(type.Name)) + ".cs";
string ns = metadata.GetString(type.Namespace);
@ -222,10 +243,11 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -222,10 +243,11 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
Directory.CreateDirectory(Path.Combine(TargetDirectory, dir));
return Path.Combine(dir, file);
}
}, StringComparer.OrdinalIgnoreCase).ToList();
var progressReporter = ProgressIndicator;
var progress = new DecompilationProgress { TotalUnits = files.Count, Title = "Exporting project..." };
DecompilerTypeSystem ts = new DecompilerTypeSystem(module, AssemblyResolver, Settings);
}
void ProcessFiles(List<IGrouping<string, TypeDefinitionHandle>> files)
{
processedTypes.AddRange(files.SelectMany(f => f));
Parallel.ForEach(
Partitioner.Create(files, loadBalance: true),
new ParallelOptions {
@ -245,7 +267,27 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -245,7 +267,27 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
}
decompiler.CancellationToken = cancellationToken;
var syntaxTree = decompiler.DecompileTypes(file.ToArray());
var declaredTypes = file.ToArray();
var syntaxTree = decompiler.DecompileTypes(declaredTypes);
foreach (var node in syntaxTree.Descendants)
{
var td = (node.GetResolveResult() as TypeResolveResult)?.Type.GetDefinition();
if (td?.ParentModule != ts.MainModule)
continue;
while (td?.DeclaringTypeDefinition != null)
{
td = td.DeclaringTypeDefinition;
}
if (td != null && td.MetadataToken is { IsNil: false } token && !processedTypes.Contains((TypeDefinitionHandle)token))
{
lock (workList)
{
workList.Add((TypeDefinitionHandle)token);
}
}
}
syntaxTree.AcceptVisitor(new CSharpOutputVisitor(w, Settings.CSharpFormattingOptions));
}
catch (Exception innerException) when (!(innerException is OperationCanceledException || innerException is DecompilerException))
@ -257,7 +299,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -257,7 +299,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
Interlocked.Increment(ref progress.UnitsCompleted);
progressReporter?.Report(progress);
});
return files.Select(f => ("Compile", f.Key)).Concat(WriteAssemblyInfo(ts, cancellationToken));
}
}
#endregion

Loading…
Cancel
Save