Browse Source

Refactoring of LookupReferencedAssemblyInternal

pull/1012/head
Siegfried Pammer 8 years ago
parent
commit
0e0291a113
  1. 2
      ICSharpCode.Decompiler/DotNetCore/DotNetCorePathFinder.cs
  2. 35
      ICSharpCode.Decompiler/DotNetCore/DotNetCorePathFinderExtensions.cs
  3. 5
      ILSpy/AssemblyList.cs
  4. 2
      ILSpy/Languages/CSharpLanguage.cs
  5. 107
      ILSpy/LoadedAssembly.cs
  6. 2
      ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs
  7. 2
      ILSpy/TreeNodes/AssemblyTreeNode.cs

2
ICSharpCode.Decompiler/DotNetCore/DotNetCorePathFinder.cs

@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler @@ -43,7 +43,7 @@ namespace ICSharpCode.Decompiler
readonly string version;
readonly string dotnetBasePath = FindDotNetExeDirectory();
public DotNetCorePathFinder(string parentAssemblyFileName, string targetFrameworkId, string version, Dictionary<string, UnresolvedAssemblyNameReference> loadInfo = null)
public DotNetCorePathFinder(string parentAssemblyFileName, string targetFrameworkId, string version, ReferenceLoadInfo loadInfo = null)
{
this.assemblyName = Path.GetFileNameWithoutExtension(parentAssemblyFileName);
this.basePath = Path.GetDirectoryName(parentAssemblyFileName);

35
ICSharpCode.Decompiler/DotNetCore/DotNetCorePathFinderExtensions.cs

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using Mono.Cecil;
@ -25,16 +26,36 @@ namespace ICSharpCode.Decompiler @@ -25,16 +26,36 @@ namespace ICSharpCode.Decompiler
return string.Empty;
}
}
public class ReferenceLoadInfo
{
readonly Dictionary<string, UnresolvedAssemblyNameReference> loadedAssemblyReferences = new Dictionary<string, UnresolvedAssemblyNameReference>();
public void AddMessage(string fullName, MessageKind kind, string message)
{
lock (loadedAssemblyReferences) {
if (!loadedAssemblyReferences.TryGetValue(fullName, out var referenceInfo)) {
referenceInfo = new UnresolvedAssemblyNameReference(fullName);
loadedAssemblyReferences.Add(fullName, referenceInfo);
}
referenceInfo.Messages.Add((kind, message));
}
}
public static void AddMessage(this Dictionary<string, UnresolvedAssemblyNameReference> container, string fullName, MessageKind kind, string message)
public bool TryGetInfo(string fullName, out UnresolvedAssemblyNameReference info)
{
if (container == null)
throw new ArgumentNullException(nameof(container));
if (!container.TryGetValue(fullName, out var referenceInfo)) {
referenceInfo = new UnresolvedAssemblyNameReference(fullName);
container.Add(fullName, referenceInfo);
lock (loadedAssemblyReferences) {
return loadedAssemblyReferences.TryGetValue(fullName, out info);
}
}
public bool HasErrors {
get {
lock (loadedAssemblyReferences) {
return loadedAssemblyReferences.Any(i => i.Value.HasErrors);
}
}
referenceInfo.Messages.Add((kind, message));
}
}
}

5
ILSpy/AssemblyList.cs

@ -23,6 +23,7 @@ using System.Collections.ObjectModel; @@ -23,6 +23,7 @@ using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Threading;
using System.Xml.Linq;
@ -38,8 +39,7 @@ namespace ICSharpCode.ILSpy @@ -38,8 +39,7 @@ namespace ICSharpCode.ILSpy
/// <summary>Dirty flag, used to mark modifications so that the list is saved later</summary>
bool dirty;
internal readonly ConcurrentDictionary<string, LoadedAssembly> assemblyLookupCache = new ConcurrentDictionary<string, LoadedAssembly>();
internal readonly ConcurrentDictionary<string, LoadedAssembly> winRTMetadataLookupCache = new ConcurrentDictionary<string, LoadedAssembly>();
internal readonly ConcurrentDictionary<(string assemblyName, bool isWinRT), LoadedAssembly> assemblyLookupCache = new ConcurrentDictionary<(string assemblyName, bool isWinRT), LoadedAssembly>();
/// <summary>
/// The assemblies in this list.
@ -136,7 +136,6 @@ namespace ICSharpCode.ILSpy @@ -136,7 +136,6 @@ namespace ICSharpCode.ILSpy
internal void ClearCache()
{
assemblyLookupCache.Clear();
winRTMetadataLookupCache.Clear();
}
public LoadedAssembly Open(string assemblyUri, bool isAutoLoaded = false)

