Browse Source

Support resolving assembly references within a bundle.

pull/2191/head
Daniel Grunwald 5 years ago
parent
commit
0de6238d65
  1. 7
      ICSharpCode.Decompiler.Tests/RoundtripAssembly.cs
  2. 2
      ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectInfoProvider.cs
  3. 2
      ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterDefault.cs
  4. 4
      ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterSdkStyle.cs
  5. 9
      ICSharpCode.Decompiler/CSharp/ProjectDecompiler/WholeProjectDecompiler.cs
  6. 24
      ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs
  7. 9
      ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs
  8. 4
      ILSpy/AssemblyList.cs
  9. 2
      ILSpy/Languages/CSharpLanguage.cs
  10. 44
      ILSpy/LoadedAssembly.cs
  11. 74
      ILSpy/LoadedPackage.cs
  12. 4
      ILSpy/Properties/AssemblyInfo.template.cs
  13. 23
      ILSpy/TreeNodes/AssemblyListTreeNode.cs
  14. 19
      ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs
  15. 5
      ILSpy/TreeNodes/AssemblyTreeNode.cs
  16. 19
      ILSpy/TreeNodes/PackageFolderTreeNode.cs

7
ICSharpCode.Decompiler.Tests/RoundtripAssembly.cs

@ -30,7 +30,6 @@ using ICSharpCode.Decompiler.Metadata; @@ -30,7 +30,6 @@ using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Tests.Helpers;
using Microsoft.Build.Locator;
using Microsoft.Win32;
using NUnit.Framework;
@ -199,7 +198,7 @@ namespace ICSharpCode.Decompiler.Tests @@ -199,7 +198,7 @@ namespace ICSharpCode.Decompiler.Tests
settings.UseSdkStyleProjectFormat = false;
}
var decompiler = new TestProjectDecompiler(projectGuid, resolver, settings);
var decompiler = new TestProjectDecompiler(projectGuid, resolver, resolver, settings);
if (snkFilePath != null)
{
@ -318,8 +317,8 @@ namespace ICSharpCode.Decompiler.Tests @@ -318,8 +317,8 @@ namespace ICSharpCode.Decompiler.Tests
class TestProjectDecompiler : WholeProjectDecompiler
{
public TestProjectDecompiler(Guid projecGuid, IAssemblyResolver resolver, DecompilerSettings settings)
: base(settings, projecGuid, resolver, debugInfoProvider: null)
public TestProjectDecompiler(Guid projecGuid, IAssemblyResolver resolver, AssemblyReferenceClassifier assemblyReferenceClassifier, DecompilerSettings settings)
: base(settings, projecGuid, resolver, assemblyReferenceClassifier, debugInfoProvider: null)
{
}
}

2
ICSharpCode.Decompiler/CSharp/ProjectDecompiler/IProjectInfoProvider.cs

@ -32,6 +32,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -32,6 +32,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
/// </summary>
IAssemblyResolver AssemblyResolver { get; }
AssemblyReferenceClassifier AssemblyReferenceClassifier { get; }
/// <summary>
/// Gets the C# language version of the project.
/// </summary>

2
ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterDefault.cs

@ -153,7 +153,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -153,7 +153,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
w.WriteStartElement("Reference");
w.WriteAttributeString("Include", r.Name);
var asm = project.AssemblyResolver.Resolve(r);
if (asm != null && !project.AssemblyResolver.IsGacAssembly(r))
if (asm != null && !project.AssemblyReferenceClassifier.IsGacAssembly(r))
{
w.WriteElementString("HintPath", asm.FileName);
}

4
ICSharpCode.Decompiler/CSharp/ProjectDecompiler/ProjectFileWriterSdkStyle.cs

@ -256,7 +256,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -256,7 +256,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
foreach (var reference in module.AssemblyReferences.Where(r => !ImplicitReferences.Contains(r.Name)))
{
if (isNetCoreApp && project.AssemblyResolver.IsSharedAssembly(reference, out string runtimePack) && targetPacks.Contains(runtimePack))
if (isNetCoreApp && project.AssemblyReferenceClassifier.IsSharedAssembly(reference, out string runtimePack) && targetPacks.Contains(runtimePack))
{
continue;
}
@ -265,7 +265,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -265,7 +265,7 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
xml.WriteAttributeString("Include", reference.Name);
var asembly = project.AssemblyResolver.Resolve(reference);
if (asembly != null && !project.AssemblyResolver.IsGacAssembly(reference))
if (asembly != null && !project.AssemblyReferenceClassifier.IsGacAssembly(reference))
{
xml.WriteElementString("HintPath", FileUtility.GetRelativePath(project.TargetDirectory, asembly.FileName));
}

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

@ -66,6 +66,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -66,6 +66,8 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
public IAssemblyResolver AssemblyResolver { get; }
public AssemblyReferenceClassifier AssemblyReferenceClassifier { get; }
public IDebugInfoProvider DebugInfoProvider { get; }
/// <summary>
@ -94,15 +96,16 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -94,15 +96,16 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
#endregion
public WholeProjectDecompiler(IAssemblyResolver assemblyResolver)
: this(new DecompilerSettings(), assemblyResolver, debugInfoProvider: null)
: this(new DecompilerSettings(), assemblyResolver, assemblyReferenceClassifier: null, debugInfoProvider: null)
{
}
public WholeProjectDecompiler(
DecompilerSettings settings,
IAssemblyResolver assemblyResolver,
AssemblyReferenceClassifier assemblyReferenceClassifier,
IDebugInfoProvider debugInfoProvider)
: this(settings, Guid.NewGuid(), assemblyResolver, debugInfoProvider)
: this(settings, Guid.NewGuid(), assemblyResolver, assemblyReferenceClassifier, debugInfoProvider)
{
}
@ -110,11 +113,13 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler @@ -110,11 +113,13 @@ namespace ICSharpCode.Decompiler.CSharp.ProjectDecompiler
DecompilerSettings settings,
Guid projectGuid,
IAssemblyResolver assemblyResolver,
AssemblyReferenceClassifier assemblyReferenceClassifier,
IDebugInfoProvider debugInfoProvider)
{
Settings = settings ?? throw new ArgumentNullException(nameof(settings));
ProjectGuid = projectGuid;
AssemblyResolver = assemblyResolver ?? throw new ArgumentNullException(nameof(assemblyResolver));
AssemblyReferenceClassifier = assemblyReferenceClassifier ?? new AssemblyReferenceClassifier();
DebugInfoProvider = debugInfoProvider;
projectWriter = Settings.UseSdkStyleProjectFormat ? ProjectFileWriterSdkStyle.Create() : ProjectFileWriterDefault.Create();
}

24
ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs

@ -48,8 +48,28 @@ namespace ICSharpCode.Decompiler.Metadata @@ -48,8 +48,28 @@ namespace ICSharpCode.Decompiler.Metadata
PEFile Resolve(IAssemblyReference reference);
PEFile ResolveModule(PEFile mainModule, string moduleName);
#endif
bool IsGacAssembly(IAssemblyReference reference);
bool IsSharedAssembly(IAssemblyReference reference, out string runtimePack);
}
public class AssemblyReferenceClassifier
{
/// <summary>
/// For GAC assembly references, the WholeProjectDecompiler will omit the HintPath in the
/// generated .csproj file.
/// </summary>
public virtual bool IsGacAssembly(IAssemblyReference reference)
{
return UniversalAssemblyResolver.GetAssemblyInGac(reference) != null;
}
/// <summary>
/// For .NET Core framework references, the WholeProjectDecompiler will omit the
/// assembly reference if the runtimePack is already included as an SDK.
/// </summary>
public virtual bool IsSharedAssembly(IAssemblyReference reference, out string runtimePack)
{
runtimePack = null;
return false;
}
}
public interface IAssemblyReference

