Browse Source

Merge pull request #3295 from tom-englert/dev/WpfRefactoring

Fix nullable issues in AssemblyTreeModel
pull/3297/head
Siegfried Pammer 1 year ago committed by GitHub
parent
commit
f5c27c396f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 20
      ILSpy/Analyzers/AnalyzerRootNode.cs
  2. 2
      ILSpy/Analyzers/AnalyzerTreeViewModel.cs
  3. 20
      ILSpy/AssemblyTree/AssemblyListPane.xaml.cs
  4. 178
      ILSpy/AssemblyTree/AssemblyTreeModel.cs
  5. 20
      ILSpy/ExportProviderAdapter.cs
  6. 20
      ILSpy/GlobalUsings.cs
  7. 20
      ILSpy/Options/DecompilerSettings.cs
  8. 20
      ILSpy/Options/OptionsDialogViewModel.cs
  9. 20
      ILSpy/Util/MenuService.cs
  10. 20
      ILSpy/Util/MessageBus.cs
  11. 20
      ILSpy/Util/ResourceHelper.cs
  12. 20
      ILSpy/Util/SettingsService.cs

20
ILSpy/Analyzers/AnalyzerRootNode.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using System.Collections.Generic;
// Copyright (c) 2024 Tom Englert 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
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;

2
ILSpy/Analyzers/AnalyzerTreeViewModel.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
// Copyright (c) 2019 AlphaSierraPapa for the SharpDevelop Team
// Copyright (c) 2024 Tom Englert 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

20
ILSpy/AssemblyTree/AssemblyListPane.xaml.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using System.ComponentModel.Composition;
// Copyright (c) 2024 Tom Englert 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
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.ComponentModel.Composition;
using System.Windows;
using System.Windows.Threading;

178
ILSpy/AssemblyTree/AssemblyTreeModel.cs

