From 2d478af943488546cf7ef7b77df3584a1ccf72b1 Mon Sep 17 00:00:00 2001 From: Giuseppe Lippolis Date: Sat, 17 Jun 2023 11:00:25 +0200 Subject: [PATCH] feat(UI): Use AssemblyWarning when AssemblyReference load faulted Allow you to easily and quickly see the reference libraries not found fixes #2932 --- ILSpy/Images/AssemblyLoading.svg | 49 ++++++++++++++++++++ ILSpy/Images/AssemblyLoading.xaml | 28 +++++++++++ ILSpy/Images/Images.cs | 1 + ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs | 47 +++++++++++++++---- 4 files changed, 116 insertions(+), 9 deletions(-) create mode 100644 ILSpy/Images/AssemblyLoading.svg create mode 100644 ILSpy/Images/AssemblyLoading.xaml diff --git a/ILSpy/Images/AssemblyLoading.svg b/ILSpy/Images/AssemblyLoading.svg new file mode 100644 index 0000000000..9281b25e61 --- /dev/null +++ b/ILSpy/Images/AssemblyLoading.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + diff --git a/ILSpy/Images/AssemblyLoading.xaml b/ILSpy/Images/AssemblyLoading.xaml new file mode 100644 index 0000000000..cd2fb7143c --- /dev/null +++ b/ILSpy/Images/AssemblyLoading.xaml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ILSpy/Images/Images.cs b/ILSpy/Images/Images.cs index 49dfde0fd6..b11bbc64cd 100644 --- a/ILSpy/Images/Images.cs +++ b/ILSpy/Images/Images.cs @@ -51,6 +51,7 @@ static ImageSource Load(string icon) public static readonly ImageSource Assembly = Load("Assembly"); public static readonly ImageSource AssemblyWarning = Load("AssemblyWarning"); + public static readonly ImageSource AssemblyLoading = Load(nameof(AssemblyLoading)); public static readonly ImageSource FindAssembly = Load("FindAssembly"); public static readonly ImageSource Library = Load("Library"); diff --git a/ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs b/ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs index 3db5f974ee..6ab93dfd67 100644 --- a/ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs +++ b/ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs @@ -1,14 +1,14 @@ // Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team -// +// // Permission is hereby granted, free of charge, to any person obtaining a copy of this // software and associated documentation files (the "Software"), to deal in the Software // without restriction, including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons // to whom the Software is furnished to do so, subject to the following conditions: -// +// // The above copyright notice and this permission notice shall be included in all copies or // substantial portions of the Software. -// +// // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE @@ -30,9 +30,18 @@ namespace ICSharpCode.ILSpy.TreeNodes /// public sealed class AssemblyReferenceTreeNode : ILSpyTreeNode { + private enum LoadState + { + Unloaded, + Loading, + Loadded, + Failed + } readonly MetadataModule module; readonly AssemblyReference r; readonly AssemblyTreeNode parentAssembly; + MetadataFile referencedModule; + private LoadState state; public AssemblyReferenceTreeNode(MetadataModule module, AssemblyReference r, AssemblyTreeNode parentAssembly) { @@ -48,7 +57,27 @@ public AssemblyReferenceTreeNode(MetadataModule module, AssemblyReference r, Ass get { return Language.EscapeName(r.Name) + GetSuffixString(r.Handle); } } - public override object Icon => Images.Assembly; + public override object Icon { + get { + if (state == LoadState.Unloaded) + { + state = LoadState.Loading; + Dispatcher.CurrentDispatcher.BeginInvoke(() => { + var resolver = parentAssembly.LoadedAssembly.GetAssemblyResolver(MainWindow.Instance.CurrentDecompilerSettings.AutoLoadAssemblyReferences); + referencedModule = resolver.Resolve(r); + state = referencedModule is null + ? LoadState.Failed + : LoadState.Loadded; + RaisePropertyChanged(nameof(Icon)); + }, DispatcherPriority.Background); + } + return state switch { + LoadState.Loadded => Images.Assembly, + LoadState.Failed => Images.AssemblyWarning, + _ => Images.AssemblyLoading, + }; + } + } public override bool ShowExpander { get { @@ -60,7 +89,7 @@ public AssemblyReferenceTreeNode(MetadataModule module, AssemblyReference r, Ass // while the list of references is updated causes problems with WPF's ListView rendering. // Moving the assembly resolving out of the "add assembly reference"-loop by using the // dispatcher fixes the issue. - Dispatcher.CurrentDispatcher.BeginInvoke((Action)EnsureLazyChildren, DispatcherPriority.Normal); + Dispatcher.CurrentDispatcher.BeginInvoke(EnsureLazyChildren, DispatcherPriority.Normal); } return base.ShowExpander; } @@ -79,10 +108,7 @@ public override void ActivateItem(System.Windows.RoutedEventArgs e) protected override void LoadChildren() { this.Children.Add(new AssemblyReferenceReferencedTypesTreeNode(module, r)); - - var resolver = parentAssembly.LoadedAssembly.GetAssemblyResolver(MainWindow.Instance.CurrentDecompilerSettings.AutoLoadAssemblyReferences); - var referencedModule = resolver.Resolve(r); - if (referencedModule != null) + if (referencedModule is not null) { var module = (MetadataModule)referencedModule.GetTypeSystemWithCurrentOptionsOrNull().MainModule; foreach (var childRef in referencedModule.AssemblyReferences) @@ -106,7 +132,10 @@ public override void Decompile(Language language, ITextOutput output, Decompilat output.Indent(); language.WriteCommentLine(output, "Assembly reference loading information:"); if (info.HasErrors) + { language.WriteCommentLine(output, "There were some problems during assembly reference load, see below for more information!"); + state = LoadState.Failed; + } foreach (var item in info.Messages) { language.WriteCommentLine(output, $"{item.Item1}: {item.Item2}");