9
ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs

@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler.Metadata
}
// This is inspired by Mono.Cecil's BaseAssemblyResolver/DefaultAssemblyResolver.
public class UniversalAssemblyResolver : IAssemblyResolver
public class UniversalAssemblyResolver : AssemblyReferenceClassifier, IAssemblyResolver
{
static UniversalAssemblyResolver()
{
@ -184,12 +184,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -184,12 +184,7 @@ namespace ICSharpCode.Decompiler.Metadata
}
#endif
public virtual bool IsGacAssembly(IAssemblyReference reference)
{
return GetAssemblyInGac(reference) != null;
}
public virtual bool IsSharedAssembly(IAssemblyReference reference, out string runtimePack)
public override bool IsSharedAssembly(IAssemblyReference reference, out string runtimePack)
{
return dotNetCorePathFinder.TryResolveDotNetCoreShared(reference, out runtimePack) != null;
}

4
ILSpy/AssemblyList.cs

@ -204,7 +204,7 @@ namespace ICSharpCode.ILSpy @@ -204,7 +204,7 @@ namespace ICSharpCode.ILSpy
return asm;
}
var newAsm = new LoadedAssembly(this, file, Task.FromResult(stream));
var newAsm = new LoadedAssembly(this, file, stream: Task.FromResult(stream));
newAsm.IsAutoLoaded = isAutoLoaded;
lock (assemblies)
{
@ -227,7 +227,7 @@ namespace ICSharpCode.ILSpy @@ -227,7 +227,7 @@ namespace ICSharpCode.ILSpy
return null;
var index = this.assemblies.IndexOf(target);
var newAsm = new LoadedAssembly(this, file, Task.FromResult(stream));
var newAsm = new LoadedAssembly(this, file, stream: Task.FromResult(stream));
newAsm.IsAutoLoaded = target.IsAutoLoaded;
lock (assemblies)
{

2
ILSpy/Languages/CSharpLanguage.cs

@ -489,7 +489,7 @@ namespace ICSharpCode.ILSpy @@ -489,7 +489,7 @@ namespace ICSharpCode.ILSpy
readonly DecompilationOptions options;
public ILSpyWholeProjectDecompiler(LoadedAssembly assembly, DecompilationOptions options)
: base(options.DecompilerSettings, assembly.GetAssemblyResolver(), assembly.GetDebugInfoOrNull())
: base(options.DecompilerSettings, assembly.GetAssemblyResolver(), assembly.GetAssemblyReferenceClassifier(), assembly.GetDebugInfoOrNull())
{
this.assembly = assembly;
this.options = options;

44
ILSpy/LoadedAssembly.cs

@ -41,7 +41,9 @@ namespace ICSharpCode.ILSpy @@ -41,7 +41,9 @@ namespace ICSharpCode.ILSpy
/// <summary>
/// Represents a file loaded into ILSpy.
///
/// Note: the file is not necessarily an assembly.
/// Note: this class is misnamed.
/// The file is not necessarily an assembly, nor is it necessarily loaded.
///
/// A LoadedAssembly can refer to:
/// * a .NET module (single-file) loaded into ILSpy
/// * a non-existant file
@ -79,17 +81,27 @@ namespace ICSharpCode.ILSpy @@ -79,17 +81,27 @@ namespace ICSharpCode.ILSpy
readonly AssemblyList assemblyList;
readonly string fileName;
readonly string shortName;
readonly IAssemblyResolver providedAssemblyResolver;
public LoadedAssembly ParentBundle { get; }
public LoadedAssembly(AssemblyList assemblyList, string fileName, Task<Stream> stream = null)
public LoadedAssembly(AssemblyList assemblyList, string fileName, Task<Stream> stream = null, IAssemblyResolver assemblyResolver = null)
{
this.assemblyList = assemblyList ?? throw new ArgumentNullException(nameof(assemblyList));
this.fileName = fileName ?? throw new ArgumentNullException(nameof(fileName));
this.providedAssemblyResolver = assemblyResolver;
this.loadingTask = Task.Run(() => LoadAsync(stream)); // requires that this.fileName is set
this.shortName = Path.GetFileNameWithoutExtension(fileName);
this.resolver = new MyAssemblyResolver(this);
}
public LoadedAssembly(LoadedAssembly bundle, string fileName, Task<Stream> stream, IAssemblyResolver assemblyResolver = null)
: this(bundle.assemblyList, fileName, stream, assemblyResolver)
{
this.ParentBundle = bundle;
}
/// <summary>
/// Returns a target framework identifier in the form '&lt;framework&gt;Version=v&lt;version&gt;'.
/// Returns an empty string if no TargetFrameworkAttribute was found or the file doesn't contain an assembly header, i.e., is only a module.
@ -265,12 +277,14 @@ namespace ICSharpCode.ILSpy @@ -265,12 +277,14 @@ namespace ICSharpCode.ILSpy
var bundle = LoadedPackage.FromBundle(fileName);
if (bundle != null)
{
bundle.LoadedAssembly = this;
return new LoadResult(loadAssemblyException, bundle);
}
// If it's not a .NET module, maybe it's a zip archive (e.g. .nupkg)
try
{
var zip = LoadedPackage.FromZipFile(fileName);
zip.LoadedAssembly = this;
return new LoadResult(loadAssemblyException, zip);
}
catch (InvalidDataException)
@ -364,24 +378,19 @@ namespace ICSharpCode.ILSpy @@ -364,24 +378,19 @@ namespace ICSharpCode.ILSpy
this.parent = parent;
}
public bool IsGacAssembly(IAssemblyReference reference)
{
return parent.universalResolver?.IsGacAssembly(reference) == true;
}
public bool IsSharedAssembly(IAssemblyReference reference, out string runtimePack)
{
runtimePack = null;
return parent.universalResolver?.IsSharedAssembly(reference, out runtimePack) == true;
}
public PEFile Resolve(Decompiler.Metadata.IAssemblyReference reference)
public PEFile Resolve(IAssemblyReference reference)
{
var module = parent.providedAssemblyResolver?.Resolve(reference);
if (module != null)
return module;
return parent.LookupReferencedAssembly(reference)?.GetPEFileOrNull();
}
public PEFile ResolveModule(PEFile mainModule, string moduleName)
{
var module = parent.providedAssemblyResolver?.ResolveModule(mainModule, moduleName);
if (module != null)
return module;
return parent.LookupReferencedModule(mainModule, moduleName)?.GetPEFileOrNull();
}
}
@ -393,6 +402,11 @@ namespace ICSharpCode.ILSpy @@ -393,6 +402,11 @@ namespace ICSharpCode.ILSpy
return resolver;
}
public AssemblyReferenceClassifier GetAssemblyReferenceClassifier()
{
return universalResolver;
}
/// <summary>
/// Returns the debug info for this assembly. Returns null in case of load errors or no debug info is available.
/// </summary>
@ -439,6 +453,8 @@ namespace ICSharpCode.ILSpy @@ -439,6 +453,8 @@ namespace ICSharpCode.ILSpy
MyUniversalResolver universalResolver;
/// <summary>
/// 0) if we're inside a package, look for filename.dll in parent directories
/// (this step already happens in MyAssemblyResolver; not in LookupReferencedAssembly)
/// 1) try to find exact match by tfm + full asm name in loaded assemblies
/// 2) try to find match in search paths
/// 3) if a.deps.json is found: search %USERPROFILE%/.nuget/packages/* as well