@ -54,6 +54,8 @@ using ICSharpCode.Decompiler; @@ -54,6 +54,8 @@ using ICSharpCode.Decompiler;
using TomsToolbox.Essentials;
using TomsToolbox.Wpf;
#nullable enable
namespace ICSharpCode.ILSpy.AssemblyTree
{
[ExportToolPane]
@ -63,10 +65,11 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -63,10 +65,11 @@ namespace ICSharpCode.ILSpy.AssemblyTree
{
public const string PaneContentId = "assemblyListPane";
AssemblyListPane activeView;
AssemblyListTreeNode assemblyListTreeNode;
private AssemblyListPane? activeView;
private AssemblyListTreeNode? assemblyListTreeNode;
private readonly DispatcherThrottle refreshThrottle;
readonly NavigationHistory<NavigationState> history = new();
private readonly NavigationHistory<NavigationState> history = new();
private bool isNavigatingHistory;
public AssemblyTreeModel()
@ -81,9 +84,11 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -81,9 +84,11 @@ namespace ICSharpCode.ILSpy.AssemblyTree
var selectionChangeThrottle = new DispatcherThrottle(DispatcherPriority.Input, TreeView_SelectionChanged);
SelectedItems.CollectionChanged += (_, _) => selectionChangeThrottle.Tick();
refreshThrottle = new DispatcherThrottle(DispatcherPriority.Background, RefreshInternal);
}
private void Settings_PropertyChanged(object sender, PropertyChangedEventArgs e)
private void Settings_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (sender is SessionSettings sessionSettings)
{
@ -95,10 +100,10 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -95,10 +100,10 @@ namespace ICSharpCode.ILSpy.AssemblyTree
case nameof(SessionSettings.Theme):
// update syntax highlighting and force reload (AvalonEdit does not automatically refresh on highlighting change)
DecompilerTextView.RegisterHighlighting();
DecompileSelectedNodes(DockWorkspace.Instance.ActiveTabPage.GetState() as DecompilerTextViewState);
RefreshDecompiledView();
break;
case nameof(SessionSettings.CurrentCulture):
MessageBox.Show(Properties.Resources.SettingsChangeRestartRequired, "ILSpy");
MessageBox.Show(Resources.SettingsChangeRestartRequired, "ILSpy");
break;
}
}
@ -107,7 +112,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -107,7 +112,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
switch (e.PropertyName)
{
case nameof(LanguageSettings.Language) or nameof(LanguageSettings.LanguageVersion):
DecompileSelectedNodes();
RefreshDecompiledView();
break;
default:
Refresh();
@ -116,27 +121,27 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -116,27 +121,27 @@ namespace ICSharpCode.ILSpy.AssemblyTree
}
}
public AssemblyList AssemblyList { get; private set; }
public AssemblyList? AssemblyList { get; private set; }
private SharpTreeNode root;
public SharpTreeNode Root {
private SharpTreeNode? root;
public SharpTreeNode? Root {
get => root;
set => SetProperty(ref root, value);
}
private SharpTreeNode selectedItem;
public SharpTreeNode SelectedItem {
private SharpTreeNode? selectedItem;
public SharpTreeNode? SelectedItem {
get => selectedItem;
set => SetProperty(ref selectedItem, value);
}
public ObservableCollection<SharpTreeNode> SelectedItems { get; } = [];
public string[] SelectedPath => GetPathForNode(SelectedItem);
public string[]? SelectedPath => GetPathForNode(SelectedItem);
readonly List<LoadedAssembly> commandLineLoadedAssemblies = [];
private readonly List<LoadedAssembly> commandLineLoadedAssemblies = [];
public bool HandleCommandLineArguments(CommandLineArguments args)
private bool HandleCommandLineArguments(CommandLineArguments args)
{
LoadAssemblies(args.AssembliesToLoad, commandLineLoadedAssemblies, focusNode: false);
if (args.Language != null)
@ -148,7 +153,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -148,7 +153,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
/// Called on startup or when passed arguments via WndProc from a second instance.
/// In the format case, spySettings is non-null; in the latter it is null.
/// </summary>
public void HandleCommandLineArgumentsAfterShowList(CommandLineArguments args, ISettingsProvider spySettings = null)
private void HandleCommandLineArgumentsAfterShowList(CommandLineArguments args, ISettingsProvider? spySettings = null)
{
var sessionSettings = SettingsService.Instance.SessionSettings;
@ -184,7 +189,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -184,7 +189,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
});
}
public async void NavigateOnLaunch(string navigateTo, string[] activeTreeViewPath, ISettingsProvider spySettings, List<LoadedAssembly> relevantAssemblies)
private async void NavigateOnLaunch(string? navigateTo, string[]? activeTreeViewPath, ISettingsProvider? spySettings, List<LoadedAssembly> relevantAssemblies)
{
var initialSelection = SelectedItem;
if (navigateTo != null)
@ -195,7 +200,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -195,7 +200,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
string namespaceName = navigateTo.Substring(2);
foreach (LoadedAssembly asm in relevantAssemblies)
{
AssemblyTreeNode asmNode = assemblyListTreeNode.FindAssemblyNode(asm);
var asmNode = assemblyListTreeNode?.FindAssemblyNode(asm);
if (asmNode != null)
{
// FindNamespaceNode() blocks the UI if the assembly is not yet loaded,
@ -222,11 +227,11 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -222,11 +227,11 @@ namespace ICSharpCode.ILSpy.AssemblyTree
}
else
{
IEntity mr = await Task.Run(() => FindEntityInRelevantAssemblies(navigateTo, relevantAssemblies));
IEntity? mr = await Task.Run(() => FindEntityInRelevantAssemblies(navigateTo, relevantAssemblies));
// Make sure we wait for assemblies being loaded...
// BeginInvoke in LoadedAssembly.LookupReferencedAssemblyInternal
await Dispatcher.InvokeAsync(delegate { }, DispatcherPriority.Normal);
if (mr != null && mr.ParentModule?.MetadataFile != null)
if (mr is { ParentModule.MetadataFile: not null })
{
found = true;
if (SelectedItem == initialSelection)
@ -246,7 +251,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -246,7 +251,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
{
// NavigateTo == null and an assembly was given on the command-line:
// Select the newly loaded assembly
AssemblyTreeNode asmNode = assemblyListTreeNode.FindAssemblyNode(relevantAssemblies[0]);
var asmNode = assemblyListTreeNode?.FindAssemblyNode(relevantAssemblies[0]);
if (asmNode != null && SelectedItem == initialSelection)
{
SelectNode(asmNode);
@ -254,8 +259,8 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -254,8 +259,8 @@ namespace ICSharpCode.ILSpy.AssemblyTree
}
else if (spySettings != null)
{
SharpTreeNode node = null;
if (activeTreeViewPath?.Length > 0)
SharpTreeNode? node = null;
if (activeTreeViewPath?.Length > 0 && AssemblyList != null)
{
foreach (var asm in AssemblyList.GetAssemblies())
{
@ -285,10 +290,10 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -285,10 +290,10 @@ namespace ICSharpCode.ILSpy.AssemblyTree
}
}
public static IEntity FindEntityInRelevantAssemblies(string navigateTo, IEnumerable<LoadedAssembly> relevantAssemblies)
public static IEntity? FindEntityInRelevantAssemblies(string navigateTo, IEnumerable<LoadedAssembly> relevantAssemblies)
{
ITypeReference typeRef;
IMemberReference memberRef = null;
IMemberReference? memberRef = null;
if (navigateTo.StartsWith("T:", StringComparison.Ordinal))
{
typeRef = IdStringProvider.ParseTypeName(navigateTo);
@ -301,7 +306,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -301,7 +306,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
foreach (LoadedAssembly asm in relevantAssemblies.ToList())
{
var module = asm.GetMetadataFileOrNull();
if (CanResolveTypeInPEFile(module, typeRef, out var typeHandle))
if (module != null && CanResolveTypeInPEFile(module, typeRef, out var typeHandle))
{
ICompilation compilation = typeHandle.Kind == HandleKind.ExportedType
? new DecompilerTypeSystem(module, module.GetAssemblyResolver())
@ -314,7 +319,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -314,7 +319,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
return null;
}
static bool CanResolveTypeInPEFile(MetadataFile module, ITypeReference typeRef, out EntityHandle typeHandle)
private static bool CanResolveTypeInPEFile(MetadataFile module, ITypeReference typeRef, out EntityHandle typeHandle)
{
// We intentionally ignore reference assemblies, so that the loop continues looking for another assembly that might have a usable definition.
if (module.IsReferenceAssembly())
@ -348,7 +353,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -348,7 +353,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
public void Initialize()
{
this.AssemblyList = SettingsService.Instance.LoadInitialAssemblyList();
AssemblyList = SettingsService.Instance.LoadInitialAssemblyList();
HandleCommandLineArguments(App.CommandLineArguments);
@ -357,22 +362,22 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -357,22 +362,22 @@ namespace ICSharpCode.ILSpy.AssemblyTree
&& AssemblyList.ListName == AssemblyListManager.DefaultListName
&& loadPreviousAssemblies)
{
LoadInitialAssemblies();
LoadInitialAssemblies(AssemblyList);
}
ShowAssemblyList(this.AssemblyList);
ShowAssemblyList(AssemblyList);
var sessionSettings = SettingsService.Instance.SessionSettings;
if (sessionSettings.ActiveAutoLoadedAssembly != null
&& File.Exists(sessionSettings.ActiveAutoLoadedAssembly))
{
this.AssemblyList.Open(sessionSettings.ActiveAutoLoadedAssembly, true);
AssemblyList.Open(sessionSettings.ActiveAutoLoadedAssembly, true);
}
Dispatcher.BeginInvoke(DispatcherPriority.Loaded, OpenAssemblies);
}
void OpenAssemblies()
private void OpenAssemblies()
{
HandleCommandLineArgumentsAfterShowList(App.CommandLineArguments, SettingsService.Instance.SpySettings);
@ -381,7 +386,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -381,7 +386,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
DockWorkspace.Instance.ShowText(output);
}
static bool FormatExceptions(App.ExceptionData[] exceptions, ITextOutput output)
private static bool FormatExceptions(App.ExceptionData[] exceptions, ITextOutput output)
{
var stringBuilder = new StringBuilder();
var result = exceptions.FormatExceptions(stringBuilder);
@ -392,18 +397,18 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -392,18 +397,18 @@ namespace ICSharpCode.ILSpy.AssemblyTree
return result;
}
public void ShowAssemblyList(string name)
private void ShowAssemblyList(string name)
{
AssemblyList list = SettingsService.Instance.AssemblyListManager.LoadList(name);
//Only load a new list when it is a different one
if (list.ListName != AssemblyList.ListName)
if (list.ListName != AssemblyList?.ListName)
{
ShowAssemblyList(list);
SelectNode(Root);
}
}
void ShowAssemblyList(AssemblyList assemblyList)
private void ShowAssemblyList(AssemblyList assemblyList)
{
history.Clear();
if (this.AssemblyList != null)
@ -440,7 +445,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -440,7 +445,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
#endif
}
void assemblyList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
private void assemblyList_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Reset)
{
@ -457,7 +462,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -457,7 +462,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
MessageBus.Send(this, new CurrentAssemblyListChangedEventArgs(e));
}
void LoadInitialAssemblies()
private static void LoadInitialAssemblies(AssemblyList assemblyList)
{
// Called when loading an empty assembly list; so that
// the user can see something initially.
@ -472,24 +477,24 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -472,24 +477,24 @@ namespace ICSharpCode.ILSpy.AssemblyTree
typeof(System.Windows.FrameworkElement).Assembly
};
foreach (System.Reflection.Assembly asm in initialAssemblies)
AssemblyList.OpenAssembly(asm.Location);
assemblyList.OpenAssembly(asm.Location);
}
public AssemblyTreeNode FindAssemblyNode(LoadedAssembly asm)
public AssemblyTreeNode? FindAssemblyNode(LoadedAssembly asm)
{
return assemblyListTreeNode.FindAssemblyNode(asm);
return assemblyListTreeNode?.FindAssemblyNode(asm);
}
#region Node Selection
public void SelectNode(SharpTreeNode node, bool inNewTabPage = false)
public void SelectNode(SharpTreeNode? node, bool inNewTabPage = false)
{
if (node == null)
return;
if (node.AncestorsAndSelf().Any(item => item.IsHidden))
{
MessageBox.Show(Properties.Resources.NavigationFailed, "ILSpy", MessageBoxButton.OK, MessageBoxImage.Exclamation);
MessageBox.Show(Resources.NavigationFailed, "ILSpy", MessageBoxButton.OK, MessageBoxImage.Exclamation);
return;
}
@ -510,7 +515,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -510,7 +515,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
}
}
internal void SelectNodes(IEnumerable<SharpTreeNode> nodes)
public void SelectNodes(IEnumerable<SharpTreeNode> nodes)
{
// Ensure nodes exist
var nodesList = nodes.Select(n => FindNodeByPath(GetPathForNode(n), true))
@ -532,7 +537,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -532,7 +537,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
SelectedItems.Clear();
foreach (var node in nodesList)
{
activeView.ScrollIntoView(node);
activeView?.ScrollIntoView(node);
SelectedItems.Add(node);
}
}
@ -543,7 +548,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -543,7 +548,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
SelectedItems.Clear();
foreach (var node in nodesList)
{
activeView.ScrollIntoView(node);
activeView?.ScrollIntoView(node);
SelectedItems.Add(node);
}
});
@ -553,12 +558,12 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -553,12 +558,12 @@ namespace ICSharpCode.ILSpy.AssemblyTree
/// <summary>
/// Retrieves a node using the .ToString() representations of its ancestors.
/// </summary>
public SharpTreeNode FindNodeByPath(string[] path, bool returnBestMatch)
public SharpTreeNode? FindNodeByPath(string[]? path, bool returnBestMatch)
{
if (path == null)
return null;
SharpTreeNode node = Root;
SharpTreeNode bestMatch = node;
var node = Root;
var bestMatch = node;
foreach (var element in path)
{
if (node == null)
@ -576,7 +581,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -576,7 +581,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
/// <summary>
/// Gets the .ToString() representation of the node's ancestors.
/// </summary>
public static string[] GetPathForNode(SharpTreeNode node)
public static string[]? GetPathForNode(SharpTreeNode? node)
{
if (node == null)
return null;
@ -590,8 +595,11 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -590,8 +595,11 @@ namespace ICSharpCode.ILSpy.AssemblyTree
return path.ToArray();
}
public ILSpyTreeNode FindTreeNode(object reference)
public ILSpyTreeNode? FindTreeNode(object? reference)
{
if (assemblyListTreeNode == null)
return null;
switch (reference)
{
case LoadedAssembly lasm:
@ -619,7 +627,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -619,7 +627,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
}
}
private void JumpToReference(object sender, NavigateToReferenceEventArgs e)
private void JumpToReference(object? sender, NavigateToReferenceEventArgs e)
{
JumpToReferenceAsync(e.Reference, e.InNewTabPage).HandleExceptions();
}
@ -631,7 +639,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -631,7 +639,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
/// Returns a task that will signal completion when the decompilation of the jump target has finished.
/// The task will be marked as canceled if the decompilation is canceled.
/// </returns>
private Task JumpToReferenceAsync(object reference, bool inNewTabPage = false)
private Task JumpToReferenceAsync(object? reference, bool inNewTabPage = false)
{
var decompilationTask = Task.CompletedTask;
@ -641,6 +649,8 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -641,6 +649,8 @@ namespace ICSharpCode.ILSpy.AssemblyTree
MainWindow.OpenLink(opCode.Link);
break;
case EntityReference unresolvedEntity:
if (AssemblyList is null)
break;
string protocol = unresolvedEntity.Protocol;
var file = unresolvedEntity.ResolveAssembly(AssemblyList);
if (file == null)
@ -669,7 +679,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -669,7 +679,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
}
break;
default:
ILSpyTreeNode treeNode = FindTreeNode(reference);
var treeNode = FindTreeNode(reference);
if (treeNode != null)
SelectNode(treeNode, inNewTabPage);
break;
@ -679,15 +689,19 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -679,15 +689,19 @@ namespace ICSharpCode.ILSpy.AssemblyTree
#endregion
public void LoadAssemblies(IEnumerable<string> fileNames, List<LoadedAssembly> loadedAssemblies = null, bool focusNode = true)
private void LoadAssemblies(IEnumerable<string> fileNames, List<LoadedAssembly>? loadedAssemblies = null, bool focusNode = true)
{
using (Keyboard.FocusedElement.PreserveFocus(!focusNode))
{
AssemblyTreeNode lastNode = null;
AssemblyTreeNode? lastNode = null;
var assemblyList = AssemblyList;
if (assemblyList is null)
return;
foreach (string file in fileNames)
{
var assembly = AssemblyList.OpenAssembly(file);
var assembly = assemblyList.OpenAssembly(file);
if (loadedAssemblies != null)
{
@ -695,7 +709,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -695,7 +709,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
}
else
{
var node = assemblyListTreeNode.FindAssemblyNode(assembly);
var node = assemblyListTreeNode?.FindAssemblyNode(assembly);
if (node != null && focusNode)
{
lastNode = node;
@ -713,7 +727,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -713,7 +727,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
#region Decompile (TreeView_SelectionChanged)
void TreeView_SelectionChanged()
private void TreeView_SelectionChanged()
{
if (SelectedItems.Count > 0)
{
@ -750,20 +764,20 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -750,20 +764,20 @@ namespace ICSharpCode.ILSpy.AssemblyTree
return;
void ContextMenuClosed(object sender, EventArgs e)
void ContextMenuClosed(object? sender, EventArgs e)
{
ContextMenuProvider.ContextMenuClosed -= ContextMenuClosed;
Dispatcher.BeginInvoke(DispatcherPriority.Background, () => {
if (Mouse.RightButton != MouseButtonState.Pressed)
{
DecompileSelectedNodes(DockWorkspace.Instance.ActiveTabPage.GetState() as DecompilerTextViewState);
RefreshDecompiledView();
}
});
}
}
private void DecompileSelectedNodes(DecompilerTextViewState newState = null)
private void DecompileSelectedNodes(DecompilerTextViewState? newState = null)
{
var activeTabPage = DockWorkspace.Instance.ActiveTabPage;
@ -787,7 +801,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -787,7 +801,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
public void RefreshDecompiledView()
{
DecompileSelectedNodes();
DecompileSelectedNodes(DockWorkspace.Instance.ActiveTabPage.GetState() as DecompilerTextViewState);
}
public Language CurrentLanguage => SettingsService.Instance.SessionSettings.LanguageSettings.Language;
@ -827,7 +841,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -827,7 +841,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
public bool CanNavigateForward => history.CanNavigateForward;
internal void NavigateTo(RequestNavigateEventArgs e, bool inNewTabPage = false)
public void NavigateTo(RequestNavigateEventArgs e, bool inNewTabPage = false)
{
if (e.Uri.Scheme == "resource")
{
@ -849,11 +863,12 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -849,11 +863,12 @@ namespace ICSharpCode.ILSpy.AssemblyTree
Title = e.Uri.AbsolutePath,
EnableHyperlinks = true
};
using (Stream s = typeof(App).Assembly.GetManifestResourceStream(typeof(App), e.Uri.AbsolutePath))
using (Stream? s = typeof(App).Assembly.GetManifestResourceStream(typeof(App), e.Uri.AbsolutePath))
{
using (StreamReader r = new StreamReader(s))
if (s != null)
{
string line;
using StreamReader r = new StreamReader(s);
string? line;
while ((line = r.ReadLine()) != null)
{
output.Write(line);
@ -882,16 +897,24 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -882,16 +897,24 @@ namespace ICSharpCode.ILSpy.AssemblyTree
}
public void Refresh()
{
refreshThrottle.Tick();
}
private void RefreshInternal()
{
using (Keyboard.FocusedElement.PreserveFocus())
{
var path = GetPathForNode(SelectedItem);
ShowAssemblyList(SettingsService.Instance.AssemblyListManager.LoadList(AssemblyList.ListName));
SelectNode(FindNodeByPath(path, true), inNewTabPage: false);
if (DockWorkspace.Instance.ActiveTabPage?.GetState()?.DecompiledNodes?.Any() == true)
if (AssemblyList != null)
{
DecompileSelectedNodes();
ShowAssemblyList(SettingsService.Instance.AssemblyListManager.LoadList(AssemblyList.ListName));
}
SelectNode(FindNodeByPath(path, true), inNewTabPage: false);
RefreshDecompiledView();
}
}
@ -900,7 +923,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -900,7 +923,7 @@ namespace ICSharpCode.ILSpy.AssemblyTree
SelectedItems.Clear();
}
public IEnumerable<SharpTreeNode> GetTopLevelSelection()
private IEnumerable<SharpTreeNode> GetTopLevelSelection()
{
var selection = this.SelectedItems;
var selectionHash = new HashSet<SharpTreeNode>(selection);
@ -917,14 +940,14 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -917,14 +940,14 @@ namespace ICSharpCode.ILSpy.AssemblyTree
{
using (activeView?.LockUpdates())
{
AssemblyList.Sort(AssemblyComparer.Instance);
AssemblyList?.Sort(AssemblyComparer.Instance);
}
}
private class AssemblyComparer : IComparer<LoadedAssembly>
{
public static readonly AssemblyComparer Instance = new();
int IComparer<LoadedAssembly>.Compare(LoadedAssembly x, LoadedAssembly y)
int IComparer<LoadedAssembly>.Compare(LoadedAssembly? x, LoadedAssembly? y)
{
return string.Compare(x?.ShortName, y?.ShortName, StringComparison.CurrentCulture);
}
@ -932,14 +955,17 @@ namespace ICSharpCode.ILSpy.AssemblyTree @@ -932,14 +955,17 @@ namespace ICSharpCode.ILSpy.AssemblyTree
public void CollapseAll()
{
using (activeView.LockUpdates())
using (activeView?.LockUpdates())
{
CollapseChildren(Root);
}
}
static void CollapseChildren(SharpTreeNode node)
private static void CollapseChildren(SharpTreeNode? node)
{
if (node is null)
return;
foreach (var child in node.Children)
{
if (!child.IsExpanded)

20
ILSpy/ExportProviderAdapter.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using System;
// Copyright (c) 2024 Tom Englert 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
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// 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.CodeAnalysis;
using System.Linq;

20
ILSpy/GlobalUsings.cs

@ -1 +1,19 @@ @@ -1 +1,19 @@
global using ICSharpCode.ILSpy.Util;
// Copyright (c) 2024 Tom Englert 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
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
global using ICSharpCode.ILSpy.Util;

20
ILSpy/Options/DecompilerSettings.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using System.ComponentModel;
// Copyright (c) 2024 Tom Englert 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
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.ComponentModel;
using ICSharpCode.ILSpyX.Settings;
using System.Linq;

20
ILSpy/Options/OptionsDialogViewModel.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using System.Linq;
// Copyright (c) 2024 Tom Englert 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
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Linq;
using System.Windows;
using System.Windows.Input;

20
ILSpy/Util/MenuService.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using System.Collections.Generic;
// Copyright (c) 2024 Tom Englert 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
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows;

20
ILSpy/Util/MessageBus.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using System;
// Copyright (c) 2024 Tom Englert 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
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// 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.Specialized;
using System.ComponentModel;

20
ILSpy/Util/ResourceHelper.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
namespace ICSharpCode.ILSpy.Util
// Copyright (c) 2024 Tom Englert 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
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
namespace ICSharpCode.ILSpy.Util
{
internal static class ResourceHelper
{

20
ILSpy/Util/SettingsService.cs

@ -1,4 +1,22 @@ @@ -1,4 +1,22 @@
using System;
// Copyright (c) 2024 Tom Englert 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
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// 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.Concurrent;
using System.ComponentModel;
using System.Xml.Linq;

Loading…
Cancel
Save