From 3c5d1845b3e1799c0a6dc6bf48887d49424a23ca Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Mon, 4 Sep 2017 22:35:57 +0200 Subject: [PATCH] Extend DecompilerTypeSystem to support transitive dependencies (type forwarders). --- .../TypeSystem/DecompilerTypeSystem.cs | 37 ++++++++++++++++++- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs index 57d04b0b9..8180985f1 100644 --- a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs +++ b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs @@ -45,15 +45,48 @@ namespace ICSharpCode.Decompiler.TypeSystem typeReferenceCecilLoader.SetCurrentModule(moduleDefinition); IUnresolvedAssembly mainAssembly = cecilLoader.LoadModule(moduleDefinition); var referencedAssemblies = new List(); - foreach (var asmRef in moduleDefinition.AssemblyReferences) { + var assemblyReferenceQueue = new Queue(moduleDefinition.AssemblyReferences); + var processedAssemblyReferences = new HashSet(AssemblyNameReferenceComparer.Instance); + while (assemblyReferenceQueue.Count > 0) { + var asmRef = assemblyReferenceQueue.Dequeue(); + if (!processedAssemblyReferences.Add(asmRef)) + continue; var asm = moduleDefinition.AssemblyResolver.Resolve(asmRef); - if (asm != null) + if (asm != null) { referencedAssemblies.Add(cecilLoader.LoadAssembly(asm)); + foreach (var forwarder in asm.MainModule.ExportedTypes) { + if (!forwarder.IsForwarder || !(forwarder.Scope is AssemblyNameReference forwarderRef)) continue; + assemblyReferenceQueue.Enqueue(forwarderRef); + } + } } compilation = new SimpleCompilation(mainAssembly, referencedAssemblies); + if (compilation.FindType(KnownTypeCode.Void).Kind == TypeKind.Unknown || compilation.FindType(KnownTypeCode.Void).Kind == TypeKind.Unknown) { + referencedAssemblies.Add(MinimalCorlib.Instance); + compilation = new SimpleCompilation(mainAssembly, referencedAssemblies); + } context = new SimpleTypeResolveContext(compilation.MainAssembly); } + class AssemblyNameReferenceComparer : IEqualityComparer + { + public static readonly AssemblyNameReferenceComparer Instance = new AssemblyNameReferenceComparer(); + + public bool Equals(AssemblyNameReference x, AssemblyNameReference y) + { + if (x == y) + return true; + if (x == null || y == null) + return false; + return x.FullName.Equals(y.FullName); + } + + public int GetHashCode(AssemblyNameReference obj) + { + return obj.FullName.GetHashCode(); + } + } + public ICompilation Compilation { get { return compilation; } }