74
ILSpy/LoadedPackage.cs

@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@ -23,6 +24,7 @@ using System.IO.Compression; @@ -23,6 +24,7 @@ using System.IO.Compression;
using System.IO.MemoryMappedFiles;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
@ -40,6 +42,11 @@ namespace ICSharpCode.ILSpy @@ -40,6 +42,11 @@ namespace ICSharpCode.ILSpy
Bundle,
}
/// <summary>
/// Gets the LoadedAssembly instance representing this bundle.
/// </summary>
internal LoadedAssembly LoadedAssembly { get; set; }
public PackageKind Kind { get; }
/// <summary>
@ -47,8 +54,7 @@ namespace ICSharpCode.ILSpy @@ -47,8 +54,7 @@ namespace ICSharpCode.ILSpy
/// </summary>
public IReadOnlyList<PackageEntry> Entries { get; }
internal IReadOnlyList<PackageEntry> TopLevelEntries { get; }
internal IReadOnlyList<PackageFolder> TopLevelFolders { get; }
internal PackageFolder RootFolder { get; }
public LoadedPackage(PackageKind kind, IEnumerable<PackageEntry> entries)
{
@ -56,15 +62,14 @@ namespace ICSharpCode.ILSpy @@ -56,15 +62,14 @@ namespace ICSharpCode.ILSpy
this.Entries = entries.ToArray();
var topLevelEntries = new List<PackageEntry>();
var folders = new Dictionary<string, PackageFolder>();
var rootFolder = new PackageFolder("");
var rootFolder = new PackageFolder(this, null, "");
folders.Add("", rootFolder);
foreach (var entry in this.Entries)
{
var (dirname, filename) = SplitName(entry.Name);
GetFolder(dirname).Entries.Add(new FolderEntry(filename, entry));
}
this.TopLevelEntries = rootFolder.Entries;
this.TopLevelFolders = rootFolder.Folders;
this.RootFolder = rootFolder;
static (string, string) SplitName(string filename)
{
@ -81,7 +86,7 @@ namespace ICSharpCode.ILSpy @@ -81,7 +86,7 @@ namespace ICSharpCode.ILSpy
return result;
var (dirname, basename) = SplitName(name);
PackageFolder parent = GetFolder(dirname);
result = new PackageFolder(basename);
result = new PackageFolder(this, parent, basename);
parent.Folders.Add(result);
folders.Add(name, result);
return result;
@ -205,19 +210,72 @@ namespace ICSharpCode.ILSpy @@ -205,19 +210,72 @@ namespace ICSharpCode.ILSpy
public abstract string FullName { get; }
}
class PackageFolder
class PackageFolder : IAssemblyResolver
{
/// <summary>
/// Gets the short name of the folder.
/// </summary>
public string Name { get; }
public PackageFolder(string name)
readonly LoadedPackage package;
readonly PackageFolder parent;
internal PackageFolder(LoadedPackage package, PackageFolder parent, string name)
{
this.package = package;
this.parent = parent;
this.Name = name;
}
public List<PackageFolder> Folders { get; } = new List<PackageFolder>();
public List<PackageEntry> Entries { get; } = new List<PackageEntry>();
public PEFile Resolve(IAssemblyReference reference)
{
var asm = ResolveFileName(reference.Name + ".dll");
if (asm != null)
{
return asm.GetPEFileOrNull();
}
return parent?.Resolve(reference);
}
public PEFile ResolveModule(PEFile mainModule, string moduleName)
{
var asm = ResolveFileName(moduleName + ".dll");
if (asm != null)
{
return asm.GetPEFileOrNull();
}
return parent?.ResolveModule(mainModule, moduleName);
}
readonly Dictionary<string, LoadedAssembly> assemblies = new Dictionary<string, LoadedAssembly>(StringComparer.OrdinalIgnoreCase);
internal LoadedAssembly ResolveFileName(string name)
{
if (package.LoadedAssembly == null)
return null;
lock (assemblies)
{
if (assemblies.TryGetValue(name, out var asm))
return asm;
var entry = Entries.FirstOrDefault(e => string.Equals(name, e.Name, StringComparison.OrdinalIgnoreCase));
if (entry != null)
{
asm = new LoadedAssembly(
package.LoadedAssembly, entry.Name,
assemblyResolver: this,
stream: Task.Run(entry.TryOpenStream)
);
}
else
{
asm = null;
}
assemblies.Add(name, asm);
return asm;
}
}
}
}