2
ILSpy/Languages/CSharpLanguage.cs

@ -289,7 +289,7 @@ namespace ICSharpCode.ILSpy @@ -289,7 +289,7 @@ namespace ICSharpCode.ILSpy
void AddReferenceWarningMessage(AssemblyDefinition assembly, ITextOutput output)
{
var loadedAssembly = MainWindow.Instance.CurrentAssemblyList.GetAssemblies().FirstOrDefault(la => la.GetAssemblyDefinitionAsync().Result == assembly);
if (loadedAssembly == null || !loadedAssembly.LoadedAssemblyReferencesInfo.Any(i => i.Value.HasErrors))
if (loadedAssembly == null || !loadedAssembly.LoadedAssemblyReferencesInfo.HasErrors)
return;
const string line1 = "Warning: Some assembly references could not be loaded. This might lead to incorrect decompilation of some parts,";
const string line2 = "for ex. property getter/setter access. To get optimal decompilation results, please manually add the references to the list of loaded assemblies.";

107
ILSpy/LoadedAssembly.cs

@ -38,7 +38,6 @@ namespace ICSharpCode.ILSpy @@ -38,7 +38,6 @@ namespace ICSharpCode.ILSpy
readonly AssemblyList assemblyList;
readonly string fileName;
readonly string shortName;
readonly Dictionary<string, UnresolvedAssemblyNameReference> loadedAssemblyReferences = new Dictionary<string, UnresolvedAssemblyNameReference>();
public LoadedAssembly(AssemblyList assemblyList, string fileName, Stream stream = null)
{
@ -63,7 +62,7 @@ namespace ICSharpCode.ILSpy @@ -63,7 +62,7 @@ namespace ICSharpCode.ILSpy
return assembly?.DetectTargetFrameworkId() ?? string.Empty;
}
public Dictionary<string, UnresolvedAssemblyNameReference> LoadedAssemblyReferencesInfo => loadedAssemblyReferences;
public ReferenceLoadInfo LoadedAssemblyReferencesInfo { get; } = new ReferenceLoadInfo();
/// <summary>
/// Gets the Cecil ModuleDefinition.
@ -206,18 +205,6 @@ namespace ICSharpCode.ILSpy @@ -206,18 +205,6 @@ namespace ICSharpCode.ILSpy
var node = parent.LookupReferencedAssembly(name);
return node != null ? node.GetAssemblyDefinitionAsync().Result : null;
}
public AssemblyDefinition Resolve(string fullName)
{
var node = parent.LookupReferencedAssembly(fullName);
return node != null ? node.GetAssemblyDefinitionAsync().Result : null;
}
public AssemblyDefinition Resolve(string fullName, ReaderParameters parameters)
{
var node = parent.LookupReferencedAssembly(fullName);
return node != null ? node.GetAssemblyDefinitionAsync().Result : null;
}
public void Dispose()
{
@ -234,16 +221,11 @@ namespace ICSharpCode.ILSpy @@ -234,16 +221,11 @@ namespace ICSharpCode.ILSpy
if (name == null)
throw new ArgumentNullException(nameof(name));
if (name.IsWindowsRuntime) {
return assemblyList.winRTMetadataLookupCache.GetOrAdd(name.Name, LookupWinRTMetadata);
return assemblyList.assemblyLookupCache.GetOrAdd((name.Name, true), LookupReferencedAssemblyInternal);
} else {
return assemblyList.assemblyLookupCache.GetOrAdd(name.FullName, LookupReferencedAssemblyInternal);
return assemblyList.assemblyLookupCache.GetOrAdd((name.FullName, false), LookupReferencedAssemblyInternal);
}
}
public LoadedAssembly LookupReferencedAssembly(string fullName)
{
return assemblyList.assemblyLookupCache.GetOrAdd(fullName, LookupReferencedAssemblyInternal);
}
class MyUniversalResolver : UniversalAssemblyResolver
{
@ -253,55 +235,52 @@ namespace ICSharpCode.ILSpy @@ -253,55 +235,52 @@ namespace ICSharpCode.ILSpy
}
}
LoadedAssembly LookupReferencedAssemblyInternal(string fullName)
static Dictionary<string, LoadedAssembly> loadingAssemblies = new Dictionary<string, LoadedAssembly>();
LoadedAssembly LookupReferencedAssemblyInternal((string fullName, bool isWinRT) data)
{
foreach (LoadedAssembly asm in assemblyList.GetAssemblies()) {
var asmDef = asm.GetAssemblyDefinitionAsync().Result;
if (asmDef != null && fullName.Equals(asmDef.FullName, StringComparison.OrdinalIgnoreCase)) {
return asm;
string file;
LoadedAssembly asm;
lock (loadingAssemblies) {
foreach (LoadedAssembly loaded in assemblyList.GetAssemblies()) {
var asmDef = loaded.GetAssemblyDefinitionAsync().Result;
if (asmDef != null && data.fullName.Equals(data.isWinRT ? asmDef.Name.Name : asmDef.FullName, StringComparison.OrdinalIgnoreCase)) {
return loaded;
}
}
}
if (assemblyLoadDisableCount > 0)
return null;
if (!App.Current.Dispatcher.CheckAccess()) {
// Call this method on the GUI thread.
return (LoadedAssembly)App.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Func<string, LoadedAssembly>(LookupReferencedAssembly), fullName);
}
var resolver = new MyUniversalResolver(this) { TargetFramework = GetTargetFrameworkIdAsync().Result };
var name = AssemblyNameReference.Parse(fullName);
var file = resolver.FindAssemblyFile(name);
if (assemblyLoadDisableCount > 0)
return null;
if (file != null) {
loadedAssemblyReferences.AddMessage(fullName, MessageKind.Info, "Success - Loading from: " + file);
return assemblyList.OpenAssembly(file, true);
} else {
loadedAssemblyReferences.AddMessage(fullName, MessageKind.Error, "Could not find reference: " + fullName);
return null;
}
}
LoadedAssembly LookupWinRTMetadata(string name)
{
foreach (LoadedAssembly asm in assemblyList.GetAssemblies()) {
var asmDef = asm.GetAssemblyDefinitionAsync().Result;
if (asmDef!= null && name.Equals(asmDef.Name.Name, StringComparison.OrdinalIgnoreCase))
if (data.isWinRT) {
file = Path.Combine(Environment.SystemDirectory, "WinMetadata", data.fullName + ".winmd");
} else {
var resolver = new MyUniversalResolver(this) { TargetFramework = GetTargetFrameworkIdAsync().Result };
var name = AssemblyNameReference.Parse(data.fullName);
file = resolver.FindAssemblyFile(name);
}
if (loadingAssemblies.TryGetValue(file, out asm))
return asm;
if (file != null) {
LoadedAssemblyReferencesInfo.AddMessage(data.fullName, MessageKind.Info, "Success - Loading from: " + file);
asm = new LoadedAssembly(assemblyList, file) { IsAutoLoaded = true };
} else {
LoadedAssemblyReferencesInfo.AddMessage(data.fullName, MessageKind.Error, "Could not find reference: " + data.fullName);
return null;
}
loadingAssemblies.Add(file, asm);
}
if (assemblyLoadDisableCount > 0)
return null;
if (!App.Current.Dispatcher.CheckAccess()) {
// Call this method on the GUI thread.
return (LoadedAssembly)App.Current.Dispatcher.Invoke(DispatcherPriority.Normal, new Func<string, LoadedAssembly>(LookupWinRTMetadata), name);
}
string file = Path.Combine(Environment.SystemDirectory, "WinMetadata", name + ".winmd");
if (File.Exists(file)) {
return assemblyList.OpenAssembly(file, true);
} else {
return null;
}
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<ModuleDefinition>> onAssemblyLoaded, TaskScheduler taskScheduler)

2
ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs

@ -88,7 +88,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -88,7 +88,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
var loaded = parentAssembly.LoadedAssembly.LoadedAssemblyReferencesInfo.TryGetValue(r.FullName, out var info);
var loaded = parentAssembly.LoadedAssembly.LoadedAssemblyReferencesInfo.TryGetInfo(r.FullName, out var info);
if (r.IsWindowsRuntime) {
language.WriteCommentLine(output, r.Name + " [WinRT]" + (!loaded ? " (unresolved)" : ""));
} else {

2
ILSpy/TreeNodes/AssemblyTreeNode.cs

@ -384,7 +384,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -384,7 +384,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
var la = ((AssemblyTreeNode)node).LoadedAssembly;
if (!la.HasLoadError) {
foreach (var assyRef in la.GetModuleDefinitionAsync().Result.AssemblyReferences) {
la.LookupReferencedAssembly(assyRef.FullName);
la.LookupReferencedAssembly(assyRef);
}
}
}

Loading…
Cancel
Save