Browse Source

Add support for module references in ILSpy.

pull/1030/head
Siegfried Pammer 7 years ago
parent
commit
5ad3cf9143
  1. 5
      ILSpy/AssemblyList.cs
  2. 69
      ILSpy/LoadedAssembly.cs
  3. 37
      ILSpy/TreeNodes/ModuleReferenceTreeNode.cs
  4. 2
      ILSpy/TreeNodes/ReferenceFolderTreeNode.cs

5
ILSpy/AssemblyList.cs

@ -38,9 +38,10 @@ namespace ICSharpCode.ILSpy @@ -38,9 +38,10 @@ namespace ICSharpCode.ILSpy
/// <summary>Dirty flag, used to mark modifications so that the list is saved later</summary>
bool dirty;
internal readonly ConcurrentDictionary<(string assemblyName, bool isWinRT), LoadedAssembly> assemblyLookupCache = new ConcurrentDictionary<(string assemblyName, bool isWinRT), LoadedAssembly>();
internal readonly ConcurrentDictionary<string, LoadedAssembly> moduleLookupCache = new ConcurrentDictionary<string, LoadedAssembly>();
/// <summary>
/// The assemblies in this list.
/// Needs locking for multi-threaded access!

69
ILSpy/LoadedAssembly.cs

@ -220,7 +220,7 @@ namespace ICSharpCode.ILSpy @@ -220,7 +220,7 @@ namespace ICSharpCode.ILSpy
}
}
sealed class MyAssemblyResolver : Decompiler.Metadata.IAssemblyResolver
sealed class MyAssemblyResolver : IAssemblyResolver
{
readonly LoadedAssembly parent;
@ -233,6 +233,11 @@ namespace ICSharpCode.ILSpy @@ -233,6 +233,11 @@ namespace ICSharpCode.ILSpy
{
return parent.LookupReferencedAssembly(reference)?.GetPEFileOrNull();
}
public PEFile ResolveModule(PEFile mainModule, string moduleName)
{
return parent.LookupReferencedModule(mainModule, moduleName)?.GetPEFileOrNull();
}
}
public IAssemblyResolver GetAssemblyResolver()
@ -261,6 +266,15 @@ namespace ICSharpCode.ILSpy @@ -261,6 +266,15 @@ namespace ICSharpCode.ILSpy
}
}
public LoadedAssembly LookupReferencedModule(PEFile mainModule, string moduleName)
{
if (mainModule == null)
throw new ArgumentNullException(nameof(mainModule));
if (moduleName == null)
throw new ArgumentNullException(nameof(moduleName));
return assemblyList.moduleLookupCache.GetOrAdd(mainModule.FileName + ";" + moduleName, _ => LookupReferencedModuleInternal(mainModule, moduleName));
}
class MyUniversalResolver : UniversalAssemblyResolver
{
public MyUniversalResolver(LoadedAssembly assembly)
@ -326,7 +340,58 @@ namespace ICSharpCode.ILSpy @@ -326,7 +340,58 @@ namespace ICSharpCode.ILSpy
});
return asm;
}
LoadedAssembly LookupReferencedModuleInternal(PEFile mainModule, string moduleName)
{
string file;
LoadedAssembly asm;
lock (loadingAssemblies) {
foreach (LoadedAssembly loaded in assemblyList.GetAssemblies()) {
var reader = loaded.GetPEFileOrNull()?.Metadata;
if (reader == null || reader.IsAssembly) continue;
var moduleDef = reader.GetModuleDefinition();
if (moduleName.Equals(reader.GetString(moduleDef.Name), StringComparison.OrdinalIgnoreCase)) {
LoadedAssemblyReferencesInfo.AddMessageOnce(moduleName, MessageKind.Info, "Success - Found in Assembly List");
return loaded;
}
}
file = Path.Combine(Path.GetDirectoryName(mainModule.FileName), moduleName);
if (!File.Exists(file))
return null;
foreach (LoadedAssembly loaded in assemblyList.GetAssemblies()) {
if (loaded.FileName.Equals(file, StringComparison.OrdinalIgnoreCase)) {
return loaded;
}
}
if (file != null && loadingAssemblies.TryGetValue(file, out asm))
return asm;
if (assemblyLoadDisableCount > 0)
return null;
if (file != null) {
LoadedAssemblyReferencesInfo.AddMessage(moduleName, MessageKind.Info, "Success - Loading from: " + file);
asm = new LoadedAssembly(assemblyList, file) { IsAutoLoaded = true };
} else {
LoadedAssemblyReferencesInfo.AddMessageOnce(moduleName, MessageKind.Error, "Could not find reference: " + moduleName);
return null;
}
loadingAssemblies.Add(file, asm);
}
App.Current.Dispatcher.BeginInvoke((Action)delegate () {
lock (assemblyList.assemblies) {
assemblyList.assemblies.Add(asm);
}
lock (loadingAssemblies) {
loadingAssemblies.Remove(file);
}
});
return asm;
}
public Task ContinueWhenLoaded(Action<Task<PEFile>> onAssemblyLoaded, TaskScheduler taskScheduler)
{
return this.assemblyTask.ContinueWith(onAssemblyLoaded, default(CancellationToken), TaskContinuationOptions.RunContinuationsAsynchronously, taskScheduler);

37
ILSpy/TreeNodes/ModuleReferenceTreeNode.cs

@ -27,30 +27,53 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -27,30 +27,53 @@ namespace ICSharpCode.ILSpy.TreeNodes
/// </summary>
sealed class ModuleReferenceTreeNode : ILSpyTreeNode
{
readonly AssemblyTreeNode parentAssembly;
readonly MetadataReader metadata;
readonly ModuleReferenceHandle handle;
readonly ModuleReference reference;
readonly AssemblyFileHandle fileHandle;
readonly AssemblyFile file;
readonly string moduleName;
public ModuleReferenceTreeNode(ModuleReferenceHandle r, MetadataReader module)
public ModuleReferenceTreeNode(AssemblyTreeNode parentAssembly, ModuleReferenceHandle r, MetadataReader module)
{
this.parentAssembly = parentAssembly ?? throw new ArgumentNullException(nameof(parentAssembly));
if (r.IsNil)
throw new ArgumentNullException(nameof(r));
this.metadata = module;
this.handle = r;
this.reference = module.GetModuleReference(r);
this.moduleName = metadata.GetString(reference.Name);
foreach (var h in module.AssemblyFiles) {
var file = module.GetAssemblyFile(h);
if (module.StringComparer.Equals(file.Name, moduleName)) {
this.file = file;
this.fileHandle = h;
break;
}
}
}
public override object Text {
get { return metadata.GetString(reference.Name) + ((EntityHandle)handle).ToSuffixString(); }
get { return moduleName + ((EntityHandle)handle).ToSuffixString(); }
}
public override object Icon {
get { return Images.Library; }
public override object Icon => Images.Library;
public override void ActivateItem(System.Windows.RoutedEventArgs e)
{
var assemblyListNode = parentAssembly.Parent as AssemblyListTreeNode;
if (assemblyListNode != null && file.ContainsMetadata) {
assemblyListNode.Select(assemblyListNode.FindAssemblyNode(parentAssembly.LoadedAssembly.LookupReferencedModule(parentAssembly.LoadedAssembly.GetPEFileOrNull(), metadata.GetString(reference.Name))));
e.Handled = true;
}
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, metadata.GetString(reference.Name));
language.WriteCommentLine(output, moduleName);
language.WriteCommentLine(output, file.ContainsMetadata ? "contains metadata" : "contains no metadata");
}
}
}

2
ILSpy/TreeNodes/ReferenceFolderTreeNode.cs

@ -58,7 +58,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -58,7 +58,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
foreach (var r in module.AssemblyReferences.OrderBy(r => r.Name))
this.Children.Add(new AssemblyReferenceTreeNode(r, parentAssembly));
foreach (var r in metadata.GetModuleReferences().OrderBy(r => metadata.GetString(metadata.GetModuleReference(r).Name)))
this.Children.Add(new ModuleReferenceTreeNode(r, metadata));
this.Children.Add(new ModuleReferenceTreeNode(parentAssembly, r, metadata));
}
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)

Loading…
Cancel
Save