4
ILSpy/Properties/AssemblyInfo.template.cs

@ -36,8 +36,8 @@ using System.Runtime.InteropServices; @@ -36,8 +36,8 @@ using System.Runtime.InteropServices;
internal static class RevisionClass
{
public const string Major = "6";
public const string Minor = "3";
public const string Major = "7";
public const string Minor = "0";
public const string Build = "0";
public const string Revision = "$INSERTREVISION$";
public const string VersionName = "preview1";

23
ILSpy/TreeNodes/AssemblyListTreeNode.cs

@ -25,6 +25,7 @@ using System.Windows; @@ -25,6 +25,7 @@ using System.Windows;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
using ICSharpCode.TreeView;
namespace ICSharpCode.ILSpy.TreeNodes
@ -182,13 +183,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -182,13 +183,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
{
if (module == null)
return null;
App.Current.Dispatcher.VerifyAccess();
foreach (AssemblyTreeNode node in this.Children)
{
if (node.LoadedAssembly.IsLoaded && node.LoadedAssembly.GetPEFileOrNull()?.FileName == module.FileName)
return node;
}
return null;
return FindAssemblyNode(module.GetLoadedAssembly());
}
public AssemblyTreeNode FindAssemblyNode(LoadedAssembly asm)
@ -196,11 +191,25 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -196,11 +191,25 @@ namespace ICSharpCode.ILSpy.TreeNodes
if (asm == null)
return null;
App.Current.Dispatcher.VerifyAccess();
if (asm.ParentBundle != null)
{
var bundle = FindAssemblyNode(asm.ParentBundle);
if (bundle == null)
return null;
foreach (var node in TreeTraversal.PreOrder(bundle.Children, r => (r as PackageFolderTreeNode)?.Children).OfType<AssemblyTreeNode>())
{
if (node.LoadedAssembly == asm)
return node;
}
}
else
{
foreach (AssemblyTreeNode node in this.Children)
{
if (node.LoadedAssembly == asm)
return node;
}
}
return null;
}

19
ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs

@ -56,29 +56,22 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -56,29 +56,22 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override void ActivateItem(System.Windows.RoutedEventArgs e)
{
var assemblyListNode = parentAssembly.Parent as AssemblyListTreeNode;
if (assemblyListNode != null)
if (parentAssembly.Parent is AssemblyListTreeNode assemblyListNode)
{
assemblyListNode.Select(assemblyListNode.FindAssemblyNode(parentAssembly.LoadedAssembly.LookupReferencedAssembly(r)));
var resolver = parentAssembly.LoadedAssembly.GetAssemblyResolver();
assemblyListNode.Select(assemblyListNode.FindAssemblyNode(resolver.Resolve(r)));
e.Handled = true;
}
}
protected override void LoadChildren()
{
var assemblyListNode = parentAssembly.Parent as AssemblyListTreeNode;
if (assemblyListNode != null)
{
var refNode = assemblyListNode.FindAssemblyNode(parentAssembly.LoadedAssembly.LookupReferencedAssembly(r));
if (refNode != null)
{
var module = refNode.LoadedAssembly.GetPEFileOrNull();
var resolver = parentAssembly.LoadedAssembly.GetAssemblyResolver();
var module = resolver.Resolve(r);
if (module != null)
{
foreach (var childRef in module.AssemblyReferences)
this.Children.Add(new AssemblyReferenceTreeNode(childRef, refNode));
}
}
this.Children.Add(new AssemblyReferenceTreeNode(childRef, parentAssembly));
}
}

5
ILSpy/TreeNodes/AssemblyTreeNode.cs

@ -182,7 +182,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -182,7 +182,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
else if (loadResult.Package != null)
{
var package = loadResult.Package;
this.Children.AddRange(PackageFolderTreeNode.LoadChildrenForFolder(package.TopLevelFolders, package.TopLevelEntries));
this.Children.AddRange(PackageFolderTreeNode.LoadChildrenForFolder(package.RootFolder));
}
}
@ -460,13 +460,14 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -460,13 +460,14 @@ namespace ICSharpCode.ILSpy.TreeNodes
foreach (var node in context.SelectedTreeNodes)
{
var la = ((AssemblyTreeNode)node).LoadedAssembly;
var resolver = la.GetAssemblyResolver();
var module = la.GetPEFileOrNull();
if (module != null)
{
var metadata = module.Metadata;
foreach (var assyRef in metadata.AssemblyReferences)
{
la.LookupReferencedAssembly(new AssemblyReference(module, assyRef));
resolver.Resolve(new AssemblyReference(module, assyRef));
}
}
}

19
ILSpy/TreeNodes/PackageFolderTreeNode.cs

@ -19,7 +19,6 @@ @@ -19,7 +19,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ICSharpCode.Decompiler;
using ICSharpCode.TreeView;
@ -48,12 +47,12 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -48,12 +47,12 @@ namespace ICSharpCode.ILSpy.TreeNodes
protected override void LoadChildren()
{
this.Children.AddRange(LoadChildrenForFolder(folder.Folders, folder.Entries));
this.Children.AddRange(LoadChildrenForFolder(folder));
}
internal static IEnumerable<SharpTreeNode> LoadChildrenForFolder(IReadOnlyList<PackageFolder> folders, IReadOnlyList<PackageEntry> entries)
internal static IEnumerable<SharpTreeNode> LoadChildrenForFolder(PackageFolder root)
{
foreach (var folder in folders.OrderBy(f => f.Name))
foreach (var folder in root.Folders.OrderBy(f => f.Name))
{
string newName = folder.Name;
var subfolder = folder;
@ -65,12 +64,13 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -65,12 +64,13 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
yield return new PackageFolderTreeNode(subfolder, newName);
}
foreach (var entry in entries.OrderBy(e => e.Name))
foreach (var entry in root.Entries.OrderBy(e => e.Name))
{
if (entry.Name.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
{
var asmList = MainWindow.Instance.CurrentAssemblyList;
var asm = new LoadedAssembly(asmList, entry.Name, Task.Run(entry.TryOpenStream));
var asm = root.ResolveFileName(entry.Name);
if (asm != null)
{
yield return new AssemblyTreeNode(asm);
}
else
@ -78,6 +78,11 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -78,6 +78,11 @@ namespace ICSharpCode.ILSpy.TreeNodes
yield return ResourceTreeNode.Create(entry);
}
}
else
{
yield return ResourceTreeNode.Create(entry);
}
}
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)

Loading…
Cancel
Save