Browse Source

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

WPF Refactoring
pull/3283/head
Siegfried Pammer 8 months ago committed by GitHub
parent
commit
d8cfb8ea0c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 9
      ICSharpCode.ILSpyX/AssemblyList.cs
  2. 9
      ICSharpCode.ILSpyX/AssemblyListManager.cs
  3. 2
      ICSharpCode.ILSpyX/Extensions/CollectionExtensions.cs
  4. 1
      ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj
  5. 8
      ICSharpCode.ILSpyX/LoadedPackage.cs
  6. 6
      ICSharpCode.ILSpyX/PdbProvider/PortableDebugInfoProvider.cs
  7. 72
      ICSharpCode.ILSpyX/Settings/ILSpySettings.cs
  8. 42
      ICSharpCode.ILSpyX/Settings/IMiscSettings.cs
  9. 2
      ICSharpCode.ILSpyX/Settings/ISettingsFilePathProvider.cs
  10. 39
      ICSharpCode.ILSpyX/Settings/ISettingsProvider.cs
  11. 32
      ICSharpCode.ILSpyX/Settings/ISettingsSection.cs
  12. 6
      ICSharpCode.ILSpyX/TreeView/SharpTreeNode.cs
  13. 2
      ICSharpCode.ILSpyX/TreeView/TreeFlattener.cs
  14. 15
      ILSpy.ReadyToRun/ReadyToRunDisassembler.cs
  15. 16
      ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml
  16. 103
      ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs
  17. 121
      ILSpy.ReadyToRun/ReadyToRunOptions.cs
  18. 4
      ILSpy/AboutPage.cs
  19. 4
      ILSpy/Analyzers/AnalyzeCommand.cs
  20. 3
      ILSpy/Analyzers/AnalyzerEntityTreeNode.cs
  21. 1
      ILSpy/Analyzers/AnalyzerRootNode.cs
  22. 2
      ILSpy/Analyzers/AnalyzerSearchTreeNode.cs
  23. 1
      ILSpy/Analyzers/AnalyzerTreeNode.cs
  24. 2
      ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs
  25. 17
      ILSpy/App.xaml
  26. 62
      ILSpy/App.xaml.cs
  27. 54
      ILSpy/AssemblyTree/AssemblyListPane.xaml
  28. 44
      ILSpy/AssemblyTree/AssemblyListPane.xaml.cs
  29. 932
      ILSpy/AssemblyTree/AssemblyTreeModel.cs
  30. 24
      ILSpy/Commands/BrowseBackCommand.cs
  31. 25
      ILSpy/Commands/BrowseForwardCommand.cs
  32. 3
      ILSpy/Commands/CheckForUpdatesCommand.cs
  33. 21
      ILSpy/Commands/CommandWrapper.cs
  34. 15
      ILSpy/Commands/DecompileAllCommand.cs
  35. 2
      ILSpy/Commands/DecompileCommand.cs
  36. 18
      ILSpy/Commands/DecompileInNewViewCommand.cs
  37. 17
      ILSpy/Commands/DisassembleAllCommand.cs
  38. 12
      ILSpy/Commands/GeneratePdbContextMenuEntry.cs
  39. 24
      ILSpy/Commands/OpenCommand.cs
  40. 19
      ILSpy/Commands/OpenFromGacCommand.cs
  41. 4
      ILSpy/Commands/Pdb2XmlCommand.cs
  42. 12
      ILSpy/Commands/RefreshCommand.cs
  43. 10
      ILSpy/Commands/RemoveAssembliesWithLoadErrors.cs
  44. 12
      ILSpy/Commands/SaveCodeContextMenuEntry.cs
  45. 20
      ILSpy/Commands/SaveCommand.cs
  46. 6
      ILSpy/Commands/SelectPdbContextMenuEntry.cs
  47. 5
      ILSpy/Commands/SetThemeCommand.cs
  48. 1
      ILSpy/Commands/ShowCFGContextMenuEntry.cs
  49. 23
      ILSpy/Commands/SortAssemblyListCommand.cs
  50. 105
      ILSpy/ContextMenuEntry.cs
  51. 7
      ILSpy/Controls/TreeView/SharpTreeView.cs
  52. 4
      ILSpy/DecompilationOptions.cs
  53. 1
      ILSpy/Docking/DockLayoutSettings.cs
  54. 94
      ILSpy/Docking/DockWorkspace.cs
  55. 59
      ILSpy/Docking/PaneCollection.cs
  56. 30
      ILSpy/ExtensionMethods.cs
  57. 1
      ILSpy/GlobalUsings.cs
  58. 3
      ILSpy/ILSpy.csproj
  59. 27
      ILSpy/LanguageSettings.cs
  60. 1
      ILSpy/Languages/CSharpILMixedLanguage.cs
  61. 7
      ILSpy/Languages/CSharpLanguage.cs
  62. 7
      ILSpy/Languages/ILLanguage.cs
  63. 9
      ILSpy/Languages/Languages.cs
  64. 199
      ILSpy/MainWindow.xaml
  65. 1446
      ILSpy/MainWindow.xaml.cs
  66. 10
      ILSpy/MainWindowViewModel.cs
  67. 2
      ILSpy/Metadata/CoffHeaderTreeNode.cs
  68. 2
      ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs
  69. 2
      ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs
  70. 4
      ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs
  71. 2
      ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs
  72. 4
      ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs
  73. 2
      ILSpy/Metadata/CorTables/EventTableTreeNode.cs
  74. 2
      ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs
  75. 2
      ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs
  76. 2
      ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs
  77. 2
      ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs
  78. 4
      ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs
  79. 2
      ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs
  80. 4
      ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs
  81. 4
      ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs
  82. 2
      ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs
  83. 2
      ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs
  84. 6
      ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs
  85. 4
      ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs
  86. 2
      ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs
  87. 2
      ILSpy/Metadata/CorTables/MethodTableTreeNode.cs
  88. 4
      ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs
  89. 4
      ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs
  90. 2
      ILSpy/Metadata/CorTables/PtrTableTreeNode.cs
  91. 6
      ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs
  92. 2
      ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs
  93. 1
      ILSpy/Metadata/DebugMetadataTablesTreeNode.cs
  94. 2
      ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs
  95. 2
      ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs
  96. 8
      ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs
  97. 4
      ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs
  98. 4
      ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs
  99. 24
      ILSpy/Metadata/GoToTokenCommand.cs
  100. 2
      ILSpy/Metadata/MetadataProtocolHandler.cs
  101. Some files were not shown because too many files have changed in this diff Show More

9
ICSharpCode.ILSpyX/AssemblyList.cs

@ -186,7 +186,7 @@ namespace ICSharpCode.ILSpyX @@ -186,7 +186,7 @@ namespace ICSharpCode.ILSpyX
get { return listName; }
}
internal void Move(LoadedAssembly[] assembliesToMove, int index)
public void Move(LoadedAssembly[] assembliesToMove, int index)
{
VerifyAccess();
lock (lockObj)
@ -230,7 +230,7 @@ namespace ICSharpCode.ILSpyX @@ -230,7 +230,7 @@ namespace ICSharpCode.ILSpyX
}
}
internal void RefreshSave()
public void RefreshSave()
{
// Whenever the assembly list is modified, mark it as dirty
// and enqueue a task that saves it once the UI has finished modifying the assembly list.
@ -281,8 +281,9 @@ namespace ICSharpCode.ILSpyX @@ -281,8 +281,9 @@ namespace ICSharpCode.ILSpyX
{
file = Path.GetFullPath(file);
return OpenAssembly(file, () => {
var newAsm = new LoadedAssembly(this, file, fileLoaders: manager?.LoaderRegistry, applyWinRTProjections: ApplyWinRTProjections, useDebugSymbols: UseDebugSymbols);
newAsm.IsAutoLoaded = isAutoLoaded;
var newAsm = new LoadedAssembly(this, file, fileLoaders: manager?.LoaderRegistry, applyWinRTProjections: ApplyWinRTProjections, useDebugSymbols: UseDebugSymbols) {
IsAutoLoaded = isAutoLoaded
};
return newAsm;
});
}

9
ICSharpCode.ILSpyX/AssemblyListManager.cs

@ -39,7 +39,7 @@ namespace ICSharpCode.ILSpyX @@ -39,7 +39,7 @@ namespace ICSharpCode.ILSpyX
public const string DotNet35List = ".NET 3.5";
public const string ASPDotNetMVC3List = "ASP.NET (MVC3)";
private ISettingsProvider settingsProvider;
private readonly ISettingsProvider settingsProvider;
public AssemblyListManager(ISettingsProvider settingsProvider)
{
@ -59,9 +59,9 @@ namespace ICSharpCode.ILSpyX @@ -59,9 +59,9 @@ namespace ICSharpCode.ILSpyX
public bool UseDebugSymbols { get; set; }
public ObservableCollection<string> AssemblyLists { get; } = new ObservableCollection<string>();
public ObservableCollection<string> AssemblyLists { get; } = [];
public FileLoaderRegistry LoaderRegistry { get; } = new FileLoaderRegistry();
public FileLoaderRegistry LoaderRegistry { get; } = new();
/// <summary>
/// Loads an assembly list from the ILSpySettings.
@ -69,14 +69,13 @@ namespace ICSharpCode.ILSpyX @@ -69,14 +69,13 @@ namespace ICSharpCode.ILSpyX
/// </summary>
public AssemblyList LoadList(string listName)
{
this.settingsProvider = this.settingsProvider.Load();
AssemblyList list = DoLoadList(listName);
if (!AssemblyLists.Contains(list.ListName))
AssemblyLists.Add(list.ListName);
return list;
}
AssemblyList DoLoadList(string listName)
AssemblyList DoLoadList(string? listName)
{
XElement doc = this.settingsProvider["AssemblyLists"];
if (listName != null)

2
ICSharpCode.ILSpyX/Extensions/CollectionExtensions.cs

@ -27,7 +27,7 @@ namespace ICSharpCode.ILSpyX.Extensions @@ -27,7 +27,7 @@ namespace ICSharpCode.ILSpyX.Extensions
{
public static class CollectionExtensions
{
public static void AddRange<T>(this ICollection<T> list, IEnumerable<T> items)
internal static void AddRange<T>(this ICollection<T> list, IEnumerable<T> items)
{
foreach (T item in items)
if (!list.Contains(item))

1
ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj

@ -41,7 +41,6 @@ @@ -41,7 +41,6 @@
</PropertyGroup>
<ItemGroup>
<InternalsVisibleTo Include="ILSpy" Key="00240000048000009400000006020000002400005253413100040000010001004dcf3979c4e902efa4dd2163a039701ed5822e6f1134d77737296abbb97bf0803083cfb2117b4f5446a217782f5c7c634f9fe1fc60b4c11d62c5b3d33545036706296d31903ddcf750875db38a8ac379512f51620bb948c94d0831125fbc5fe63707cbb93f48c1459c4d1749eb7ac5e681a2f0d6d7c60fa527a3c0b8f92b02bf" />
<InternalsVisibleTo Include="ILSpy.Tests" Key="00240000048000009400000006020000002400005253413100040000010001004dcf3979c4e902efa4dd2163a039701ed5822e6f1134d77737296abbb97bf0803083cfb2117b4f5446a217782f5c7c634f9fe1fc60b4c11d62c5b3d33545036706296d31903ddcf750875db38a8ac379512f51620bb948c94d0831125fbc5fe63707cbb93f48c1459c4d1749eb7ac5e681a2f0d6d7c60fa527a3c0b8f92b02bf" />
</ItemGroup>

8
ICSharpCode.ILSpyX/LoadedPackage.cs

@ -51,14 +51,14 @@ namespace ICSharpCode.ILSpyX @@ -51,14 +51,14 @@ namespace ICSharpCode.ILSpyX
public PackageKind Kind { get; }
internal SingleFileBundle.Header BundleHeader { get; set; }
public SingleFileBundle.Header BundleHeader { get; set; }
/// <summary>
/// List of all entries, including those in sub-directories within the package.
/// </summary>
public IReadOnlyList<PackageEntry> Entries { get; }
internal PackageFolder RootFolder { get; }
public PackageFolder RootFolder { get; }
public LoadedPackage(PackageKind kind, IEnumerable<PackageEntry> entries)
{
@ -256,7 +256,7 @@ namespace ICSharpCode.ILSpyX @@ -256,7 +256,7 @@ namespace ICSharpCode.ILSpyX
public abstract string FullName { get; }
}
sealed class PackageFolder : IAssemblyResolver
public sealed class PackageFolder : IAssemblyResolver
{
/// <summary>
/// Gets the short name of the folder.
@ -326,7 +326,7 @@ namespace ICSharpCode.ILSpyX @@ -326,7 +326,7 @@ namespace ICSharpCode.ILSpyX
readonly Dictionary<string, LoadedAssembly?> assemblies = new Dictionary<string, LoadedAssembly?>(StringComparer.OrdinalIgnoreCase);
internal LoadedAssembly? ResolveFileName(string name)
public LoadedAssembly? ResolveFileName(string name)
{
if (package.LoadedAssembly == null)
return null;

6
ICSharpCode.ILSpyX/PdbProvider/PortableDebugInfoProvider.cs

@ -32,7 +32,7 @@ using static ICSharpCode.Decompiler.Metadata.MetadataFile; @@ -32,7 +32,7 @@ using static ICSharpCode.Decompiler.Metadata.MetadataFile;
namespace ICSharpCode.ILSpyX.PdbProvider
{
class PortableDebugInfoProvider : IDebugInfoProvider
public class PortableDebugInfoProvider : IDebugInfoProvider
{
string? pdbFileName;
string moduleFileName;
@ -40,7 +40,7 @@ namespace ICSharpCode.ILSpyX.PdbProvider @@ -40,7 +40,7 @@ namespace ICSharpCode.ILSpyX.PdbProvider
MetadataReaderOptions options;
bool hasError;
internal bool IsEmbedded => pdbFileName == null;
public bool IsEmbedded => pdbFileName == null;
public PortableDebugInfoProvider(string moduleFileName, MetadataReaderProvider provider,
MetadataReaderOptions options = MetadataReaderOptions.Default,
@ -69,7 +69,7 @@ namespace ICSharpCode.ILSpyX.PdbProvider @@ -69,7 +69,7 @@ namespace ICSharpCode.ILSpyX.PdbProvider
}
}
internal MetadataReader? GetMetadataReader()
public MetadataReader? GetMetadataReader()
{
try
{

72
ICSharpCode.ILSpyX/Settings/ILSpySettings.cs

@ -34,16 +34,11 @@ namespace ICSharpCode.ILSpyX.Settings @@ -34,16 +34,11 @@ namespace ICSharpCode.ILSpyX.Settings
/// </summary>
public static ISettingsFilePathProvider? SettingsFilePathProvider { get; set; }
readonly XElement root;
XElement root;
ILSpySettings()
ILSpySettings(XElement? root = null)
{
this.root = new XElement("ILSpy");
}
ILSpySettings(XElement root)
{
this.root = root;
this.root = root ?? new XElement("ILSpy");
}
public XElement this[XName section] {
@ -64,13 +59,7 @@ namespace ICSharpCode.ILSpyX.Settings @@ -64,13 +59,7 @@ namespace ICSharpCode.ILSpyX.Settings
{
try
{
XDocument doc = LoadWithoutCheckingCharacters(GetConfigFile());
if (null == doc.Root)
{
return new ILSpySettings();
}
return new ILSpySettings(doc.Root);
return new ILSpySettings(LoadFile(GetConfigFile()).Root);
}
catch (IOException)
{
@ -83,7 +72,7 @@ namespace ICSharpCode.ILSpyX.Settings @@ -83,7 +72,7 @@ namespace ICSharpCode.ILSpyX.Settings
}
}
static XDocument LoadWithoutCheckingCharacters(string fileName)
static XDocument LoadFile(string fileName)
{
return XDocument.Load(fileName, LoadOptions.None);
}
@ -91,16 +80,15 @@ namespace ICSharpCode.ILSpyX.Settings @@ -91,16 +80,15 @@ namespace ICSharpCode.ILSpyX.Settings
/// <summary>
/// Saves a setting section.
/// </summary>
public static void SaveSettings(XElement section)
public void SaveSettings(XElement section)
{
Update(
delegate (XElement root) {
XElement? existingElement = root.Element(section.Name);
if (existingElement != null)
existingElement.ReplaceWith(section);
else
root.Add(section);
});
Update(rootElement => {
XElement? existingElement = rootElement.Element(section.Name);
if (existingElement != null)
existingElement.ReplaceWith(section);
else
rootElement.Add(section);
});
}
/// <summary>
@ -108,7 +96,7 @@ namespace ICSharpCode.ILSpyX.Settings @@ -108,7 +96,7 @@ namespace ICSharpCode.ILSpyX.Settings
/// We always reload the file on updates to ensure we aren't overwriting unrelated changes performed
/// by another ILSpy instance.
/// </summary>
public static void Update(Action<XElement> action)
public void Update(Action<XElement> action)
{
using (new MutexProtector(ConfigFileMutex))
{
@ -116,7 +104,7 @@ namespace ICSharpCode.ILSpyX.Settings @@ -116,7 +104,7 @@ namespace ICSharpCode.ILSpyX.Settings
XDocument doc;
try
{
doc = LoadWithoutCheckingCharacters(config);
doc = LoadFile(config);
}
catch (IOException)
{
@ -131,14 +119,10 @@ namespace ICSharpCode.ILSpyX.Settings @@ -131,14 +119,10 @@ namespace ICSharpCode.ILSpyX.Settings
doc.Root!.SetAttributeValue("version", DecompilerVersionInfo.Major + "." + DecompilerVersionInfo.Minor + "." + DecompilerVersionInfo.Build + "." + DecompilerVersionInfo.Revision);
action(doc.Root);
doc.Save(config, SaveOptions.None);
this.root = doc.Root;
}
}
void ISettingsProvider.Update(Action<XElement> action)
{
Update(action);
}
static string GetConfigFile()
{
if (null != SettingsFilePathProvider)
@ -148,11 +132,6 @@ namespace ICSharpCode.ILSpyX.Settings @@ -148,11 +132,6 @@ namespace ICSharpCode.ILSpyX.Settings
// return "ILSpy.xml";
}
ISettingsProvider ISettingsProvider.Load()
{
return Load();
}
const string ConfigFileMutex = "01A91708-49D1-410D-B8EB-4DE2662B3971";
/// <summary>
@ -164,17 +143,16 @@ namespace ICSharpCode.ILSpyX.Settings @@ -164,17 +143,16 @@ namespace ICSharpCode.ILSpyX.Settings
public MutexProtector(string name)
{
bool createdNew;
this.mutex = new Mutex(true, name, out createdNew);
if (!createdNew)
this.mutex = new Mutex(true, name, out bool createdNew);
if (createdNew)
return;
try
{
mutex.WaitOne();
}
catch (AbandonedMutexException)
{
try
{
mutex.WaitOne();
}
catch (AbandonedMutexException)
{
}
}
}

42
ICSharpCode.ILSpyX/Settings/IMiscSettings.cs

@ -1,42 +0,0 @@ @@ -1,42 +0,0 @@
// Copyright (c) 2022 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
// 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.Xml.Linq;
namespace ICSharpCode.ILSpyX.Settings
{
public interface IMiscSettings
{
public bool AllowMultipleInstances { get; set; }
public bool LoadPreviousAssemblies { get; set; }
public static void Save(XElement root, IMiscSettings miscSettings)
{
var section = new XElement("MiscSettings");
section.SetAttributeValue(nameof(miscSettings.AllowMultipleInstances), miscSettings.AllowMultipleInstances);
section.SetAttributeValue(nameof(miscSettings.LoadPreviousAssemblies), miscSettings.LoadPreviousAssemblies);
XElement? existingElement = root.Element("MiscSettings");
if (existingElement != null)
existingElement.ReplaceWith(section);
else
root.Add(section);
}
}
}

2
ICSharpCode.ILSpyX/Settings/ISettingsFilePathProvider.cs

@ -16,8 +16,6 @@ @@ -16,8 +16,6 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
namespace ICSharpCode.ILSpyX.Settings
{
public interface ISettingsFilePathProvider

39
ICSharpCode.ILSpyX/Settings/ISettingsProvider.cs

@ -17,13 +17,8 @@ @@ -17,13 +17,8 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
using static System.Collections.Specialized.BitVector32;
namespace ICSharpCode.ILSpyX.Settings
{
public interface ISettingsProvider
@ -31,39 +26,7 @@ namespace ICSharpCode.ILSpyX.Settings @@ -31,39 +26,7 @@ namespace ICSharpCode.ILSpyX.Settings
XElement this[XName section] { get; }
void Update(Action<XElement> action);
ISettingsProvider Load();
public static ICSharpCode.Decompiler.DecompilerSettings LoadDecompilerSettings(ISettingsProvider settingsProvider)
{
XElement e = settingsProvider["DecompilerSettings"];
var newSettings = new Decompiler.DecompilerSettings();
var properties = typeof(Decompiler.DecompilerSettings).GetProperties()
.Where(p => p.GetCustomAttribute<BrowsableAttribute>()?.Browsable != false);
foreach (var p in properties)
{
var value = (bool?)e.Attribute(p.Name);
if (value.HasValue)
p.SetValue(newSettings, value.Value);
}
return newSettings;
}
public static void SaveDecompilerSettings(XElement root, ICSharpCode.Decompiler.DecompilerSettings newSettings)
{
var properties = typeof(Decompiler.DecompilerSettings).GetProperties()
.Where(p => p.GetCustomAttribute<BrowsableAttribute>()?.Browsable != false);
XElement section = new XElement("DecompilerSettings");
foreach (var p in properties)
{
section.SetAttributeValue(p.Name, p.GetValue(newSettings));
}
XElement? existingElement = root.Element("DecompilerSettings");
if (existingElement != null)
existingElement.ReplaceWith(section);
else
root.Add(section);
}
void SaveSettings(XElement section);
}
}

32
ICSharpCode.ILSpyX/Settings/ISettingsSection.cs

@ -1,32 +0,0 @@ @@ -1,32 +0,0 @@
// Copyright (c) 2022 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
// 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;
namespace ICSharpCode.ILSpyX.Settings
{
public interface ISettingsSection<TSelf>
{
// This should be abstract, but that needs C# 11.0 (see IParseable<TSelf>)
// Keep it to be enabled in the future
public static TSelf Load(ISettingsProvider settingsProvider)
{
throw new NotImplementedException();
}
}
}

6
ICSharpCode.ILSpyX/TreeView/SharpTreeNode.cs

@ -182,7 +182,7 @@ namespace ICSharpCode.ILSpyX.TreeView @@ -182,7 +182,7 @@ namespace ICSharpCode.ILSpyX.TreeView
#endregion
#region OnChildrenChanged
protected internal virtual void OnChildrenChanged(NotifyCollectionChangedEventArgs e)
public virtual void OnChildrenChanged(NotifyCollectionChangedEventArgs e)
{
if (e.OldItems != null)
{
@ -359,7 +359,7 @@ namespace ICSharpCode.ILSpyX.TreeView @@ -359,7 +359,7 @@ namespace ICSharpCode.ILSpyX.TreeView
return TreeTraversal.PreOrder(this.Children.Where(c => c.isVisible), n => n.Children.Where(c => c.isVisible));
}
internal IEnumerable<SharpTreeNode> VisibleDescendantsAndSelf()
public IEnumerable<SharpTreeNode> VisibleDescendantsAndSelf()
{
return TreeTraversal.PreOrder(this, n => n.Children.Where(c => c.isVisible));
}
@ -637,7 +637,7 @@ namespace ICSharpCode.ILSpyX.TreeView @@ -637,7 +637,7 @@ namespace ICSharpCode.ILSpyX.TreeView
return false;
}
internal void InternalDrop(IPlatformDragEventArgs e, int index)
public void InternalDrop(IPlatformDragEventArgs e, int index)
{
if (LazyLoading)
{

2
ICSharpCode.ILSpyX/TreeView/TreeFlattener.cs

@ -26,7 +26,7 @@ using System.Diagnostics; @@ -26,7 +26,7 @@ using System.Diagnostics;
namespace ICSharpCode.ILSpyX.TreeView
{
sealed class TreeFlattener : IList, INotifyCollectionChanged
public sealed class TreeFlattener : IList, INotifyCollectionChanged
{
/// <summary>
/// The root node of the flat list tree.

15
ILSpy.ReadyToRun/ReadyToRunDisassembler.cs

@ -26,6 +26,7 @@ using Iced.Intel; @@ -26,6 +26,7 @@ using Iced.Intel;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.Util;
using ILCompiler.Reflection.ReadyToRun;
using ILCompiler.Reflection.ReadyToRun.Amd64;
@ -50,11 +51,13 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -50,11 +51,13 @@ namespace ICSharpCode.ILSpy.ReadyToRun
ReadyToRunMethod readyToRunMethod = runtimeFunction.Method;
WriteCommentLine(readyToRunMethod.SignatureString);
if (ReadyToRunOptions.GetIsShowGCInfo(null))
var options = SettingsService.Instance.GetSettings<ReadyToRunOptions>();
if (options.IsShowGCInfo)
{
if (readyToRunMethod.GcInfo != null)
{
string[] lines = readyToRunMethod.GcInfo.ToString().Split(Environment.NewLine);
string[] lines = readyToRunMethod.GcInfo.ToString()?.Split(Environment.NewLine) ?? [];
WriteCommentLine("GC info:");
foreach (string line in lines)
{
@ -68,12 +71,12 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -68,12 +71,12 @@ namespace ICSharpCode.ILSpy.ReadyToRun
}
Dictionary<ulong, UnwindCode> unwindInfo = null;
if (ReadyToRunOptions.GetIsShowUnwindInfo(null) && bitness == 64)
if (options.IsShowUnwindInfo && bitness == 64)
{
unwindInfo = WriteUnwindInfo();
}
bool isShowDebugInfo = ReadyToRunOptions.GetIsShowDebugInfo(null);
bool isShowDebugInfo = options.IsShowDebugInfo;
DebugInfoHelper debugInfo = null;
if (isShowDebugInfo)
{
@ -97,7 +100,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -97,7 +100,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun
decoder.Decode(out instructions.AllocUninitializedElement());
}
string disassemblyFormat = ReadyToRunOptions.GetDisassemblyFormat(null);
string disassemblyFormat = options.DisassemblyFormat;
Formatter formatter = null;
if (disassemblyFormat.Equals(ReadyToRunOptions.intel))
{
@ -144,7 +147,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun @@ -144,7 +147,7 @@ namespace ICSharpCode.ILSpy.ReadyToRun
}
}
}
if (ReadyToRunOptions.GetIsShowGCInfo(null))
if (options.IsShowGCInfo)
{
DecorateGCInfo(instr, baseInstrIP, readyToRunMethod.GcInfo);
}

16
ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml

@ -1,7 +1,11 @@ @@ -1,7 +1,11 @@
<UserControl x:Class="ICSharpCode.ILSpy.ReadyToRun.ReadyToRunOptionPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:properties="clr-namespace:ILSpy.ReadyToRun.Properties"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" d:DesignHeight="500" d:DesignWidth="500" mc:Ignorable="d"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:readyToRun="clr-namespace:ICSharpCode.ILSpy.ReadyToRun"
d:DataContext="{d:DesignInstance readyToRun:ReadyToRunOptionsViewModel}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
@ -14,12 +18,12 @@ @@ -14,12 +18,12 @@
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Margin="3" Text="{x:Static properties:Resources.DisassemblyFormat}" />
<ComboBox Grid.Column="1" Margin="3" ItemsSource="{Binding DisassemblyFormats}" SelectedItem="{Binding DisassemblyFormat}" />
<TextBlock Grid.Row="1" Margin="3" Text="{x:Static properties:Resources.ShowStackUnwindInfo}"/>
<CheckBox Grid.Row="1" Grid.Column="1" Margin="3" IsChecked="{Binding IsShowUnwindInfo}" />
<ComboBox Grid.Row="0" Grid.Column="1" Margin="3" ItemsSource="{Binding Options.DisassemblyFormats}" SelectedItem="{Binding Options.DisassemblyFormat}" />
<TextBlock Grid.Row="1" Grid.Column="0" Margin="3" Text="{x:Static properties:Resources.ShowStackUnwindInfo}"/>
<CheckBox Grid.Row="1" Grid.Column="1" Margin="3" IsChecked="{Binding Options.IsShowUnwindInfo}" />
<TextBlock Grid.Row="2" Margin="3" Text="{x:Static properties:Resources.ShowDebugInfo}"/>
<CheckBox Grid.Row="2" Grid.Column="1" Margin="3" IsChecked="{Binding IsShowDebugInfo}" />
<CheckBox Grid.Row="2" Grid.Column="1" Margin="3" IsChecked="{Binding Options.IsShowDebugInfo}" />
<TextBlock Grid.Row="3" Margin="3" Text="{x:Static properties:Resources.ShowGCInfo}"/>
<CheckBox Grid.Row="3" Grid.Column="1" Margin="3" IsChecked="{Binding IsShowGCInfo}" />
<CheckBox Grid.Row="3" Grid.Column="1" Margin="3" IsChecked="{Binding Options.IsShowGCInfo}" />
</Grid>
</UserControl>

103
ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs

@ -16,112 +16,47 @@ @@ -16,112 +16,47 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System.ComponentModel;
using System.ComponentModel.Composition;
using System.Windows.Controls;
using System.Xml.Linq;
using ICSharpCode.ILSpy.Options;
using ICSharpCode.ILSpyX.Settings;
using ICSharpCode.ILSpy.Util;
using TomsToolbox.Wpf;
using TomsToolbox.Wpf.Composition.Mef;
namespace ICSharpCode.ILSpy.ReadyToRun
{
[ExportOptionPage(Title = nameof(global::ILSpy.ReadyToRun.Properties.Resources.ReadyToRun), Order = 40)]
[DataTemplate(typeof(ReadyToRunOptionsViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
partial class ReadyToRunOptionPage : UserControl, IOptionPage
partial class ReadyToRunOptionPage
{
public ReadyToRunOptionPage()
{
InitializeComponent();
}
public void Load(ILSpySettings settings)
{
Options s = new Options();
s.DisassemblyFormat = ReadyToRunOptions.GetDisassemblyFormat(settings);
s.IsShowUnwindInfo = ReadyToRunOptions.GetIsShowUnwindInfo(settings);
s.IsShowDebugInfo = ReadyToRunOptions.GetIsShowDebugInfo(settings);
s.IsShowGCInfo = ReadyToRunOptions.GetIsShowGCInfo(settings);
this.DataContext = s;
}
public void LoadDefaults()
{
this.DataContext = new Options();
}
public void Save(XElement root)
{
Options s = (Options)this.DataContext;
ReadyToRunOptions.SetDisassemblyOptions(root, s.DisassemblyFormat, s.IsShowUnwindInfo, s.IsShowDebugInfo, s.IsShowGCInfo);
}
}
internal class Options : INotifyPropertyChanged
[ExportOptionPage(Order = 40)]
[PartCreationPolicy(CreationPolicy.NonShared)]
class ReadyToRunOptionsViewModel : ObservableObject, IOptionPage
{
public string[] DisassemblyFormats {
get {
return ReadyToRunOptions.disassemblyFormats;
}
}
private bool isShowUnwindInfo;
public bool IsShowUnwindInfo {
get {
return isShowUnwindInfo;
}
set {
isShowUnwindInfo = value;
OnPropertyChanged(nameof(IsShowUnwindInfo));
}
}
private bool isShowDebugInfo;
private ReadyToRunOptions options;
public bool IsShowDebugInfo {
get {
return isShowDebugInfo;
}
set {
isShowDebugInfo = value;
OnPropertyChanged(nameof(IsShowDebugInfo));
}
public ReadyToRunOptions Options {
get => options;
set => SetProperty(ref options, value);
}
private bool isShowGCInfo;
public string Title => global::ILSpy.ReadyToRun.Properties.Resources.ReadyToRun;
public bool IsShowGCInfo {
get {
return isShowGCInfo;
}
set {
isShowGCInfo = value;
OnPropertyChanged(nameof(IsShowGCInfo));
}
}
private string disassemblyFormat;
public string DisassemblyFormat {
get { return disassemblyFormat; }
set {
if (disassemblyFormat != value)
{
disassemblyFormat = value;
OnPropertyChanged(nameof(DisassemblyFormat));
}
}
public void Load(SettingsSnapshot snapshot)
{
Options = snapshot.GetSettings<ReadyToRunOptions>();
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
public void LoadDefaults()
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
Options.LoadFromXml(new("empty"));
}
}
}

121
ILSpy.ReadyToRun/ReadyToRunOptions.cs

@ -18,110 +18,77 @@ @@ -18,110 +18,77 @@
using System.Xml.Linq;
using ICSharpCode.ILSpyX;
using ICSharpCode.ILSpyX.Settings;
using ICSharpCode.ILSpy.Util;
using TomsToolbox.Wpf;
namespace ICSharpCode.ILSpy.ReadyToRun
{
internal class ReadyToRunOptions
internal partial class ReadyToRunOptions : ObservableObject, ISettingsSection
{
private static readonly XNamespace ns = "http://www.ilspy.net/ready-to-run";
internal static string intel = "Intel";
internal static string gas = "AT & T";
internal static string[] disassemblyFormats = new string[] { intel, gas };
internal static string[] disassemblyFormats = [intel, gas];
public static string GetDisassemblyFormat(ILSpySettings settings)
{
if (settings == null)
{
settings = ILSpySettings.Load();
}
XElement e = settings[ns + "ReadyToRunOptions"];
XAttribute a = e.Attribute("DisassemblyFormat");
if (a == null)
{
return ReadyToRunOptions.intel;
}
else
{
return (string)a;
public string[] DisassemblyFormats {
get {
return disassemblyFormats;
}
}
public static bool GetIsShowUnwindInfo(ILSpySettings settings)
{
if (settings == null)
{
settings = ILSpySettings.Load();
}
XElement e = settings[ns + "ReadyToRunOptions"];
XAttribute a = e.Attribute("IsShowUnwindInfo");
private bool isShowUnwindInfo;
public bool IsShowUnwindInfo {
get => isShowUnwindInfo;
set => SetProperty(ref isShowUnwindInfo, value);
}
if (a == null)
{
return false;
}
else
{
return (bool)a;
}
private bool isShowDebugInfo;
public bool IsShowDebugInfo {
get => isShowDebugInfo;
set => SetProperty(ref isShowDebugInfo, value);
}
public static bool GetIsShowDebugInfo(ILSpySettings settings)
{
if (settings == null)
{
settings = ILSpySettings.Load();
}
XElement e = settings[ns + "ReadyToRunOptions"];
XAttribute a = e.Attribute("IsShowDebugInfo");
private bool isShowGCInfo;
public bool IsShowGCInfo {
get => isShowGCInfo;
set => SetProperty(ref isShowGCInfo, value);
}
if (a == null)
{
return true;
}
else
{
return (bool)a;
}
private string disassemblyFormat;
public string DisassemblyFormat {
get => disassemblyFormat;
set => SetProperty(ref disassemblyFormat, value);
}
public static bool GetIsShowGCInfo(ILSpySettings settings)
public XName SectionName { get; } = ns + "ReadyToRunOptions";
public void LoadFromXml(XElement e)
{
if (settings == null)
{
settings = ILSpySettings.Load();
}
XElement e = settings[ns + "ReadyToRunOptions"];
XAttribute a = e.Attribute("IsShowGCInfo");
XAttribute format = e.Attribute("DisassemblyFormat");
DisassemblyFormat = format == null ? intel : (string)format;
if (a == null)
{
return false;
}
else
{
return (bool)a;
}
XAttribute unwind = e.Attribute("IsShowUnwindInfo");
IsShowUnwindInfo = unwind != null && (bool)unwind;
XAttribute debug = e.Attribute("IsShowDebugInfo");
IsShowDebugInfo = debug == null || (bool)debug;
XAttribute showGc = e.Attribute("IsShowGCInfo");
IsShowGCInfo = showGc != null && (bool)showGc;
}
public static void SetDisassemblyOptions(XElement root, string disassemblyFormat, bool isShowUnwindInfo, bool isShowDebugInfo, bool isShowGCInfo)
public XElement SaveToXml()
{
XElement section = new XElement(ns + "ReadyToRunOptions");
var section = new XElement(SectionName);
section.SetAttributeValue("DisassemblyFormat", disassemblyFormat);
section.SetAttributeValue("IsShowUnwindInfo", isShowUnwindInfo);
section.SetAttributeValue("IsShowDebugInfo", isShowDebugInfo);
section.SetAttributeValue("IsShowGCInfo", isShowGCInfo);
XElement existingElement = root.Element(ns + "ReadyToRunOptions");
if (existingElement != null)
{
existingElement.ReplaceWith(section);
}
else
{
root.Add(section);
}
return section;
}
}
}

4
ILSpy/AboutPage.cs

@ -42,7 +42,7 @@ namespace ICSharpCode.ILSpy @@ -42,7 +42,7 @@ namespace ICSharpCode.ILSpy
{
public override void Execute(object parameter)
{
MainWindow.Instance.NavigateTo(
MainWindow.Instance.AssemblyTreeModel.NavigateTo(
new RequestNavigateEventArgs(new Uri("resource://aboutpage"), null),
inNewTabPage: true
);
@ -76,7 +76,7 @@ namespace ICSharpCode.ILSpy @@ -76,7 +76,7 @@ namespace ICSharpCode.ILSpy
CheckBox checkBox = new CheckBox();
checkBox.Margin = new Thickness(4);
checkBox.Content = Resources.AutomaticallyCheckUpdatesEveryWeek;
UpdateSettings settings = new UpdateSettings(ILSpySettings.Load());
UpdateSettings settings = new UpdateSettings(SettingsService.Instance.SpySettings);
checkBox.SetBinding(CheckBox.IsCheckedProperty, new Binding("AutomaticUpdateCheckEnabled") { Source = settings });
return new StackPanel {
Margin = new Thickness(0, 4, 0, 0),

4
ILSpy/Analyzers/AnalyzeCommand.cs

@ -78,12 +78,12 @@ namespace ICSharpCode.ILSpy.Analyzers @@ -78,12 +78,12 @@ namespace ICSharpCode.ILSpy.Analyzers
public override bool CanExecute(object parameter)
{
return MainWindow.Instance.SelectedNodes.All(n => n is IMemberTreeNode);
return MainWindow.Instance.AssemblyTreeModel.SelectedNodes.All(n => n is IMemberTreeNode);
}
public override void Execute(object parameter)
{
foreach (var node in MainWindow.Instance.SelectedNodes.OfType<IMemberTreeNode>())
foreach (var node in MainWindow.Instance.AssemblyTreeModel.SelectedNodes.OfType<IMemberTreeNode>())
{
AnalyzerTreeView.Analyze(node.Member);
}

3
ILSpy/Analyzers/AnalyzerEntityTreeNode.cs

@ -42,7 +42,8 @@ namespace ICSharpCode.ILSpy.Analyzers @@ -42,7 +42,8 @@ namespace ICSharpCode.ILSpy.Analyzers
MessageBox.Show(Properties.Resources.CannotAnalyzeMissingRef, "ILSpy");
return;
}
MainWindow.Instance.JumpToReference(new EntityReference(this.Member.ParentModule.MetadataFile, this.Member.MetadataToken));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(this.Member.ParentModule?.MetadataFile, this.Member.MetadataToken)));
}
public override bool HandleAssemblyListChanged(ICollection<LoadedAssembly> removedAssemblies, ICollection<LoadedAssembly> addedAssemblies)

1
ILSpy/Analyzers/AnalyzerRootNode.cs

@ -2,7 +2,6 @@ @@ -2,7 +2,6 @@
using System.Collections.Specialized;
using System.Linq;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX;
using ICSharpCode.ILSpyX.TreeView;

2
ILSpy/Analyzers/AnalyzerSearchTreeNode.cs

@ -61,7 +61,7 @@ namespace ICSharpCode.ILSpy.Analyzers @@ -61,7 +61,7 @@ namespace ICSharpCode.ILSpy.Analyzers
var context = new AnalyzerContext() {
CancellationToken = ct,
Language = Language,
AssemblyList = MainWindow.Instance.CurrentAssemblyList
AssemblyList = MainWindow.Instance.AssemblyTreeModel.AssemblyList
};
var results = analyzer.Analyze(symbol, context).Select(SymbolTreeNodeFactory);
if (context.SortResults)

1
ILSpy/Analyzers/AnalyzerTreeNode.cs

@ -18,7 +18,6 @@ @@ -18,7 +18,6 @@
using System.Collections.Generic;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX;
using ICSharpCode.ILSpyX.TreeView;

2
ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs

@ -61,7 +61,7 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes @@ -61,7 +61,7 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
MessageBox.Show(Properties.Resources.CannotAnalyzeMissingRef, "ILSpy");
return;
}
MainWindow.Instance.JumpToReference(analyzedModule.MetadataFile);
MessageBus.Send(this, new NavigateToReferenceEventArgs(analyzedModule.MetadataFile));
}
public override IEntity Member => null;

17
ILSpy/App.xaml

@ -1,15 +1,14 @@ @@ -1,15 +1,14 @@
<Application x:Class="ICSharpCode.ILSpy.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:styles="urn:TomsToolbox.Wpf.Styles"
xmlns:toms="urn:TomsToolbox"
xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes"
StartupUri="MainWindow.xaml">
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:styles="urn:TomsToolbox.Wpf.Styles"
xmlns:toms="urn:TomsToolbox"
xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes">
<Application.Resources>
<Style x:Key="DialogWindow" TargetType="{x:Type Window}">
<Setter Property="ShowInTaskbar" Value="False"/>
<Setter Property="UseLayoutRounding" Value="True"/>
<Setter Property="TextOptions.TextFormattingMode" Value="Display"/>
<Setter Property="ShowInTaskbar" Value="False" />
<Setter Property="UseLayoutRounding" Value="True" />
<Setter Property="TextOptions.TextFormattingMode" Value="Display" />
<Setter Property="toms:StyleBindings.Behaviors">
<Setter.Value>
<toms:BehaviorCollection>

62
ILSpy/App.xaml.cs

@ -31,9 +31,8 @@ using System.Windows.Navigation; @@ -31,9 +31,8 @@ using System.Windows.Navigation;
using System.Windows.Threading;
using ICSharpCode.ILSpy.AppEnv;
using ICSharpCode.ILSpy.Options;
using ICSharpCode.ILSpy.AssemblyTree;
using ICSharpCode.ILSpyX.Analyzers;
using ICSharpCode.ILSpyX.Settings;
using Medo.Application;
@ -44,7 +43,9 @@ using ICSharpCode.ILSpyX.TreeView; @@ -44,7 +43,9 @@ using ICSharpCode.ILSpyX.TreeView;
using TomsToolbox.Composition;
using TomsToolbox.Wpf.Composition;
using System.ComponentModel.Composition.Hosting;
using ICSharpCode.ILSpy.Themes;
using System.Globalization;
using System.Threading;
namespace ICSharpCode.ILSpy
{
@ -66,31 +67,31 @@ namespace ICSharpCode.ILSpy @@ -66,31 +67,31 @@ namespace ICSharpCode.ILSpy
public App()
{
ILSpySettings.SettingsFilePathProvider = new ILSpySettingsFilePathProvider();
var cmdArgs = Environment.GetCommandLineArgs().Skip(1);
App.CommandLineArguments = CommandLineArguments.Create(cmdArgs);
CommandLineArguments = CommandLineArguments.Create(cmdArgs);
bool forceSingleInstance = (App.CommandLineArguments.SingleInstance ?? true)
&& !MiscSettingsPanel.CurrentMiscSettings.AllowMultipleInstances;
bool forceSingleInstance = (CommandLineArguments.SingleInstance ?? true)
&& !SettingsService.Instance.MiscSettings.AllowMultipleInstances;
if (forceSingleInstance)
{
SingleInstance.Attach(); // will auto-exit for second instance
SingleInstance.NewInstanceDetected += SingleInstance_NewInstanceDetected;
}
SharpTreeNode.SetImagesProvider(new WpfWindowsTreeNodeImagesProvider());
InitializeComponent();
Resources.RegisterDefaultStyles();
if (!System.Diagnostics.Debugger.IsAttached)
if (!Debugger.IsAttached)
{
AppDomain.CurrentDomain.UnhandledException += ShowErrorBox;
Dispatcher.CurrentDispatcher.UnhandledException += Dispatcher_UnhandledException;
}
TaskScheduler.UnobservedTaskException += DotNet40_UnobservedTaskException;
SharpTreeNode.SetImagesProvider(new WpfWindowsTreeNodeImagesProvider());
Resources.RegisterDefaultStyles();
InitializeMef().GetAwaiter().GetResult();
// Register the export provider so that it can be accessed from WPF/XAML components.
@ -98,30 +99,34 @@ namespace ICSharpCode.ILSpy @@ -98,30 +99,34 @@ namespace ICSharpCode.ILSpy
// Add data templates registered via MEF.
Resources.MergedDictionaries.Add(DataTemplateManager.CreateDynamicDataTemplates(ExportProvider));
var sessionSettings = SettingsService.Instance.SessionSettings;
ThemeManager.Current.Theme = sessionSettings.Theme;
if (!string.IsNullOrEmpty(sessionSettings.CurrentCulture))
{
Thread.CurrentThread.CurrentUICulture = CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo(sessionSettings.CurrentCulture);
}
EventManager.RegisterClassHandler(typeof(Window),
Hyperlink.RequestNavigateEvent,
new RequestNavigateEventHandler(Window_RequestNavigate));
ILSpyTraceListener.Install();
if (App.CommandLineArguments.ArgumentsParser.IsShowingInformation)
if (CommandLineArguments.ArgumentsParser.IsShowingInformation)
{
MessageBox.Show(App.CommandLineArguments.ArgumentsParser.GetHelpText(), "ILSpy Command Line Arguments");
MessageBox.Show(CommandLineArguments.ArgumentsParser.GetHelpText(), "ILSpy Command Line Arguments");
}
if (App.CommandLineArguments.ArgumentsParser.RemainingArguments.Any())
if (CommandLineArguments.ArgumentsParser.RemainingArguments.Any())
{
string unknownArguments = string.Join(", ", App.CommandLineArguments.ArgumentsParser.RemainingArguments);
string unknownArguments = string.Join(", ", CommandLineArguments.ArgumentsParser.RemainingArguments);
MessageBox.Show(unknownArguments, "ILSpy Unknown Command Line Arguments Passed");
}
}
private static void SingleInstance_NewInstanceDetected(object sender, NewInstanceEventArgs e)
{
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
ICSharpCode.ILSpy.MainWindow.Instance.HandleSingleInstanceCommandLineArguments(e.Args);
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
SettingsService.Instance.AssemblyListManager.CreateDefaultAssemblyLists();
}
private static void SingleInstance_NewInstanceDetected(object sender, NewInstanceEventArgs e) => ExportProvider.GetExportedValue<AssemblyTreeModel>().HandleSingleInstanceCommandLineArguments(e.Args).HandleExceptions();
static Assembly ResolvePluginDependencies(AssemblyLoadContext context, AssemblyName assemblyName)
{
var rootPath = Path.GetDirectoryName(typeof(App).Assembly.Location);
@ -200,6 +205,8 @@ namespace ICSharpCode.ILSpy @@ -200,6 +205,8 @@ namespace ICSharpCode.ILSpy
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var output = new StringBuilder();
if (StartupExceptions.FormatExceptions(output))
@ -207,7 +214,12 @@ namespace ICSharpCode.ILSpy @@ -207,7 +214,12 @@ namespace ICSharpCode.ILSpy
MessageBox.Show(output.ToString(), "Sorry we crashed!");
Environment.Exit(1);
}
base.OnStartup(e);
MainWindow = new MainWindow();
MainWindow.Loaded += (sender, args) => {
ExportProvider.GetExportedValue<AssemblyTreeModel>().Initialize();
};
MainWindow.Show();
}
void DotNet40_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
@ -268,7 +280,7 @@ namespace ICSharpCode.ILSpy @@ -268,7 +280,7 @@ namespace ICSharpCode.ILSpy
void Window_RequestNavigate(object sender, RequestNavigateEventArgs e)
{
ILSpy.MainWindow.Instance.NavigateTo(e);
ExportProvider.GetExportedValue<AssemblyTreeModel>().NavigateTo(e);
}
}
}

54
ILSpy/AssemblyTree/AssemblyListPane.xaml

@ -0,0 +1,54 @@ @@ -0,0 +1,54 @@
<treeView:SharpTreeView x:Class="ICSharpCode.ILSpy.AssemblyTree.AssemblyListPane"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:treeView="clr-namespace:ICSharpCode.ILSpy.Controls.TreeView"
xmlns:treeNodes="clr-namespace:ICSharpCode.ILSpy.TreeNodes"
xmlns:assemblyTree="clr-namespace:ICSharpCode.ILSpy.AssemblyTree"
xmlns:toms="urn:TomsToolbox"
mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance assemblyTree:AssemblyTreeModel}"
AutomationProperties.Name="Assemblies and Classes"
ShowRoot="False"
AllowDropOrder="True"
AllowDrop="True"
BorderThickness="0" Visibility="Visible"
Root="{Binding Root}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"
toms:MultiSelectorExtensions.SelectionBinding="{Binding SelectedItems}">
<treeView:SharpTreeView.ItemContainerStyle>
<Style TargetType="treeView:SharpTreeViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type treeView:SharpTreeViewItem}"
d:DataContext="{d:DesignInstance treeNodes:ILSpyTreeNode}">
<Border Background="Transparent">
<Border Background="{TemplateBinding Background}">
<treeView:SharpTreeNodeView x:Name="nodeView" HorizontalAlignment="Left" />
</Border>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding IsAutoLoaded}" Value="True">
<Setter Property="Foreground" Value="SteelBlue" />
</DataTrigger>
<DataTrigger Binding="{Binding IsPublicAPI}" Value="False">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</DataTrigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="nodeView" Property="TextBackground"
Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
<Setter TargetName="nodeView" Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="nodeView" Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</treeView:SharpTreeView.ItemContainerStyle>
</treeView:SharpTreeView>

44
ILSpy/AssemblyTree/AssemblyListPane.xaml.cs

@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
using System.ComponentModel.Composition;
using System.Windows;
using ICSharpCode.ILSpyX.TreeView;
using TomsToolbox.Wpf.Composition.Mef;
namespace ICSharpCode.ILSpy.AssemblyTree
{
/// <summary>
/// Interaction logic for AssemblyListPane.xaml
/// </summary>
[DataTemplate(typeof(AssemblyTreeModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public partial class AssemblyListPane
{
public AssemblyListPane()
{
InitializeComponent();
ContextMenuProvider.Add(this);
}
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (e.Property == DataContextProperty)
{
if (e.NewValue is not AssemblyTreeModel model)
return;
model.SetActiveView(this);
}
else if (e.Property == SelectedItemProperty)
{
if (e.NewValue is not SharpTreeNode treeNode)
return;
FocusNode(treeNode);
}
}
}
}

932
ILSpy/AssemblyTree/AssemblyTreeModel.cs

@ -0,0 +1,932 @@ @@ -0,0 +1,932 @@
// Copyright (c) 2019 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
// 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;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows.Threading;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.Docking;
using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.ViewModels;
using ICSharpCode.ILSpyX;
using ICSharpCode.ILSpyX.Settings;
using ICSharpCode.ILSpyX.TreeView;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using ICSharpCode.Decompiler.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Windows;
using ICSharpCode.Decompiler.Documentation;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using System.Reflection.Metadata;
using ICSharpCode.ILSpy.AppEnv;
using ICSharpCode.ILSpy.Search;
using ICSharpCode.Decompiler;
using System.Text;
using TomsToolbox.Essentials;
using TomsToolbox.Wpf;
using System.Windows.Navigation;
namespace ICSharpCode.ILSpy.AssemblyTree
{
[ExportToolPane]
[PartCreationPolicy(CreationPolicy.Shared)]
[Export]
public class AssemblyTreeModel : ToolPaneModel
{
public const string PaneContentId = "assemblyListPane";
AssemblyListPane activeView;
AssemblyListTreeNode assemblyListTreeNode;
readonly NavigationHistory<NavigationState> history = new();
public AssemblyTreeModel()
{
Title = Resources.Assemblies;
ContentId = PaneContentId;
IsCloseable = false;
ShortcutKey = new KeyGesture(Key.F6);
MessageBus<NavigateToReferenceEventArgs>.Subscribers += JumpToReference;
MessageBus<SettingsChangedEventArgs>.Subscribers += (sender, e) => Settings_PropertyChanged(sender, e);
var selectionChangeThrottle = new DispatcherThrottle(DispatcherPriority.Background, TreeView_SelectionChanged);
SelectedItems.CollectionChanged += (_, _) => selectionChangeThrottle.Tick();
}
private void Settings_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (sender is SessionSettings sessionSettings)
{
switch (e.PropertyName)
{
case nameof(SessionSettings.ActiveAssemblyList):
ShowAssemblyList(sessionSettings.ActiveAssemblyList);
break;
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);
break;
case nameof(SessionSettings.CurrentCulture):
MessageBox.Show(Properties.Resources.SettingsChangeRestartRequired, "ILSpy");
break;
}
}
else if (sender is LanguageSettings)
{
switch (e.PropertyName)
{
case nameof(LanguageSettings.Language) or nameof(LanguageSettings.LanguageVersion):
DecompileSelectedNodes(recordHistory: false);
break;
}
}
}
public AssemblyList AssemblyList { get; private set; }
private SharpTreeNode root;
public SharpTreeNode Root {
get => root;
set => SetProperty(ref root, value);
}
private SharpTreeNode selectedItem;
public SharpTreeNode SelectedItem {
get => selectedItem;
set => SetProperty(ref selectedItem, value);
}
public ObservableCollection<SharpTreeNode> SelectedItems { get; } = [];
public string[] SelectedPath => GetPathForNode(SelectedItem);
readonly List<LoadedAssembly> commandLineLoadedAssemblies = [];
public bool HandleCommandLineArguments(CommandLineArguments args)
{
LoadAssemblies(args.AssembliesToLoad, commandLineLoadedAssemblies, focusNode: false);
if (args.Language != null)
SettingsService.Instance.SessionSettings.LanguageSettings.Language = Languages.GetLanguage(args.Language);
return true;
}
/// <summary>
/// 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)
{
var sessionSettings = SettingsService.Instance.SessionSettings;
var relevantAssemblies = commandLineLoadedAssemblies.ToList();
commandLineLoadedAssemblies.Clear(); // clear references once we don't need them anymore
NavigateOnLaunch(args.NavigateTo, sessionSettings.ActiveTreeViewPath, spySettings, relevantAssemblies);
if (args.Search != null)
{
var searchPane = App.ExportProvider.GetExportedValue<SearchPaneModel>();
searchPane.SearchTerm = args.Search;
searchPane.Show();
}
}
public async Task HandleSingleInstanceCommandLineArguments(string[] args)
{
var cmdArgs = CommandLineArguments.Create(args);
await Dispatcher.InvokeAsync(() => {
if (!HandleCommandLineArguments(cmdArgs))
return;
var window = Application.Current.MainWindow;
if (!cmdArgs.NoActivate && window is { WindowState: WindowState.Minimized })
{
window.WindowState = WindowState.Normal;
}
HandleCommandLineArgumentsAfterShowList(cmdArgs);
});
}
public async void NavigateOnLaunch(string navigateTo, string[] activeTreeViewPath, ISettingsProvider spySettings, List<LoadedAssembly> relevantAssemblies)
{
var initialSelection = SelectedItem;
if (navigateTo != null)
{
bool found = false;
if (navigateTo.StartsWith("N:", StringComparison.Ordinal))
{
string namespaceName = navigateTo.Substring(2);
foreach (LoadedAssembly asm in relevantAssemblies)
{
AssemblyTreeNode asmNode = assemblyListTreeNode.FindAssemblyNode(asm);
if (asmNode != null)
{
// FindNamespaceNode() blocks the UI if the assembly is not yet loaded,
// so use an async wait instead.
await asm.GetMetadataFileAsync().Catch<Exception>(ex => { });
NamespaceTreeNode nsNode = asmNode.FindNamespaceNode(namespaceName);
if (nsNode != null)
{
found = true;
if (SelectedItem == initialSelection)
{
SelectNode(nsNode);
}
break;
}
}
}
}
else if (navigateTo == "none")
{
// Don't navigate anywhere; start empty.
// Used by ILSpy VS addin, it'll send us the real location to navigate to via IPC.
found = true;
}
else
{
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)
{
found = true;
if (SelectedItem == initialSelection)
{
await JumpToReferenceAsync(mr);
}
}
}
if (!found && SelectedItem == initialSelection)
{
AvalonEditTextOutput output = new AvalonEditTextOutput();
output.Write($"Cannot find '{navigateTo}' in command line specified assemblies.");
DockWorkspace.Instance.ShowText(output);
}
}
else if (relevantAssemblies.Count == 1)
{
// NavigateTo == null and an assembly was given on the command-line:
// Select the newly loaded assembly
AssemblyTreeNode asmNode = assemblyListTreeNode.FindAssemblyNode(relevantAssemblies[0]);
if (asmNode != null && SelectedItem == initialSelection)
{
SelectNode(asmNode);
}
}
else if (spySettings != null)
{
SharpTreeNode node = null;
if (activeTreeViewPath?.Length > 0)
{
foreach (var asm in AssemblyList.GetAssemblies())
{
if (asm.FileName == activeTreeViewPath[0])
{
// FindNodeByPath() blocks the UI if the assembly is not yet loaded,
// so use an async wait instead.
await asm.GetMetadataFileAsync().Catch<Exception>(ex => { });
}
}
node = FindNodeByPath(activeTreeViewPath, true);
}
if (SelectedItem == initialSelection)
{
if (node != null)
{
SelectNode(node);
// only if not showing the about page, perform the update check:
await MainWindow.Instance.ShowMessageIfUpdatesAvailableAsync(spySettings);
}
else
{
DockWorkspace.Instance.ActiveTabPage.ShowTextView(AboutPage.Display);
}
}
}
}
public static IEntity FindEntityInRelevantAssemblies(string navigateTo, IEnumerable<LoadedAssembly> relevantAssemblies)
{
ITypeReference typeRef;
IMemberReference memberRef = null;
if (navigateTo.StartsWith("T:", StringComparison.Ordinal))
{
typeRef = IdStringProvider.ParseTypeName(navigateTo);
}
else
{
memberRef = IdStringProvider.ParseMemberIdString(navigateTo);
typeRef = memberRef.DeclaringTypeReference;
}
foreach (LoadedAssembly asm in relevantAssemblies.ToList())
{
var module = asm.GetMetadataFileOrNull();
if (CanResolveTypeInPEFile(module, typeRef, out var typeHandle))
{
ICompilation compilation = typeHandle.Kind == HandleKind.ExportedType
? new DecompilerTypeSystem(module, module.GetAssemblyResolver())
: new SimpleCompilation((PEFile)module, MinimalCorlib.Instance);
return memberRef == null
? typeRef.Resolve(new SimpleTypeResolveContext(compilation)) as ITypeDefinition
: memberRef.Resolve(new SimpleTypeResolveContext(compilation));
}
}
return null;
}
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())
{
typeHandle = default;
return false;
}
switch (typeRef)
{
case GetPotentiallyNestedClassTypeReference topLevelType:
typeHandle = topLevelType.ResolveInPEFile(module);
return !typeHandle.IsNil;
case NestedTypeReference nestedType:
if (!CanResolveTypeInPEFile(module, nestedType.DeclaringTypeReference, out typeHandle))
return false;
if (typeHandle.Kind == HandleKind.ExportedType)
return true;
var typeDef = module.Metadata.GetTypeDefinition((TypeDefinitionHandle)typeHandle);
typeHandle = typeDef.GetNestedTypes().FirstOrDefault(t => {
var td = module.Metadata.GetTypeDefinition(t);
var typeName = ReflectionHelper.SplitTypeParameterCountFromReflectionName(module.Metadata.GetString(td.Name), out int typeParameterCount);
return nestedType.AdditionalTypeParameterCount == typeParameterCount && nestedType.Name == typeName;
});
return !typeHandle.IsNil;
default:
typeHandle = default;
return false;
}
}
public void Initialize()
{
this.AssemblyList = SettingsService.Instance.LoadInitialAssemblyList();
HandleCommandLineArguments(App.CommandLineArguments);
var loadPreviousAssemblies = SettingsService.Instance.MiscSettings.LoadPreviousAssemblies;
if (AssemblyList.GetAssemblies().Length == 0
&& AssemblyList.ListName == AssemblyListManager.DefaultListName
&& loadPreviousAssemblies)
{
LoadInitialAssemblies();
}
ShowAssemblyList(this.AssemblyList);
var sessionSettings = SettingsService.Instance.SessionSettings;
if (sessionSettings.ActiveAutoLoadedAssembly != null
&& File.Exists(sessionSettings.ActiveAutoLoadedAssembly))
{
this.AssemblyList.Open(sessionSettings.ActiveAutoLoadedAssembly, true);
}
Dispatcher.BeginInvoke(DispatcherPriority.Loaded, OpenAssemblies);
}
void OpenAssemblies()
{
HandleCommandLineArgumentsAfterShowList(App.CommandLineArguments, SettingsService.Instance.SpySettings);
AvalonEditTextOutput output = new();
if (FormatExceptions(App.StartupExceptions.ToArray(), output))
DockWorkspace.Instance.ShowText(output);
}
static bool FormatExceptions(App.ExceptionData[] exceptions, ITextOutput output)
{
var stringBuilder = new StringBuilder();
var result = exceptions.FormatExceptions(stringBuilder);
if (result)
{
output.Write(stringBuilder.ToString());
}
return result;
}
public 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)
{
ShowAssemblyList(list);
SelectNode(Root);
}
}
void ShowAssemblyList(AssemblyList assemblyList)
{
history.Clear();
if (this.AssemblyList != null)
{
this.AssemblyList.CollectionChanged -= assemblyList_CollectionChanged;
}
this.AssemblyList = assemblyList;
assemblyList.CollectionChanged += assemblyList_CollectionChanged;
assemblyListTreeNode = new(assemblyList) {
Select = x => SelectNode(x)
};
Root = assemblyListTreeNode;
if (assemblyList.ListName == AssemblyListManager.DefaultListName)
#if DEBUG
this.Title = $"ILSpy {DecompilerVersionInfo.FullVersion}";
#else
this.Title = "ILSpy";
#endif
else
#if DEBUG
this.Title = $"ILSpy {DecompilerVersionInfo.FullVersion} - " + assemblyList.ListName;
#else
this.Title = "ILSpy - " + assemblyList.ListName;
#endif
}
void assemblyList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.Action == NotifyCollectionChangedAction.Reset)
{
history.RemoveAll(_ => true);
}
if (e.OldItems != null)
{
var oldAssemblies = new HashSet<LoadedAssembly>(e.OldItems.Cast<LoadedAssembly>());
history.RemoveAll(n => n.TreeNodes.Any(
nd => nd.AncestorsAndSelf().OfType<AssemblyTreeNode>().Any(
a => oldAssemblies.Contains(a.LoadedAssembly))));
}
MessageBus.Send(this, new CurrentAssemblyListChangedEventArgs(e));
}
void LoadInitialAssemblies()
{
// Called when loading an empty assembly list; so that
// the user can see something initially.
System.Reflection.Assembly[] initialAssemblies = {
typeof(object).Assembly,
typeof(Uri).Assembly,
typeof(System.Linq.Enumerable).Assembly,
typeof(System.Xml.XmlDocument).Assembly,
typeof(System.Windows.Markup.MarkupExtension).Assembly,
typeof(System.Windows.Rect).Assembly,
typeof(System.Windows.UIElement).Assembly,
typeof(System.Windows.FrameworkElement).Assembly
};
foreach (System.Reflection.Assembly asm in initialAssemblies)
AssemblyList.OpenAssembly(asm.Location);
}
public AssemblyTreeNode FindAssemblyNode(LoadedAssembly asm)
{
return assemblyListTreeNode.FindAssemblyNode(asm);
}
#region Node Selection
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);
return;
}
if (inNewTabPage)
{
DockWorkspace.Instance.AddTabPage();
SelectedItem = null;
}
if (SelectedItem == node)
{
Dispatcher.BeginInvoke(RefreshDecompiledView);
}
else
{
activeView?.ScrollIntoView(node);
SelectedItem = node;
}
}
internal void SelectNodes(IEnumerable<SharpTreeNode> nodes, bool ignoreCompilationRequests = false)
{
this.ignoreDecompilationRequests = ignoreCompilationRequests;
try
{
// Ensure nodes exist
var nodesList = nodes.Select(n => FindNodeByPath(GetPathForNode(n), true))
.Where(n => n != null)
.ToArray();
if (!nodesList.Any() || nodesList.Any(n => n.AncestorsAndSelf().Any(a => a.IsHidden)))
{
return;
}
if (SelectedItems.SequenceEqual(nodesList))
{
Dispatcher.BeginInvoke(RefreshDecompiledView);
return;
}
SelectedItems.Clear();
SelectedItems.AddRange(nodesList);
}
finally
{
this.ignoreDecompilationRequests = false;
}
}
/// <summary>
/// Retrieves a node using the .ToString() representations of its ancestors.
/// </summary>
public SharpTreeNode FindNodeByPath(string[] path, bool returnBestMatch)
{
if (path == null)
return null;
SharpTreeNode node = Root;
SharpTreeNode bestMatch = node;
foreach (var element in path)
{
if (node == null)
break;
bestMatch = node;
node.EnsureLazyChildren();
if (node is ILSpyTreeNode ilSpyTreeNode)
ilSpyTreeNode.EnsureChildrenFiltered();
node = node.Children.FirstOrDefault(c => c.ToString() == element);
}
if (returnBestMatch)
return node ?? bestMatch;
else
return node;
}
/// <summary>
/// Gets the .ToString() representation of the node's ancestors.
/// </summary>
public static string[] GetPathForNode(SharpTreeNode node)
{
if (node == null)
return null;
List<string> path = new List<string>();
while (node.Parent != null)
{
path.Add(node.ToString());
node = node.Parent;
}
path.Reverse();
return path.ToArray();
}
public ILSpyTreeNode FindTreeNode(object reference)
{
switch (reference)
{
case LoadedAssembly lasm:
return assemblyListTreeNode.FindAssemblyNode(lasm);
case MetadataFile asm:
return assemblyListTreeNode.FindAssemblyNode(asm);
case Resource res:
return assemblyListTreeNode.FindResourceNode(res);
case ValueTuple<Resource, string> resName:
return assemblyListTreeNode.FindResourceNode(resName.Item1, resName.Item2);
case ITypeDefinition type:
return assemblyListTreeNode.FindTypeNode(type);
case IField fd:
return assemblyListTreeNode.FindFieldNode(fd);
case IMethod md:
return assemblyListTreeNode.FindMethodNode(md);
case IProperty pd:
return assemblyListTreeNode.FindPropertyNode(pd);
case IEvent ed:
return assemblyListTreeNode.FindEventNode(ed);
case INamespace nd:
return assemblyListTreeNode.FindNamespaceNode(nd);
default:
return null;
}
}
private void JumpToReference(object sender, NavigateToReferenceEventArgs e)
{
JumpToReferenceAsync(e.Reference, e.InNewTabPage).HandleExceptions();
}
/// <summary>
/// Jumps to the specified reference.
/// </summary>
/// <returns>
/// 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)
{
var decompilationTask = Task.CompletedTask;
switch (reference)
{
case Decompiler.Disassembler.OpCodeInfo opCode:
MainWindow.OpenLink(opCode.Link);
break;
case EntityReference unresolvedEntity:
string protocol = unresolvedEntity.Protocol;
var file = unresolvedEntity.ResolveAssembly(AssemblyList);
if (file == null)
{
break;
}
if (protocol != "decompile")
{
var protocolHandlers = App.ExportProvider.GetExportedValues<IProtocolHandler>();
foreach (var handler in protocolHandlers)
{
var node = handler.Resolve(protocol, file, unresolvedEntity.Handle, out bool newTabPage);
if (node != null)
{
SelectNode(node, newTabPage || inNewTabPage);
return decompilationTask;
}
}
}
var possibleToken = MetadataTokenHelpers.TryAsEntityHandle(MetadataTokens.GetToken(unresolvedEntity.Handle));
if (possibleToken != null)
{
var typeSystem = new DecompilerTypeSystem(file, file.GetAssemblyResolver(), TypeSystemOptions.Default | TypeSystemOptions.Uncached);
reference = typeSystem.MainModule.ResolveEntity(possibleToken.Value);
goto default;
}
break;
default:
ILSpyTreeNode treeNode = FindTreeNode(reference);
if (treeNode != null)
SelectNode(treeNode, inNewTabPage);
break;
}
return decompilationTask;
}
#endregion
public void LoadAssemblies(IEnumerable<string> fileNames, List<LoadedAssembly> loadedAssemblies = null, bool focusNode = true)
{
using (Keyboard.FocusedElement.PreserveFocus(!focusNode))
{
AssemblyTreeNode lastNode = null;
foreach (string file in fileNames)
{
var assembly = AssemblyList.OpenAssembly(file);
if (loadedAssemblies != null)
{
loadedAssemblies.Add(assembly);
}
else
{
var node = assemblyListTreeNode.FindAssemblyNode(assembly);
if (node != null && focusNode)
{
lastNode = node;
SelectedItems.Add(node);
}
}
}
if (focusNode && lastNode != null)
{
activeView?.FocusNode(lastNode);
}
}
}
#region Decompile (TreeView_SelectionChanged)
void TreeView_SelectionChanged()
{
var delayDecompilationRequestDueToContextMenu = Mouse.RightButton == MouseButtonState.Pressed;
if (!delayDecompilationRequestDueToContextMenu)
{
DecompileSelectedNodes();
}
else
{
ContextMenuProvider.ContextMenuClosed += ContextMenuClosed;
}
MessageBus.Send(this, new AssemblyTreeSelectionChangedEventArgs());
return;
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);
}
});
}
}
private bool ignoreDecompilationRequests;
public void DecompileSelectedNodes(DecompilerTextViewState newState = null, bool recordHistory = true)
{
if (ignoreDecompilationRequests)
return;
var activeTabPage = DockWorkspace.Instance.ActiveTabPage;
if (recordHistory)
{
var currentState = activeTabPage.GetState();
if (currentState != null)
history.UpdateCurrent(new NavigationState(activeTabPage, currentState));
history.Record(new NavigationState(activeTabPage, SelectedItems));
}
activeTabPage.SupportsLanguageSwitching = true;
if (SelectedItems.Count == 1)
{
if (SelectedItem is ILSpyTreeNode node && node.View(activeTabPage))
return;
}
if (newState?.ViewedUri != null)
{
MainWindow.Instance.AssemblyTreeModel.NavigateTo(new(newState.ViewedUri, null), recordHistory: false);
return;
}
var options = SettingsService.Instance.CreateDecompilationOptions(activeTabPage);
options.TextViewState = newState;
activeTabPage.ShowTextViewAsync(textView => textView.DecompileAsync(this.CurrentLanguage, this.SelectedNodes, options));
}
public void RefreshDecompiledView()
{
DecompileSelectedNodes();
}
public Language CurrentLanguage => SettingsService.Instance.SessionSettings.LanguageSettings.Language;
public LanguageVersion CurrentLanguageVersion => SettingsService.Instance.SessionSettings.LanguageSettings.LanguageVersion;
public IEnumerable<ILSpyTreeNode> SelectedNodes {
get {
return GetTopLevelSelection().OfType<ILSpyTreeNode>();
}
}
#endregion
public void NavigateHistory(bool forward)
{
TabPageModel tabPage = DockWorkspace.Instance.ActiveTabPage;
var state = tabPage.GetState();
if (state != null)
history.UpdateCurrent(new NavigationState(tabPage, state));
var newState = forward ? history.GoForward() : history.GoBack();
DockWorkspace.Instance.ActiveTabPage = newState.TabPage;
SelectNodes(newState.TreeNodes, ignoreCompilationRequests: true);
DecompileSelectedNodes(newState.ViewState as DecompilerTextViewState, false);
}
public bool CanNavigateBack => history.CanNavigateBack;
public bool CanNavigateForward => history.CanNavigateForward;
internal void NavigateTo(RequestNavigateEventArgs e, bool recordHistory = true, bool inNewTabPage = false)
{
if (e.Uri.Scheme == "resource")
{
if (inNewTabPage)
{
DockWorkspace.Instance.AddTabPage();
}
if (e.Uri.Host == "aboutpage")
{
RecordHistory();
DockWorkspace.Instance.ActiveTabPage.ShowTextView(AboutPage.Display);
e.Handled = true;
return;
}
AvalonEditTextOutput output = new AvalonEditTextOutput {
Address = e.Uri,
Title = e.Uri.AbsolutePath,
EnableHyperlinks = true
};
using (Stream s = typeof(App).Assembly.GetManifestResourceStream(typeof(App), e.Uri.AbsolutePath))
{
using (StreamReader r = new StreamReader(s))
{
string line;
while ((line = r.ReadLine()) != null)
{
output.Write(line);
output.WriteLine();
}
}
}
RecordHistory();
DockWorkspace.Instance.ShowText(output);
e.Handled = true;
}
void RecordHistory()
{
if (!recordHistory)
return;
TabPageModel tabPage = DockWorkspace.Instance.ActiveTabPage;
var currentState = tabPage.GetState();
if (currentState != null)
history.UpdateCurrent(new NavigationState(tabPage, currentState));
UnselectAll(ignoreCompilationRequests: true);
history.Record(new NavigationState(tabPage, new ViewState { ViewedUri = e.Uri }));
}
}
public void Refresh()
{
using (Keyboard.FocusedElement.PreserveFocus())
{
var path = GetPathForNode(SelectedItem);
ShowAssemblyList(SettingsService.Instance.AssemblyListManager.LoadList(AssemblyList.ListName));
SelectNode(FindNodeByPath(path, true), inNewTabPage: false);
}
}
public void UnselectAll(bool ignoreCompilationRequests = false)
{
this.ignoreDecompilationRequests = ignoreCompilationRequests;
SelectedItems.Clear();
this.ignoreDecompilationRequests = false;
}
public IEnumerable<SharpTreeNode> GetTopLevelSelection()
{
var selection = this.SelectedItems;
var selectionHash = new HashSet<SharpTreeNode>(selection);
return selection.Where(item => item.Ancestors().All(a => !selectionHash.Contains(a)));
}
public void SetActiveView(AssemblyListPane activeView)
{
this.activeView = activeView;
}
public void SortAssemblyList()
{
using (activeView?.LockUpdates())
{
AssemblyList.Sort(AssemblyComparer.Instance);
}
}
private class AssemblyComparer : IComparer<LoadedAssembly>
{
public static readonly AssemblyComparer Instance = new();
int IComparer<LoadedAssembly>.Compare(LoadedAssembly x, LoadedAssembly y)
{
return string.Compare(x?.ShortName, y?.ShortName, StringComparison.CurrentCulture);
}
}
public void CollapseAll()
{
using (activeView.LockUpdates())
{
CollapseChildren(Root);
}
}
static void CollapseChildren(SharpTreeNode node)
{
foreach (var child in node.Children)
{
if (!child.IsExpanded)
continue;
CollapseChildren(child);
child.IsExpanded = false;
}
}
public void OpenFiles(string[] fileNames, bool focusNode = true)
{
if (fileNames == null)
throw new ArgumentNullException(nameof(fileNames));
if (focusNode)
UnselectAll();
LoadAssemblies(fileNames, focusNode: focusNode);
}
}
}

24
ILSpy/Commands/BrowseBackCommand.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System.ComponentModel.Composition;
using System.Windows.Input;
using ICSharpCode.ILSpy.AssemblyTree;
using ICSharpCode.ILSpy.Properties;
namespace ICSharpCode.ILSpy
@ -27,9 +28,30 @@ namespace ICSharpCode.ILSpy @@ -27,9 +28,30 @@ namespace ICSharpCode.ILSpy
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class BrowseBackCommand : CommandWrapper
{
public BrowseBackCommand()
readonly AssemblyTreeModel assemblyTreeModel;
[ImportingConstructor]
public BrowseBackCommand(AssemblyTreeModel assemblyTreeModel)
: base(NavigationCommands.BrowseBack)
{
this.assemblyTreeModel = assemblyTreeModel;
}
protected override void OnCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
base.OnCanExecute(sender, e);
e.Handled = true;
e.CanExecute = assemblyTreeModel.CanNavigateBack;
}
protected override void OnExecute(object sender, ExecutedRoutedEventArgs e)
{
if (assemblyTreeModel.CanNavigateBack)
{
e.Handled = true;
assemblyTreeModel.NavigateHistory(false);
}
}
}
}

25
ILSpy/Commands/BrowseForwardCommand.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System.ComponentModel.Composition;
using System.Windows.Input;
using ICSharpCode.ILSpy.AssemblyTree;
using ICSharpCode.ILSpy.Properties;
namespace ICSharpCode.ILSpy
@ -27,9 +28,31 @@ namespace ICSharpCode.ILSpy @@ -27,9 +28,31 @@ namespace ICSharpCode.ILSpy
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class BrowseForwardCommand : CommandWrapper
{
public BrowseForwardCommand()
private readonly AssemblyTreeModel assemblyTreeModel;
[ImportingConstructor]
public BrowseForwardCommand(AssemblyTreeModel assemblyTreeModel)
: base(NavigationCommands.BrowseForward)
{
this.assemblyTreeModel = assemblyTreeModel;
}
protected override void OnCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
base.OnCanExecute(sender, e);
e.Handled = true;
e.CanExecute = assemblyTreeModel.CanNavigateForward;
}
protected override void OnExecute(object sender, ExecutedRoutedEventArgs e)
{
if (assemblyTreeModel.CanNavigateForward)
{
e.Handled = true;
assemblyTreeModel.NavigateHistory(true);
}
}
}
}

3
ILSpy/Commands/CheckForUpdatesCommand.cs

@ -20,7 +20,6 @@ @@ -20,7 +20,6 @@
using System.ComponentModel.Composition;
using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpyX.Settings;
namespace ICSharpCode.ILSpy
{
@ -35,7 +34,7 @@ namespace ICSharpCode.ILSpy @@ -35,7 +34,7 @@ namespace ICSharpCode.ILSpy
public override async void Execute(object parameter)
{
await MainWindow.Instance.ShowMessageIfUpdatesAvailableAsync(ILSpySettings.Load(), forceCheck: true);
await MainWindow.Instance.ShowMessageIfUpdatesAvailableAsync(SettingsService.Instance.SpySettings, forceCheck: true);
}
}
}

21
ILSpy/Commands/CommandWrapper.cs

@ -17,26 +17,28 @@ @@ -17,26 +17,28 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Windows;
using System.Windows.Input;
namespace ICSharpCode.ILSpy
{
class CommandWrapper : ICommand
abstract class CommandWrapper : ICommand
{
private readonly ICommand wrappedCommand;
public CommandWrapper(ICommand wrappedCommand)
protected CommandWrapper(ICommand wrappedCommand)
{
this.wrappedCommand = wrappedCommand;
Application.Current.MainWindow?.CommandBindings.Add(new CommandBinding(wrappedCommand, OnExecute, OnCanExecute));
}
public static ICommand Unwrap(ICommand command)
{
CommandWrapper w = command as CommandWrapper;
if (w != null)
if (command is CommandWrapper w)
return w.wrappedCommand;
else
return command;
return command;
}
public event EventHandler CanExecuteChanged {
@ -53,5 +55,12 @@ namespace ICSharpCode.ILSpy @@ -53,5 +55,12 @@ namespace ICSharpCode.ILSpy
{
return wrappedCommand.CanExecute(parameter);
}
protected abstract void OnExecute(object sender, ExecutedRoutedEventArgs e);
protected virtual void OnCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = true;
}
}
}

15
ILSpy/Commands/DecompileAllCommand.cs

@ -26,9 +26,9 @@ using System.Linq; @@ -26,9 +26,9 @@ using System.Linq;
using System.Threading.Tasks;
using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy.Docking;
using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX;
using TomsToolbox.Essentials;
@ -49,7 +49,7 @@ namespace ICSharpCode.ILSpy @@ -49,7 +49,7 @@ namespace ICSharpCode.ILSpy
Docking.DockWorkspace.Instance.RunWithCancellation(ct => Task<AvalonEditTextOutput>.Factory.StartNew(() => {
AvalonEditTextOutput output = new AvalonEditTextOutput();
Parallel.ForEach(
Partitioner.Create(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), loadBalance: true),
Partitioner.Create(MainWindow.Instance.AssemblyTreeModel.AssemblyList.GetAssemblies(), loadBalance: true),
new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = ct },
delegate (LoadedAssembly asm) {
if (!asm.HasLoadError)
@ -60,7 +60,7 @@ namespace ICSharpCode.ILSpy @@ -60,7 +60,7 @@ namespace ICSharpCode.ILSpy
{
try
{
var options = MainWindow.Instance.CreateDecompilationOptions();
var options = SettingsService.Instance.CreateDecompilationOptions(DockWorkspace.Instance.ActiveTabPage);
options.CancellationToken = ct;
options.FullDecompilation = true;
new CSharpLanguage().DecompileAssembly(asm, new PlainTextOutput(writer), options);
@ -96,9 +96,10 @@ namespace ICSharpCode.ILSpy @@ -96,9 +96,10 @@ namespace ICSharpCode.ILSpy
{
const int numRuns = 100;
var language = SettingsService.Instance.SessionSettings.LanguageSettings.Language;
var nodes = MainWindow.Instance.SelectedNodes.ToArray();
var options = MainWindow.Instance.CreateDecompilationOptions();
Docking.DockWorkspace.Instance.RunWithCancellation(ct => Task<AvalonEditTextOutput>.Factory.StartNew(() => {
var nodes = MainWindow.Instance.AssemblyTreeModel.SelectedNodes.ToArray();
DockWorkspace dockWorkspace = DockWorkspace.Instance;
var options = SettingsService.Instance.CreateDecompilationOptions(dockWorkspace.ActiveTabPage);
dockWorkspace.RunWithCancellation(ct => Task<AvalonEditTextOutput>.Factory.StartNew(() => {
options.CancellationToken = ct;
Stopwatch w = Stopwatch.StartNew();
for (int i = 0; i < numRuns; ++i)
@ -113,7 +114,7 @@ namespace ICSharpCode.ILSpy @@ -113,7 +114,7 @@ namespace ICSharpCode.ILSpy
double msPerRun = w.Elapsed.TotalMilliseconds / numRuns;
output.Write($"Average time: {msPerRun.ToString("f1")}ms\n");
return output;
}, ct)).Then(output => Docking.DockWorkspace.Instance.ShowText(output)).HandleExceptions();
}, ct)).Then(output => dockWorkspace.ShowText(output)).HandleExceptions();
}
}
}

2
ILSpy/Commands/DecompileCommand.cs

@ -66,7 +66,7 @@ namespace ICSharpCode.ILSpy.Commands @@ -66,7 +66,7 @@ namespace ICSharpCode.ILSpy.Commands
selection = entity;
}
if (selection != null)
MainWindow.Instance.JumpToReference(selection);
MessageBus.Send(this, new NavigateToReferenceEventArgs(selection));
}
}
}

18
ILSpy/Commands/DecompileInNewViewCommand.cs

@ -25,9 +25,10 @@ using System.Windows.Threading; @@ -25,9 +25,10 @@ using System.Windows.Threading;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.Docking;
using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
using TomsToolbox.Essentials;
namespace ICSharpCode.ILSpy.Commands
{
[ExportContextMenuEntry(Header = nameof(Resources.DecompileToNewPanel), InputGestureText = "MMB", Icon = "images/Search", Category = nameof(Resources.Analyze), Order = 90)]
@ -53,18 +54,18 @@ namespace ICSharpCode.ILSpy.Commands @@ -53,18 +54,18 @@ namespace ICSharpCode.ILSpy.Commands
{
if (context.SelectedTreeNodes != null)
{
if (context.TreeView != MainWindow.Instance.AssemblyTreeView)
if (context.TreeView.DataContext != MainWindow.Instance.AssemblyTreeModel)
{
return context.SelectedTreeNodes.OfType<IMemberTreeNode>().Select(FindTreeNode).Where(n => n != null);
return context.SelectedTreeNodes.OfType<IMemberTreeNode>().Select(FindTreeNode).ExceptNullItems();
}
else
{
return context.SelectedTreeNodes.OfType<ILSpyTreeNode>().Where(n => n != null);
return context.SelectedTreeNodes.OfType<ILSpyTreeNode>();
}
}
else if (context.Reference?.Reference is IEntity entity)
{
if (MainWindow.Instance.FindTreeNode(entity) is ILSpyTreeNode node)
if (MainWindow.Instance.AssemblyTreeModel.FindTreeNode(entity) is { } node)
{
return new[] { node };
}
@ -75,7 +76,7 @@ namespace ICSharpCode.ILSpy.Commands @@ -75,7 +76,7 @@ namespace ICSharpCode.ILSpy.Commands
{
if (node is ILSpyTreeNode ilspyNode)
return ilspyNode;
return MainWindow.Instance.FindTreeNode(node.Member);
return MainWindow.Instance.AssemblyTreeModel.FindTreeNode(node.Member);
}
}
@ -84,8 +85,9 @@ namespace ICSharpCode.ILSpy.Commands @@ -84,8 +85,9 @@ namespace ICSharpCode.ILSpy.Commands
if (nodes.Length == 0)
return;
MainWindow.Instance.SelectNodes(nodes, inNewTabPage: true);
MainWindow.Instance.Dispatcher.BeginInvoke(DispatcherPriority.Background, (Action)MainWindow.Instance.RefreshDecompiledView);
DockWorkspace.Instance.AddTabPage();
MainWindow.Instance.AssemblyTreeModel.SelectNodes(nodes);
}
}
}

17
ILSpy/Commands/DisassembleAllCommand.cs

@ -26,7 +26,6 @@ using System.Threading.Tasks; @@ -26,7 +26,6 @@ using System.Threading.Tasks;
using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpyX;
namespace ICSharpCode.ILSpy
{
@ -41,12 +40,14 @@ namespace ICSharpCode.ILSpy @@ -41,12 +40,14 @@ namespace ICSharpCode.ILSpy
public override void Execute(object parameter)
{
Docking.DockWorkspace.Instance.RunWithCancellation(ct => Task<AvalonEditTextOutput>.Factory.StartNew(() => {
AvalonEditTextOutput output = new AvalonEditTextOutput();
var dockWorkspace = Docking.DockWorkspace.Instance;
dockWorkspace.RunWithCancellation(ct => Task<AvalonEditTextOutput>.Factory.StartNew(() => {
AvalonEditTextOutput output = new();
Parallel.ForEach(
Partitioner.Create(MainWindow.Instance.CurrentAssemblyList.GetAssemblies(), loadBalance: true),
new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = ct },
delegate (LoadedAssembly asm) {
Partitioner.Create(MainWindow.Instance.AssemblyTreeModel.AssemblyList.GetAssemblies(), loadBalance: true),
new() { MaxDegreeOfParallelism = Environment.ProcessorCount, CancellationToken = ct },
asm => {
if (!asm.HasLoadError)
{
Stopwatch w = Stopwatch.StartNew();
@ -55,7 +56,7 @@ namespace ICSharpCode.ILSpy @@ -55,7 +56,7 @@ namespace ICSharpCode.ILSpy
{
try
{
var options = MainWindow.Instance.CreateDecompilationOptions();
var options = SettingsService.Instance.CreateDecompilationOptions(dockWorkspace.ActiveTabPage);
options.FullDecompilation = true;
options.CancellationToken = ct;
new ILLanguage().DecompileAssembly(asm, new Decompiler.PlainTextOutput(writer), options);
@ -79,7 +80,7 @@ namespace ICSharpCode.ILSpy @@ -79,7 +80,7 @@ namespace ICSharpCode.ILSpy
}
});
return output;
}, ct)).Then(output => Docking.DockWorkspace.Instance.ShowText(output)).HandleExceptions();
}, ct)).Then(dockWorkspace.ShowText).HandleExceptions();
}
}
}

12
ILSpy/Commands/GeneratePdbContextMenuEntry.cs

@ -29,6 +29,7 @@ using ICSharpCode.Decompiler.CSharp; @@ -29,6 +29,7 @@ using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.CSharp.ProjectDecompiler;
using ICSharpCode.Decompiler.DebugInfo;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.Docking;
using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
@ -73,9 +74,10 @@ namespace ICSharpCode.ILSpy @@ -73,9 +74,10 @@ namespace ICSharpCode.ILSpy
dlg.InitialDirectory = Path.GetDirectoryName(assembly.FileName);
if (dlg.ShowDialog() != true)
return;
DecompilationOptions options = MainWindow.Instance.CreateDecompilationOptions();
DockWorkspace dockWorkspace = DockWorkspace.Instance;
DecompilationOptions options = SettingsService.Instance.CreateDecompilationOptions(dockWorkspace.ActiveTabPage);
string fileName = dlg.FileName;
Docking.DockWorkspace.Instance.RunWithCancellation(ct => Task<AvalonEditTextOutput>.Factory.StartNew(() => {
dockWorkspace.RunWithCancellation(ct => Task<AvalonEditTextOutput>.Factory.StartNew(() => {
AvalonEditTextOutput output = new AvalonEditTextOutput();
Stopwatch stopwatch = Stopwatch.StartNew();
options.CancellationToken = ct;
@ -110,14 +112,14 @@ namespace ICSharpCode.ILSpy @@ -110,14 +112,14 @@ namespace ICSharpCode.ILSpy
{
public override bool CanExecute(object parameter)
{
return MainWindow.Instance.SelectedNodes?.Count() == 1
&& MainWindow.Instance.SelectedNodes?.FirstOrDefault() is AssemblyTreeNode tn
return MainWindow.Instance.AssemblyTreeModel.SelectedNodes?.Count() == 1
&& MainWindow.Instance.AssemblyTreeModel.SelectedNodes?.FirstOrDefault() is AssemblyTreeNode tn
&& !tn.LoadedAssembly.HasLoadError;
}
public override void Execute(object parameter)
{
var assembly = (MainWindow.Instance.SelectedNodes?.FirstOrDefault() as AssemblyTreeNode)?.LoadedAssembly;
var assembly = (MainWindow.Instance.AssemblyTreeModel.SelectedNodes?.FirstOrDefault() as AssemblyTreeNode)?.LoadedAssembly;
if (assembly == null)
return;
GeneratePdbContextMenuEntry.GeneratePdbForAssembly(assembly);

24
ILSpy/Commands/OpenCommand.cs

@ -19,8 +19,11 @@ @@ -19,8 +19,11 @@
using System.ComponentModel.Composition;
using System.Windows.Input;
using ICSharpCode.ILSpy.AssemblyTree;
using ICSharpCode.ILSpy.Properties;
using Microsoft.Win32;
namespace ICSharpCode.ILSpy
{
[ExportToolbarCommand(ToolTip = nameof(Resources.Open), ToolbarIcon = "Images/Open", ToolbarCategory = nameof(Resources.Open), ToolbarOrder = 0)]
@ -28,9 +31,28 @@ namespace ICSharpCode.ILSpy @@ -28,9 +31,28 @@ namespace ICSharpCode.ILSpy
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class OpenCommand : CommandWrapper
{
public OpenCommand()
private readonly AssemblyTreeModel assemblyTreeModel;
[ImportingConstructor]
public OpenCommand(AssemblyTreeModel assemblyTreeModel)
: base(ApplicationCommands.Open)
{
this.assemblyTreeModel = assemblyTreeModel;
}
protected override void OnExecute(object sender, ExecutedRoutedEventArgs e)
{
e.Handled = true;
OpenFileDialog dlg = new OpenFileDialog {
Filter = ".NET assemblies|*.dll;*.exe;*.winmd;*.wasm|Nuget Packages (*.nupkg)|*.nupkg|Portable Program Database (*.pdb)|*.pdb|All files|*.*",
Multiselect = true,
RestoreDirectory = true
};
if (dlg.ShowDialog() == true)
{
assemblyTreeModel.OpenFiles(dlg.FileNames);
}
}
}
}

19
ILSpy/Commands/OpenFromGacCommand.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System.ComponentModel.Composition;
using ICSharpCode.ILSpy.AppEnv;
using ICSharpCode.ILSpy.AssemblyTree;
using ICSharpCode.ILSpy.Properties;
namespace ICSharpCode.ILSpy
@ -27,6 +28,14 @@ namespace ICSharpCode.ILSpy @@ -27,6 +28,14 @@ namespace ICSharpCode.ILSpy
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class OpenFromGacCommand : SimpleCommand
{
private readonly AssemblyTreeModel assemblyTreeModel;
[ImportingConstructor]
public OpenFromGacCommand(AssemblyTreeModel assemblyTreeModel)
{
this.assemblyTreeModel = assemblyTreeModel;
}
public override bool CanExecute(object parameter)
{
return AppEnvironment.IsWindows;
@ -34,10 +43,14 @@ namespace ICSharpCode.ILSpy @@ -34,10 +43,14 @@ namespace ICSharpCode.ILSpy
public override void Execute(object parameter)
{
OpenFromGacDialog dlg = new OpenFromGacDialog();
dlg.Owner = MainWindow.Instance;
OpenFromGacDialog dlg = new OpenFromGacDialog {
Owner = MainWindow.Instance
};
if (dlg.ShowDialog() == true)
MainWindow.Instance.OpenFiles(dlg.SelectedFileNames);
{
assemblyTreeModel.OpenFiles(dlg.SelectedFileNames);
}
}
}
}

4
ILSpy/Commands/Pdb2XmlCommand.cs

@ -40,14 +40,14 @@ namespace ICSharpCode.ILSpy @@ -40,14 +40,14 @@ namespace ICSharpCode.ILSpy
{
public override bool CanExecute(object parameter)
{
var selectedNodes = MainWindow.Instance.SelectedNodes;
var selectedNodes = MainWindow.Instance.AssemblyTreeModel.SelectedNodes;
return selectedNodes?.Any() == true
&& selectedNodes.All(n => n is AssemblyTreeNode asm && !asm.LoadedAssembly.HasLoadError);
}
public override void Execute(object parameter)
{
Execute(MainWindow.Instance.SelectedNodes.OfType<AssemblyTreeNode>());
Execute(MainWindow.Instance.AssemblyTreeModel.SelectedNodes.OfType<AssemblyTreeNode>());
}
internal static void Execute(IEnumerable<AssemblyTreeNode> nodes)

12
ILSpy/Commands/RefreshCommand.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System.ComponentModel.Composition;
using System.Windows.Input;
using ICSharpCode.ILSpy.AssemblyTree;
using ICSharpCode.ILSpy.Properties;
namespace ICSharpCode.ILSpy
@ -28,9 +29,18 @@ namespace ICSharpCode.ILSpy @@ -28,9 +29,18 @@ namespace ICSharpCode.ILSpy
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class RefreshCommand : CommandWrapper
{
public RefreshCommand()
private readonly AssemblyTreeModel assemblyTreeModel;
[ImportingConstructor]
public RefreshCommand(AssemblyTreeModel assemblyTreeModel)
: base(NavigationCommands.Refresh)
{
this.assemblyTreeModel = assemblyTreeModel;
}
protected override void OnExecute(object sender, ExecutedRoutedEventArgs e)
{
assemblyTreeModel.Refresh();
}
}
}

10
ILSpy/Commands/RemoveAssembliesWithLoadErrors.cs

@ -29,16 +29,16 @@ namespace ICSharpCode.ILSpy @@ -29,16 +29,16 @@ namespace ICSharpCode.ILSpy
{
public override bool CanExecute(object parameter)
{
return MainWindow.Instance.CurrentAssemblyList?.GetAssemblies().Any(l => l.HasLoadError) == true;
return MainWindow.Instance.AssemblyTreeModel.AssemblyList?.GetAssemblies().Any(l => l.HasLoadError) == true;
}
public override void Execute(object parameter)
{
foreach (var asm in MainWindow.Instance.CurrentAssemblyList.GetAssemblies())
foreach (var asm in MainWindow.Instance.AssemblyTreeModel.AssemblyList.GetAssemblies())
{
if (!asm.HasLoadError)
continue;
var node = MainWindow.Instance.AssemblyListTreeNode.FindAssemblyNode(asm);
var node = MainWindow.Instance.AssemblyTreeModel.FindAssemblyNode(asm);
if (node != null && node.CanDelete())
node.Delete();
}
@ -51,12 +51,12 @@ namespace ICSharpCode.ILSpy @@ -51,12 +51,12 @@ namespace ICSharpCode.ILSpy
{
public override bool CanExecute(object parameter)
{
return MainWindow.Instance.CurrentAssemblyList?.Count > 0;
return MainWindow.Instance.AssemblyTreeModel.AssemblyList?.Count > 0;
}
public override void Execute(object parameter)
{
MainWindow.Instance.CurrentAssemblyList?.Clear();
MainWindow.Instance.AssemblyTreeModel.AssemblyList?.Clear();
}
}
}

12
ILSpy/Commands/SaveCodeContextMenuEntry.cs

@ -32,7 +32,8 @@ using Microsoft.Win32; @@ -32,7 +32,8 @@ using Microsoft.Win32;
using ICSharpCode.ILSpyX.TreeView;
using System.ComponentModel.Composition;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpy.Docking;
namespace ICSharpCode.ILSpy.TextView
{
@ -62,8 +63,11 @@ namespace ICSharpCode.ILSpy.TextView @@ -62,8 +63,11 @@ namespace ICSharpCode.ILSpy.TextView
public static void Execute(IReadOnlyList<SharpTreeNode> selectedNodes)
{
var currentLanguage = SettingsService.Instance.SessionSettings.LanguageSettings.Language;
var tabPage = Docking.DockWorkspace.Instance.ActiveTabPage;
var settingsService = SettingsService.Instance;
var dockWorkspace = Docking.DockWorkspace.Instance;
var currentLanguage = settingsService.SessionSettings.LanguageSettings.Language;
var tabPage = dockWorkspace.ActiveTabPage;
tabPage.ShowTextView(textView => {
if (selectedNodes.Count == 1 && selectedNodes[0] is ILSpyTreeNode singleSelection)
{
@ -88,7 +92,7 @@ namespace ICSharpCode.ILSpy.TextView @@ -88,7 +92,7 @@ namespace ICSharpCode.ILSpy.TextView
// Fallback: if nobody was able to handle the request, use default behavior.
// try to save all nodes to disk.
var options = MainWindow.Instance.CreateDecompilationOptions();
var options = settingsService.CreateDecompilationOptions(dockWorkspace.ActiveTabPage);
options.FullDecompilation = true;
textView.SaveToDisk(currentLanguage, selectedNodes.OfType<ILSpyTreeNode>(), options);
});

20
ILSpy/Commands/SaveCommand.cs

@ -17,9 +17,12 @@ @@ -17,9 +17,12 @@
// DEALINGS IN THE SOFTWARE.
using System.ComponentModel.Composition;
using System.Linq;
using System.Windows.Input;
using ICSharpCode.ILSpy.AssemblyTree;
using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpy.TextView;
namespace ICSharpCode.ILSpy
{
@ -27,9 +30,24 @@ namespace ICSharpCode.ILSpy @@ -27,9 +30,24 @@ namespace ICSharpCode.ILSpy
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class SaveCommand : CommandWrapper
{
public SaveCommand()
private AssemblyTreeModel assemblyTreeModel;
[ImportingConstructor]
public SaveCommand(AssemblyTreeModel assemblyTreeModel)
: base(ApplicationCommands.Save)
{
this.assemblyTreeModel = assemblyTreeModel;
}
protected override void OnCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
e.Handled = true;
e.CanExecute = SaveCodeContextMenuEntry.CanExecute(assemblyTreeModel.SelectedNodes.ToList());
}
protected override void OnExecute(object sender, ExecutedRoutedEventArgs e)
{
SaveCodeContextMenuEntry.Execute(assemblyTreeModel.SelectedNodes.ToList());
}
}
}

6
ILSpy/Commands/SelectPdbContextMenuEntry.cs

@ -48,10 +48,10 @@ namespace ICSharpCode.ILSpy @@ -48,10 +48,10 @@ namespace ICSharpCode.ILSpy
await assembly.LoadDebugInfo(dlg.FileName);
}
var node = (AssemblyTreeNode)MainWindow.Instance.FindNodeByPath(new[] { assembly.FileName }, true);
var node = (AssemblyTreeNode)MainWindow.Instance.AssemblyTreeModel.FindNodeByPath(new[] { assembly.FileName }, true);
node.UpdateToolTip();
MainWindow.Instance.SelectNode(node);
MainWindow.Instance.RefreshDecompiledView();
MainWindow.Instance.AssemblyTreeModel.SelectNode(node);
MainWindow.Instance.AssemblyTreeModel.RefreshDecompiledView();
}
public bool IsEnabled(TextViewContext context) => true;

5
ILSpy/Commands/SetThemeCommand.cs

@ -1,5 +1,4 @@ @@ -1,5 +1,4 @@
using ICSharpCode.ILSpy.Util;

namespace ICSharpCode.ILSpy.Commands
{
public class SetThemeCommand : SimpleCommand
@ -7,7 +6,9 @@ namespace ICSharpCode.ILSpy.Commands @@ -7,7 +6,9 @@ namespace ICSharpCode.ILSpy.Commands
public override void Execute(object parameter)
{
if (parameter is string theme)
{
SettingsService.Instance.SessionSettings.Theme = theme;
}
}
}
}

1
ILSpy/Commands/ShowCFGContextMenuEntry.cs

@ -6,7 +6,6 @@ using System.Windows; @@ -6,7 +6,6 @@ using System.Windows;
using ICSharpCode.Decompiler.FlowAnalysis;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.IL.ControlFlow;
using ICSharpCode.ILSpy.Util;
namespace ICSharpCode.ILSpy.Commands
{

23
ILSpy/Commands/SortAssemblyListCommand.cs

@ -29,17 +29,11 @@ namespace ICSharpCode.ILSpy @@ -29,17 +29,11 @@ namespace ICSharpCode.ILSpy
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._View), Header = nameof(Resources.SortAssembly_listName), MenuIcon = "Images/Sort", MenuCategory = nameof(Resources.View))]
[ExportToolbarCommand(ToolTip = nameof(Resources.SortAssemblyListName), ToolbarIcon = "Images/Sort", ToolbarCategory = nameof(Resources.View))]
[PartCreationPolicy(CreationPolicy.Shared)]
sealed class SortAssemblyListCommand : SimpleCommand, IComparer<LoadedAssembly>
sealed class SortAssemblyListCommand : SimpleCommand
{
public override void Execute(object parameter)
{
using (MainWindow.Instance.AssemblyTreeView.LockUpdates())
MainWindow.Instance.CurrentAssemblyList.Sort(this);
}
int IComparer<LoadedAssembly>.Compare(LoadedAssembly x, LoadedAssembly y)
{
return string.Compare(x.ShortName, y.ShortName, StringComparison.CurrentCulture);
MainWindow.Instance.AssemblyTreeModel.SortAssemblyList();
}
}
@ -50,19 +44,8 @@ namespace ICSharpCode.ILSpy @@ -50,19 +44,8 @@ namespace ICSharpCode.ILSpy
{
public override void Execute(object parameter)
{
using (MainWindow.Instance.AssemblyTreeView.LockUpdates())
CollapseChildren(MainWindow.Instance.AssemblyTreeView.Root);
MainWindow.Instance.AssemblyTreeModel.CollapseAll();
void CollapseChildren(SharpTreeNode node)
{
foreach (var child in node.Children)
{
if (!child.IsExpanded)
continue;
CollapseChildren(child);
child.IsExpanded = false;
}
}
}
}
}

105
ILSpy/ContextMenuEntry.cs

@ -22,8 +22,6 @@ using System.ComponentModel.Composition; @@ -22,8 +22,6 @@ using System.ComponentModel.Composition;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.AvalonEdit;
using ICSharpCode.ILSpy.TextView;
@ -32,6 +30,7 @@ using ICSharpCode.ILSpy.Controls.TreeView; @@ -32,6 +30,7 @@ using ICSharpCode.ILSpy.Controls.TreeView;
using ICSharpCode.ILSpyX.TreeView;
using TomsToolbox.Composition;
using TomsToolbox.Essentials;
namespace ICSharpCode.ILSpy
{
@ -86,36 +85,40 @@ namespace ICSharpCode.ILSpy @@ -86,36 +85,40 @@ namespace ICSharpCode.ILSpy
/// </summary>
public TextViewPosition? Position { get; private set; }
public Point MousePosition { get; private set; }
/// <summary>
/// Returns the original source of the context menu event.
/// </summary>
public DependencyObject OriginalSource { get; private set; }
public static TextViewContext Create(SharpTreeView treeView = null, DecompilerTextView textView = null, ListBox listBox = null, DataGrid dataGrid = null)
public static TextViewContext Create(ContextMenuEventArgs eventArgs, SharpTreeView treeView = null, DecompilerTextView textView = null, ListBox listBox = null, DataGrid dataGrid = null)
{
ReferenceSegment reference;
if (textView != null)
if (textView is not null)
{
reference = textView.GetReferenceSegmentAtMousePosition();
else if (listBox?.SelectedItem is SearchResult result)
reference = new ReferenceSegment { Reference = result.Reference };
else if (listBox?.SelectedItem is TreeNodes.IMemberTreeNode provider)
reference = new ReferenceSegment { Reference = provider.Member };
else if (listBox?.SelectedItem != null)
reference = new ReferenceSegment { Reference = listBox.SelectedItem };
else if (dataGrid?.SelectedItem is TreeNodes.IMemberTreeNode provider2)
reference = new ReferenceSegment { Reference = provider2.Member };
else if (dataGrid?.SelectedItem != null)
reference = new ReferenceSegment { Reference = dataGrid.SelectedItem };
}
else
reference = null;
var position = textView != null ? textView.GetPositionFromMousePosition() : null;
var selectedTreeNodes = treeView != null ? treeView.GetTopLevelSelection().ToArray() : null;
return new TextViewContext {
{
reference = (listBox?.SelectedItem ?? dataGrid?.SelectedItem) switch {
SearchResult searchResult => new() { Reference = searchResult.Reference },
TreeNodes.IMemberTreeNode treeNode => new() { Reference = treeNode.Member }, { } value => new() { Reference = value },
_ => null
};
}
var position = textView?.GetPositionFromMousePosition();
var selectedTreeNodes = treeView?.GetTopLevelSelection().ToArray();
return new() {
ListBox = listBox,
DataGrid = dataGrid,
TreeView = treeView,
SelectedTreeNodes = selectedTreeNodes,
TextView = textView,
SelectedTreeNodes = selectedTreeNodes,
Reference = reference,
Position = position,
MousePosition = ((Visual)textView ?? treeView ?? (Visual)listBox ?? dataGrid).PointToScreen(Mouse.GetPosition((IInputElement)textView ?? treeView ?? (IInputElement)listBox ?? dataGrid))
OriginalSource = eventArgs.OriginalSource as DependencyObject
};
}
}
@ -168,6 +171,13 @@ namespace ICSharpCode.ILSpy @@ -168,6 +171,13 @@ namespace ICSharpCode.ILSpy
internal class ContextMenuProvider
{
private static readonly WeakEventSource<EventArgs> ContextMenuClosedEventSource = new();
public static event EventHandler<EventArgs> ContextMenuClosed {
add => ContextMenuClosedEventSource.Subscribe(value);
remove => ContextMenuClosedEventSource.Unsubscribe(value);
}
/// <summary>
/// Enables extensible context menu support for the specified tree view.
/// </summary>
@ -203,51 +213,54 @@ namespace ICSharpCode.ILSpy @@ -203,51 +213,54 @@ namespace ICSharpCode.ILSpy
dataGrid.ContextMenu = new ContextMenu();
}
readonly Control control;
readonly SharpTreeView treeView;
readonly DecompilerTextView textView;
readonly ListBox listBox;
readonly DataGrid dataGrid;
readonly IExport<IContextMenuEntry, IContextMenuEntryMetadata>[] entries;
private ContextMenuProvider()
private ContextMenuProvider(Control control)
{
entries = App.ExportProvider.GetExports<IContextMenuEntry, IContextMenuEntryMetadata>().ToArray();
this.control = control;
}
ContextMenuProvider(DecompilerTextView textView)
: this()
: this((Control)textView)
{
this.textView = textView ?? throw new ArgumentNullException(nameof(textView));
}
ContextMenuProvider(SharpTreeView treeView)
: this()
: this((Control)treeView)
{
this.treeView = treeView ?? throw new ArgumentNullException(nameof(treeView));
}
ContextMenuProvider(ListBox listBox)
: this()
: this((Control)listBox)
{
this.listBox = listBox ?? throw new ArgumentNullException(nameof(listBox));
}
ContextMenuProvider(DataGrid dataGrid)
: this()
: this((Control)dataGrid)
{
this.dataGrid = dataGrid ?? throw new ArgumentNullException(nameof(dataGrid));
}
void treeView_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
TextViewContext context = TextViewContext.Create(treeView);
var context = TextViewContext.Create(e, treeView: treeView);
if (context.SelectedTreeNodes.Length == 0)
{
e.Handled = true; // don't show the menu
return;
}
ContextMenu menu;
if (ShowContextMenu(context, out menu))
if (ShowContextMenu(context, out var menu))
treeView.ContextMenu = menu;
else
// hide the context menu.
@ -256,9 +269,8 @@ namespace ICSharpCode.ILSpy @@ -256,9 +269,8 @@ namespace ICSharpCode.ILSpy
void textView_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
TextViewContext context = TextViewContext.Create(textView: textView);
ContextMenu menu;
if (ShowContextMenu(context, out menu))
var context = TextViewContext.Create(e, textView: textView);
if (ShowContextMenu(context, out var menu))
textView.ContextMenu = menu;
else
// hide the context menu.
@ -267,9 +279,8 @@ namespace ICSharpCode.ILSpy @@ -267,9 +279,8 @@ namespace ICSharpCode.ILSpy
void listBox_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
TextViewContext context = TextViewContext.Create(listBox: listBox);
ContextMenu menu;
if (ShowContextMenu(context, out menu))
var context = TextViewContext.Create(e, listBox: listBox);
if (ShowContextMenu(context, out var menu))
listBox.ContextMenu = menu;
else
// hide the context menu.
@ -278,9 +289,8 @@ namespace ICSharpCode.ILSpy @@ -278,9 +289,8 @@ namespace ICSharpCode.ILSpy
void dataGrid_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
TextViewContext context = TextViewContext.Create(dataGrid: dataGrid);
ContextMenu menu;
if (ShowContextMenu(context, out menu))
var context = TextViewContext.Create(e, dataGrid: dataGrid);
if (ShowContextMenu(context, out var menu))
dataGrid.ContextMenu = menu;
else
// hide the context menu.
@ -289,7 +299,18 @@ namespace ICSharpCode.ILSpy @@ -289,7 +299,18 @@ namespace ICSharpCode.ILSpy
bool ShowContextMenu(TextViewContext context, out ContextMenu menu)
{
// Closing event is raised on the control where mouse is clicked, not on the control that opened the menu, so we hook on the global window event.
var window = Window.GetWindow(control)!;
window.ContextMenuClosing += ContextMenu_Closing;
void ContextMenu_Closing(object sender, EventArgs e)
{
window.ContextMenuClosing -= ContextMenu_Closing;
ContextMenuClosedEventSource.Raise(this, EventArgs.Empty);
}
menu = new ContextMenu();
var menuGroups = new Dictionary<string, IExport<IContextMenuEntry, IContextMenuEntryMetadata>[]>();
IExport<IContextMenuEntry, IContextMenuEntryMetadata>[] topLevelGroup = null;
foreach (var group in entries.OrderBy(c => c.Metadata.Order).GroupBy(c => c.Metadata.ParentMenuID))
@ -310,10 +331,10 @@ namespace ICSharpCode.ILSpy @@ -310,10 +331,10 @@ namespace ICSharpCode.ILSpy
{
foreach (var category in menuGroup.GroupBy(c => c.Metadata.Category))
{
bool needSeparatorForCategory = parent.Count > 0;
var needSeparatorForCategory = parent.Count > 0;
foreach (var entryPair in category)
{
IContextMenuEntry entry = entryPair.Value;
var entry = entryPair.Value;
if (entry.IsVisible(context))
{
if (needSeparatorForCategory)
@ -321,8 +342,8 @@ namespace ICSharpCode.ILSpy @@ -321,8 +342,8 @@ namespace ICSharpCode.ILSpy
parent.Add(new Separator());
needSeparatorForCategory = false;
}
MenuItem menuItem = new MenuItem();
menuItem.Header = MainWindow.GetResourceString(entryPair.Metadata.Header);
var menuItem = new MenuItem();
menuItem.Header = ResourceHelper.GetString(entryPair.Metadata.Header);
menuItem.InputGestureText = entryPair.Metadata.InputGestureText;
if (!string.IsNullOrEmpty(entryPair.Metadata.Icon))
{

7
ILSpy/Controls/TreeView/SharpTreeView.cs

@ -158,6 +158,7 @@ namespace ICSharpCode.ILSpy.Controls.TreeView @@ -158,6 +158,7 @@ namespace ICSharpCode.ILSpy.Controls.TreeView
if (flattener != null)
{
flattener.Stop();
flattener.CollectionChanged -= flattener_CollectionChanged;
}
if (Root != null)
{
@ -818,9 +819,9 @@ namespace ICSharpCode.ILSpy.Controls.TreeView @@ -818,9 +819,9 @@ namespace ICSharpCode.ILSpy.Controls.TreeView
/// </summary>
public IEnumerable<SharpTreeNode> GetTopLevelSelection()
{
var selection = this.SelectedItems.OfType<SharpTreeNode>();
var selectionHash = new HashSet<SharpTreeNode>(selection);
return selection.Where(item => item.Ancestors().All(a => !selectionHash.Contains(a)));
var selection = this.SelectedItems.OfType<SharpTreeNode>().ToHashSet();
return selection.Where(item => item.Ancestors().All(a => !selection.Contains(a)));
}
#endregion

4
ILSpy/DecompilationOptions.cs

@ -23,6 +23,8 @@ using ICSharpCode.Decompiler; @@ -23,6 +23,8 @@ using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy.Options;
using ICSharpCode.ILSpyX;
using DecompilerSettings = ICSharpCode.ILSpy.Options.DecompilerSettings;
namespace ICSharpCode.ILSpy
{
/// <summary>
@ -87,7 +89,9 @@ namespace ICSharpCode.ILSpy @@ -87,7 +89,9 @@ namespace ICSharpCode.ILSpy
{
if (!Enum.TryParse(version?.Version, out Decompiler.CSharp.LanguageVersion languageVersion))
languageVersion = Decompiler.CSharp.LanguageVersion.Latest;
var newSettings = this.DecompilerSettings = settings.Clone();
newSettings.SetLanguageVersion(languageVersion);
newSettings.ExpandMemberDefinitions = displaySettings.ExpandMemberDefinitions;
newSettings.ExpandUsingDeclarations = displaySettings.ExpandUsingDeclarations;

1
ILSpy/Docking/DockLayoutSettings.cs

@ -19,7 +19,6 @@ @@ -19,7 +19,6 @@
using System;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using AvalonDock.Layout.Serialization;

94
ILSpy/Docking/DockWorkspace.cs

@ -33,9 +33,11 @@ using ICSharpCode.AvalonEdit.Highlighting; @@ -33,9 +33,11 @@ using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.ILSpy.Analyzers;
using ICSharpCode.ILSpy.Search;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpy.ViewModels;
using ICSharpCode.ILSpyX.Extensions;
using TomsToolbox.Composition;
using TomsToolbox.Essentials;
using TomsToolbox.Wpf;
namespace ICSharpCode.ILSpy.Docking
@ -44,11 +46,22 @@ namespace ICSharpCode.ILSpy.Docking @@ -44,11 +46,22 @@ namespace ICSharpCode.ILSpy.Docking
{
private static SessionSettings SessionSettings => SettingsService.Instance.SessionSettings;
private readonly IExportProvider exportProvider = App.ExportProvider;
public static readonly DockWorkspace Instance = new();
private readonly ObservableCollection<TabPageModel> tabPages = [];
private readonly ObservableCollection<ToolPaneModel> toolPanes = [];
private DockWorkspace()
{
this.TabPages.CollectionChanged += Documents_CollectionChanged;
this.tabPages.CollectionChanged += TabPages_CollectionChanged;
TabPages = new(tabPages);
ToolPanes = new(toolPanes);
// Make sure there is at least one tab open
AddTabPage();
MessageBus<CurrentAssemblyListChangedEventArgs>.Subscribers += (sender, e) => CurrentAssemblyList_Changed(sender, e);
}
@ -58,52 +71,57 @@ namespace ICSharpCode.ILSpy.Docking @@ -58,52 +71,57 @@ namespace ICSharpCode.ILSpy.Docking
{
return;
}
foreach (var tab in TabPages.ToArray())
foreach (var tab in tabPages.ToArray())
{
var state = tab.GetState();
if (state == null || state.DecompiledNodes == null)
{
var decompiledNodes = state?.DecompiledNodes;
if (decompiledNodes == null)
continue;
}
bool found = false;
foreach (var node in state.DecompiledNodes)
{
var assemblyNode = node.Ancestors().OfType<TreeNodes.AssemblyTreeNode>().LastOrDefault();
if (assemblyNode != null && !e.OldItems.Contains(assemblyNode.LoadedAssembly))
{
found = true;
break;
}
}
if (!found && TabPages.Count > 1)
bool found = decompiledNodes
.Select(node => node.Ancestors().OfType<TreeNodes.AssemblyTreeNode>().LastOrDefault())
.ExceptNullItems()
.Any(assemblyNode => !e.OldItems.Contains(assemblyNode.LoadedAssembly));
if (!found && tabPages.Count > 1)
{
TabPages.Remove(tab);
tabPages.Remove(tab);
}
}
}
private void Documents_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
private void TabPages_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
var collection = (PaneCollection<TabPageModel>)sender;
if (e.Action == NotifyCollectionChangedAction.Add)
{
ActiveTabPage = e.NewItems?[0] as TabPageModel;
if (e.NewItems?[0] is TabPageModel model)
{
ActiveTabPage = model;
model.IsActive = true;
model.IsVisible = true;
}
}
bool canClose = collection.Count > 1;
foreach (var item in collection)
bool canClose = tabPages.Count > 1;
foreach (var item in tabPages)
{
item.IsCloseable = canClose;
}
}
public PaneCollection<TabPageModel> TabPages { get; } = new PaneCollection<TabPageModel>();
public void AddTabPage(TabPageModel tabPage = null)
{
tabPages.Add(tabPage ?? new TabPageModel());
}
public ReadOnlyObservableCollection<TabPageModel> TabPages { get; }
public ObservableCollection<ToolPaneModel> ToolPanes { get; } = new ObservableCollection<ToolPaneModel>();
public ReadOnlyObservableCollection<ToolPaneModel> ToolPanes { get; }
public bool ShowToolPane(string contentId)
{
var pane = ToolPanes.FirstOrDefault(p => p.ContentId == contentId);
var pane = toolPanes.FirstOrDefault(p => p.ContentId == contentId);
if (pane != null)
{
pane.Show();
@ -115,7 +133,7 @@ namespace ICSharpCode.ILSpy.Docking @@ -115,7 +133,7 @@ namespace ICSharpCode.ILSpy.Docking
public void Remove(PaneModel model)
{
if (model is TabPageModel document)
TabPages.Remove(document);
tabPages.Remove(document);
if (model is ToolPaneModel tool)
tool.IsVisible = false;
}
@ -131,25 +149,27 @@ namespace ICSharpCode.ILSpy.Docking @@ -131,25 +149,27 @@ namespace ICSharpCode.ILSpy.Docking
return;
}
var state = value.GetState();
var state = value?.GetState();
if (state != null)
{
if (state.DecompiledNodes != null)
{
MainWindow.Instance.SelectNodes(state.DecompiledNodes,
inNewTabPage: false, setFocus: true, changingActiveTab: true);
MainWindow.Instance.AssemblyTreeModel.SelectNodes(state.DecompiledNodes);
}
else
{
MainWindow.Instance.NavigateTo(new(state.ViewedUri, null));
MainWindow.Instance.AssemblyTreeModel.NavigateTo(new(state.ViewedUri, null));
}
}
MessageBus.Send(this, new DockWorkspaceActiveTabPageChangedEventArgs());
}
}
public void InitializeLayout(DockingManager manager)
{
var panes = exportProvider.GetExportedValues<ToolPaneModel>("ToolPane").OrderBy(item => item.Title);
this.toolPanes.AddRange(panes);
manager.LayoutUpdateStrategy = this;
XmlLayoutSerializer serializer = new XmlLayoutSerializer(manager);
serializer.LayoutSerializationCallback += LayoutSerializationCallback;
@ -168,7 +188,7 @@ namespace ICSharpCode.ILSpy.Docking @@ -168,7 +188,7 @@ namespace ICSharpCode.ILSpy.Docking
switch (e.Model)
{
case LayoutAnchorable la:
e.Content = ToolPanes.FirstOrDefault(p => p.ContentId == la.ContentId);
e.Content = this.toolPanes.FirstOrDefault(p => p.ContentId == la.ContentId);
e.Cancel = e.Content == null;
la.CanDockAsTabbedDocument = false;
if (!e.Cancel)
@ -200,23 +220,23 @@ namespace ICSharpCode.ILSpy.Docking @@ -200,23 +220,23 @@ namespace ICSharpCode.ILSpy.Docking
internal void CloseAllTabs()
{
foreach (var doc in TabPages.ToArray())
foreach (var doc in tabPages.ToArray())
{
if (doc.IsCloseable)
TabPages.Remove(doc);
tabPages.Remove(doc);
}
}
internal void ResetLayout()
{
foreach (var pane in ToolPanes)
foreach (var pane in toolPanes)
{
pane.IsVisible = false;
}
CloseAllTabs();
SessionSettings.DockLayout.Reset();
InitializeLayout(MainWindow.Instance.dockManager);
MainWindow.Instance.Dispatcher.BeginInvoke(DispatcherPriority.Background, (Action)MainWindow.Instance.RefreshDecompiledView);
MainWindow.Instance.Dispatcher.BeginInvoke(DispatcherPriority.Background, (Action)MainWindow.Instance.AssemblyTreeModel.RefreshDecompiledView);
}
static readonly PropertyInfo previousContainerProperty = typeof(LayoutContent).GetProperty("PreviousContainer", BindingFlags.NonPublic | BindingFlags.Instance);

59
ILSpy/Docking/PaneCollection.cs

@ -1,59 +0,0 @@ @@ -1,59 +0,0 @@
// Copyright (c) 2019 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
// 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;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using ICSharpCode.ILSpy.ViewModels;
namespace ICSharpCode.ILSpy.Docking
{
public class PaneCollection<T> : INotifyCollectionChanged, ICollection<T>
where T : PaneModel, new()
{
private ObservableCollection<T> observableCollection = new ObservableCollection<T>();
public event NotifyCollectionChangedEventHandler CollectionChanged;
public PaneCollection()
{
observableCollection.CollectionChanged += (sender, e) => CollectionChanged?.Invoke(this, e);
}
public void Add(T item = null)
{
item ??= new T();
observableCollection.Add(item);
item.IsVisible = true;
item.IsActive = true;
}
public int Count => observableCollection.Count;
public bool IsReadOnly => false;
public void Clear() => observableCollection.Clear();
public bool Contains(T item) => observableCollection.Contains(item);
public void CopyTo(T[] array, int arrayIndex) => observableCollection.CopyTo(array, arrayIndex);
public bool Remove(T item) => observableCollection.Remove(item);
public IEnumerator<T> GetEnumerator() => observableCollection.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => observableCollection.GetEnumerator();
}
}

30
ILSpy/ExtensionMethods.cs

@ -27,9 +27,10 @@ using System.Windows.Media; @@ -27,9 +27,10 @@ using System.Windows.Media;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX;
using TomsToolbox.Essentials;
namespace ICSharpCode.ILSpy
{
/// <summary>
@ -125,9 +126,9 @@ namespace ICSharpCode.ILSpy @@ -125,9 +126,9 @@ namespace ICSharpCode.ILSpy
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
if (child != null && child is T)
if (child is T dependencyObject)
{
return (T)child;
return dependencyObject;
}
T? childItem = FindVisualChild<T>(child);
@ -178,20 +179,37 @@ namespace ICSharpCode.ILSpy @@ -178,20 +179,37 @@ namespace ICSharpCode.ILSpy
else
output.AppendLine("-------------------------------------------------");
output.AppendLine("Error(s) loading plugin: " + item.PluginName);
if (item.Exception is System.Reflection.ReflectionTypeLoadException)
if (item.Exception is System.Reflection.ReflectionTypeLoadException exception)
{
var e = (System.Reflection.ReflectionTypeLoadException)item.Exception;
foreach (var ex in e.LoaderExceptions)
foreach (var ex in exception.LoaderExceptions.ExceptNullItems())
{
output.AppendLine(ex.ToString());
output.AppendLine();
}
}
else
{
output.AppendLine(item.Exception.ToString());
}
}
return true;
}
public static IDisposable PreserveFocus(this IInputElement? inputElement, bool preserve = true)
{
return new RestoreFocusHelper(inputElement, preserve);
}
private sealed class RestoreFocusHelper(IInputElement? inputElement, bool preserve) : IDisposable
{
public void Dispose()
{
if (preserve)
{
inputElement?.Focus();
}
}
}
}
}

1
ILSpy/GlobalUsings.cs

@ -0,0 +1 @@ @@ -0,0 +1 @@
global using ICSharpCode.ILSpy.Util;

3
ILSpy/ILSpy.csproj

@ -1,5 +1,4 @@ @@ -1,5 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>

27
ILSpy/LanguageSettings.cs

@ -16,22 +16,20 @@ @@ -16,22 +16,20 @@
// 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.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Xml.Linq;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX;
using TomsToolbox.Wpf;
namespace ICSharpCode.ILSpy
{
/// <summary>
/// Represents the filters applied to the tree view.
/// </summary>
public class LanguageSettings : INotifyPropertyChanged
public class LanguageSettings : ObservableObject, IChildSettings
{
/// <summary>
/// This dictionary is necessary to remember language versions across language changes. For example,
@ -40,14 +38,17 @@ namespace ICSharpCode.ILSpy @@ -40,14 +38,17 @@ namespace ICSharpCode.ILSpy
/// </summary>
private readonly Dictionary<Language, LanguageVersion> languageVersionHistory = new Dictionary<Language, LanguageVersion>();
public LanguageSettings(XElement element)
public LanguageSettings(XElement element, ISettingsSection parent)
{
Parent = parent;
this.ShowApiLevel = (ApiVisibility?)(int?)element.Element("ShowAPILevel") ?? ApiVisibility.PublicAndInternal;
this.Language = Languages.GetLanguage((string)element.Element("Language")) ?? Languages.AllLanguages.First();
this.LanguageVersion = Language.LanguageVersions.FirstOrDefault(v => v.Version == (string)element.Element("LanguageVersion"))
?? Language.LanguageVersions.LastOrDefault();
}
public ISettingsSection Parent { get; }
public XElement SaveAsXml()
{
return new XElement(
@ -173,20 +174,6 @@ namespace ICSharpCode.ILSpy @@ -173,20 +174,6 @@ namespace ICSharpCode.ILSpy
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
if (PropertyChanged != null)
{
var args = new PropertyChangedEventArgs(propertyName);
PropertyChanged(this, args);
MessageBus.Send(this, new LanguageSettingsChangedEventArgs(args));
}
}
// This class has been initially called FilterSettings, but then has been Hijacked to store language settings as well.
// While the filter settings were some sort of local, the language settings are global. This is a bit of a mess.
// There has been a lot of workarounds cloning the FilterSettings to pass them down to the tree nodes, without messing up the global language settings.

1
ILSpy/Languages/CSharpILMixedLanguage.cs

@ -34,7 +34,6 @@ using ICSharpCode.Decompiler.Disassembler; @@ -34,7 +34,6 @@ using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX;
using ICSharpCode.ILSpyX.Extensions;

7
ILSpy/Languages/CSharpLanguage.cs

@ -41,7 +41,6 @@ using ICSharpCode.Decompiler.TypeSystem; @@ -41,7 +41,6 @@ using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX;
using LanguageVersion = ICSharpCode.ILSpyX.LanguageVersion;
@ -359,15 +358,15 @@ namespace ICSharpCode.ILSpy @@ -359,15 +358,15 @@ namespace ICSharpCode.ILSpy
void AddReferenceWarningMessage(MetadataFile module, ITextOutput output)
{
var loadedAssembly = MainWindow.Instance.CurrentAssemblyList.GetAssemblies().FirstOrDefault(la => la.GetMetadataFileOrNull() == module);
var loadedAssembly = MainWindow.Instance.AssemblyTreeModel.AssemblyList.GetAssemblies().FirstOrDefault(la => la.GetMetadataFileOrNull() == module);
if (loadedAssembly == null || !loadedAssembly.LoadedAssemblyReferencesInfo.HasErrors)
return;
string line1 = Properties.Resources.WarningSomeAssemblyReference;
string line2 = Properties.Resources.PropertyManuallyMissingReferencesListLoadedAssemblies;
AddWarningMessage(module, output, line1, line2, Properties.Resources.ShowAssemblyLoad, Images.ViewCode, delegate {
ILSpyTreeNode assemblyNode = MainWindow.Instance.FindTreeNode(module);
ILSpyTreeNode assemblyNode = MainWindow.Instance.AssemblyTreeModel.FindTreeNode(module);
assemblyNode.EnsureLazyChildren();
MainWindow.Instance.SelectNode(assemblyNode.Children.OfType<ReferenceFolderTreeNode>().Single());
MainWindow.Instance.AssemblyTreeModel.SelectNode(assemblyNode.Children.OfType<ReferenceFolderTreeNode>().Single());
});
}

7
ILSpy/Languages/ILLanguage.cs

@ -29,8 +29,8 @@ using ICSharpCode.Decompiler.Metadata; @@ -29,8 +29,8 @@ using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Solution;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
using ICSharpCode.ILSpy.Docking;
using ICSharpCode.ILSpy.TextView;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX;
namespace ICSharpCode.ILSpy
@ -198,7 +198,10 @@ namespace ICSharpCode.ILSpy @@ -198,7 +198,10 @@ namespace ICSharpCode.ILSpy
public override RichText GetRichTextTooltip(IEntity entity)
{
var output = new AvalonEditTextOutput() { IgnoreNewLineAndIndent = true };
var disasm = CreateDisassembler(output, MainWindow.Instance.CreateDecompilationOptions());
var settingsService = SettingsService.Instance;
var dockWorkspace = DockWorkspace.Instance;
var disasm = CreateDisassembler(output, settingsService.CreateDecompilationOptions(dockWorkspace.ActiveTabPage));
MetadataFile module = entity.ParentModule?.MetadataFile;
if (module == null)
{

9
ILSpy/Languages/Languages.cs

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#nullable enable
using System;
using System.Collections.ObjectModel;
using System.Linq;
@ -31,9 +33,9 @@ namespace ICSharpCode.ILSpy @@ -31,9 +33,9 @@ namespace ICSharpCode.ILSpy
/// </summary>
public static ReadOnlyCollection<Language> AllLanguages { get; } = Initialize(App.ExportProvider);
static ReadOnlyCollection<Language> Initialize(IExportProvider ep)
static ReadOnlyCollection<Language> Initialize(IExportProvider exportProvider)
{
var languages = ep.GetExportedValues<Language>().ToList();
var languages = exportProvider.GetExportedValues<Language>().ToList();
languages.Sort((a, b) => string.Compare(a.Name, b.Name, StringComparison.Ordinal));
#if DEBUG
@ -52,7 +54,8 @@ namespace ICSharpCode.ILSpy @@ -52,7 +54,8 @@ namespace ICSharpCode.ILSpy
return AllLanguages.FirstOrDefault(l => l.Name == name) ?? AllLanguages.First();
}
static ILLanguage ilLanguage;
static ILLanguage? ilLanguage;
public static ILLanguage ILLanguage {
get {
if (ilLanguage == null)

199
ILSpy/MainWindow.xaml

@ -1,72 +1,25 @@ @@ -1,72 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<Window
x:Class="ICSharpCode.ILSpy.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:tv="clr-namespace:ICSharpCode.ILSpy.Controls.TreeView"
xmlns:local="clr-namespace:ICSharpCode.ILSpy"
xmlns:avalondock="https://github.com/Dirkster99/AvalonDock"
xmlns:controls="clr-namespace:ICSharpCode.ILSpy.Controls"
xmlns:docking="clr-namespace:ICSharpCode.ILSpy.Docking"
xmlns:properties="clr-namespace:ICSharpCode.ILSpy.Properties"
Title="ILSpy"
MinWidth="250"
MinHeight="200"
UseLayoutRounding="True"
TextOptions.TextFormattingMode="Display"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" d:DesignHeight="500" d:DesignWidth="500"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes"
xmlns:toms="urn:TomsToolbox"
xmlns:viewModels="clr-namespace:ICSharpCode.ILSpy.ViewModels"
xmlns:treeNodes="clr-namespace:ICSharpCode.ILSpy.TreeNodes"
xmlns:util="clr-namespace:ICSharpCode.ILSpy.Util"
d:DataContext="{d:DesignInstance local:MainWindowViewModel}">
<Window x:Class="ICSharpCode.ILSpy.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ICSharpCode.ILSpy"
xmlns:avalondock="https://github.com/Dirkster99/AvalonDock"
xmlns:controls="clr-namespace:ICSharpCode.ILSpy.Controls"
xmlns:docking="clr-namespace:ICSharpCode.ILSpy.Docking"
xmlns:properties="clr-namespace:ICSharpCode.ILSpy.Properties"
Title="ILSpy"
MinWidth="250"
MinHeight="200"
UseLayoutRounding="True"
TextOptions.TextFormattingMode="Display"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" d:DesignHeight="500" d:DesignWidth="500"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes"
xmlns:toms="urn:TomsToolbox"
xmlns:viewModels="clr-namespace:ICSharpCode.ILSpy.ViewModels"
d:DataContext="{d:DesignInstance local:MainWindowViewModel}">
<Window.Resources>
<tv:SharpTreeView x:Key="AssemblyTreeView"
AutomationProperties.Name="Assemblies and Classes"
SelectionChanged="TreeView_SelectionChanged"
ShowRoot="False"
AllowDropOrder="True"
AllowDrop="True"
BorderThickness="0" Visibility="Visible">
<tv:SharpTreeView.ItemContainerStyle>
<Style TargetType="tv:SharpTreeViewItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type tv:SharpTreeViewItem}" d:DataContext="{d:DesignInstance treeNodes:ILSpyTreeNode}">
<Border Background="Transparent">
<Border Background="{TemplateBinding Background}">
<tv:SharpTreeNodeView x:Name="nodeView" HorizontalAlignment="Left" />
</Border>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding IsAutoLoaded}" Value="True">
<Setter Property="Foreground" Value="SteelBlue" />
</DataTrigger>
<DataTrigger Binding="{Binding IsPublicAPI}" Value="False">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</DataTrigger>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="nodeView" Property="TextBackground" Value="{DynamicResource {x:Static SystemColors.HighlightBrushKey}}" />
<Setter TargetName="nodeView" Property="Foreground" Value="{DynamicResource {x:Static SystemColors.HighlightTextBrushKey}}" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="nodeView" Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</tv:SharpTreeView.ItemContainerStyle>
</tv:SharpTreeView>
<DataTemplate DataType="{x:Type viewModels:AssemblyListPaneModel}">
<ContentControl Content="{StaticResource AssemblyTreeView}" />
</DataTemplate>
<DataTemplate DataType="{x:Type viewModels:TabPageModel}">
<ContentPresenter Content="{Binding Content}" />
@ -76,38 +29,12 @@ @@ -76,38 +29,12 @@
<ContentPresenter Content="{Binding Content}" />
</DataTemplate>
<toms:BindingRelay x:Key="WindowBinding" DataContext="{Binding}" />
</Window.Resources>
<b:Interaction.Behaviors>
<themes:WindowStyleManagerBehavior />
</b:Interaction.Behaviors>
<Window.CommandBindings>
<CommandBinding
Command="Open"
Executed="OpenCommandExecuted" />
<CommandBinding
Command="Refresh"
Executed="RefreshCommandExecuted" />
<CommandBinding
Command="Save"
CanExecute="SaveCommandCanExecute"
Executed="SaveCommandExecuted" />
<CommandBinding
Command="BrowseBack"
CanExecute="BackCommandCanExecute"
Executed="BackCommandExecuted" />
<CommandBinding
Command="BrowseForward"
CanExecute="ForwardCommandCanExecute"
Executed="ForwardCommandExecuted" />
<CommandBinding
Command="Search"
Executed="SearchCommandExecuted" />
</Window.CommandBindings>
<Window.InputBindings>
<KeyBinding Key="R" Modifiers="Control" Command="{x:Static local:ILSpyCommands.Analyze}" />
</Window.InputBindings>
@ -122,9 +49,12 @@ @@ -122,9 +49,12 @@
<MenuItem Header="{x:Static properties:Resources._File}" Tag="_File" />
<!-- contents of file menu are added using MEF -->
<MenuItem Header="{x:Static properties:Resources._View}" Tag="_View">
<MenuItem Header="{x:Static properties:Resources.Show_publiconlyTypesMembers}" IsCheckable="True" IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicOnly}" />
<MenuItem Header="{x:Static properties:Resources.Show_internalTypesMembers}" IsCheckable="True" IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicAndInternal}" />
<MenuItem Header="{x:Static properties:Resources.Show_allTypesAndMembers}" IsCheckable="True" IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisAll}" />
<MenuItem Header="{x:Static properties:Resources.Show_publiconlyTypesMembers}" IsCheckable="True"
IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicOnly}" />
<MenuItem Header="{x:Static properties:Resources.Show_internalTypesMembers}" IsCheckable="True"
IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicAndInternal}" />
<MenuItem Header="{x:Static properties:Resources.Show_allTypesAndMembers}" IsCheckable="True"
IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisAll}" />
<Separator />
<MenuItem Header="{x:Static properties:Resources.Theme}" ItemsSource="{x:Static themes:ThemeManager.AllThemes}">
<MenuItem.ItemContainerStyle>
@ -137,7 +67,7 @@ @@ -137,7 +67,7 @@
<Setter.Value>
<MultiBinding Converter="{x:Static toms:BinaryOperationConverter.Equality}" Mode="OneWay">
<Binding />
<Binding Source="{StaticResource WindowBinding}" Path="DataContext.SessionSettings.Theme" />
<Binding Path="DataContext.SessionSettings.Theme" RelativeSource="{RelativeSource FindAncestor, AncestorType=Window}"/>
</MultiBinding>
</Setter.Value>
</Setter>
@ -145,9 +75,12 @@ @@ -145,9 +75,12 @@
</MenuItem.ItemContainerStyle>
</MenuItem>
<MenuItem Header="{x:Static properties:Resources.UILanguage}">
<MenuItem Header="{x:Static properties:Resources.UILanguage_System}" IsCheckable="True" IsChecked="{Binding SessionSettings.CurrentCulture, Converter={controls:CultureSelectionConverter}, ConverterParameter={x:Null}}" />
<MenuItem Header="English" IsCheckable="True" IsChecked="{Binding SessionSettings.CurrentCulture, Converter={controls:CultureSelectionConverter}, ConverterParameter=en-US}" />
<MenuItem Header="中文" IsCheckable="True" IsChecked="{Binding SessionSettings.CurrentCulture, Converter={controls:CultureSelectionConverter}, ConverterParameter=zh-Hans}" />
<MenuItem Header="{x:Static properties:Resources.UILanguage_System}" IsCheckable="True"
IsChecked="{Binding SessionSettings.CurrentCulture, Converter={controls:CultureSelectionConverter}, ConverterParameter={x:Null}}" />
<MenuItem Header="English" IsCheckable="True"
IsChecked="{Binding SessionSettings.CurrentCulture, Converter={controls:CultureSelectionConverter}, ConverterParameter=en-US}" />
<MenuItem Header="中文" IsCheckable="True"
IsChecked="{Binding SessionSettings.CurrentCulture, Converter={controls:CultureSelectionConverter}, ConverterParameter=zh-Hans}" />
</MenuItem>
</MenuItem>
<MenuItem Header="{x:Static properties:Resources._Window}" Tag="_Window" />
@ -183,52 +116,52 @@ @@ -183,52 +116,52 @@
<!-- 'Open' toolbar category is inserted here -->
<Separator />
<ComboBox Name="assemblyListComboBox" Width="100" MaxDropDownHeight="Auto"
ItemsSource="{Binding AssemblyListManager.AssemblyLists}"
ToolTip="{x:Static properties:Resources.SelectAssemblyListDropdownTooltip}"
SelectedItem="{Binding SessionSettings.ActiveAssemblyList}" />
ItemsSource="{Binding AssemblyListManager.AssemblyLists}"
ToolTip="{x:Static properties:Resources.SelectAssemblyListDropdownTooltip}"
SelectedItem="{Binding SessionSettings.ActiveAssemblyList}" />
<Button Command="{x:Static local:ILSpyCommands.ManageAssemblyListsCommand}"
ToolTip="{x:Static properties:Resources.ManageAssemblyLists}">
ToolTip="{x:Static properties:Resources.ManageAssemblyLists}">
<Image Width="16" Height="16" Source="{controls:XamlResource Images/AssemblyList}"
Style="{StaticResource DarkModeAwareImageStyle}" />
Style="{StaticResource DarkModeAwareImageStyle}" />
</Button>
<Separator />
<CheckBox IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicOnly}"
ToolTip="{x:Static properties:Resources.ShowPublicOnlyTypesMembers}">
ToolTip="{x:Static properties:Resources.ShowPublicOnlyTypesMembers}">
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowPublicOnly}"
Style="{StaticResource DarkModeAwareImageStyle}" />
Style="{StaticResource DarkModeAwareImageStyle}" />
</CheckBox>
<CheckBox IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisPublicAndInternal}"
ToolTip="{x:Static properties:Resources.ShowInternalTypesMembers}">
ToolTip="{x:Static properties:Resources.ShowInternalTypesMembers}">
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowPrivateInternal}"
Style="{StaticResource DarkModeAwareImageStyle}" />
Style="{StaticResource DarkModeAwareImageStyle}" />
</CheckBox>
<CheckBox IsChecked="{Binding SessionSettings.LanguageSettings.ApiVisAll}"
ToolTip="{x:Static properties:Resources.ShowAllTypesAndMembers}">
ToolTip="{x:Static properties:Resources.ShowAllTypesAndMembers}">
<Image Width="16" Height="16" Source="{controls:XamlResource Images/ShowAll}"
Style="{StaticResource DarkModeAwareImageStyle}" />
Style="{StaticResource DarkModeAwareImageStyle}" />
</CheckBox>
<Separator />
<ComboBox Name="languageComboBox" DisplayMemberPath="Name" Width="100" MaxDropDownHeight="Auto"
IsEnabled="{Binding Workspace.ActiveTabPage.SupportsLanguageSwitching}"
ItemsSource="{x:Static local:Languages.AllLanguages}"
ToolTip="{x:Static properties:Resources.SelectLanguageDropdownTooltip}"
SelectedItem="{Binding SessionSettings.LanguageSettings.Language}" />
IsEnabled="{Binding Workspace.ActiveTabPage.SupportsLanguageSwitching}"
ItemsSource="{x:Static local:Languages.AllLanguages}"
ToolTip="{x:Static properties:Resources.SelectLanguageDropdownTooltip}"
SelectedItem="{Binding SessionSettings.LanguageSettings.Language}" />
<ComboBox Name="languageVersionComboBox" DisplayMemberPath="DisplayName" Width="120" MaxDropDownHeight="Auto"
ToolTip="{x:Static properties:Resources.SelectVersionDropdownTooltip}"
Visibility="{Binding SelectedItem.HasLanguageVersions, ElementName=languageComboBox, Converter={toms:BooleanToVisibilityConverter}}"
IsEnabled="{Binding Workspace.ActiveTabPage.SupportsLanguageSwitching}"
ItemsSource="{Binding SelectedItem.LanguageVersions, ElementName=languageComboBox, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding SessionSettings.LanguageSettings.LanguageVersion, UpdateSourceTrigger=PropertyChanged}" />
ToolTip="{x:Static properties:Resources.SelectVersionDropdownTooltip}"
Visibility="{Binding SelectedItem.HasLanguageVersions, ElementName=languageComboBox, Converter={toms:BooleanToVisibilityConverter}}"
IsEnabled="{Binding Workspace.ActiveTabPage.SupportsLanguageSwitching}"
ItemsSource="{Binding SelectedItem.LanguageVersions, ElementName=languageComboBox, UpdateSourceTrigger=PropertyChanged}"
SelectedItem="{Binding SessionSettings.LanguageSettings.LanguageVersion, UpdateSourceTrigger=PropertyChanged}" />
</ToolBar>
<!-- Update panel -->
<Border DockPanel.Dock="Top" BorderBrush="Black" BorderThickness="1" Name="updatePanel" Visibility="Collapsed">
<DockPanel KeyboardNavigation.TabNavigation="Contained">
<Button DockPanel.Dock="Right" Click="updatePanelCloseButtonClick" MinWidth="0">X</Button>
<Button DockPanel.Dock="Right" Click="UpdatePanelCloseButtonClick" MinWidth="0">X</Button>
<StackPanel Orientation="Horizontal">
<TextBlock Name="updatePanelMessage" Margin="4,0" VerticalAlignment="Center"
Text="{x:Static properties:Resources.ILSpyVersionAvailable}" />
<Button Name="downloadOrCheckUpdateButton" Click="downloadOrCheckUpdateButtonClick"
Content="{x:Static properties:Resources.Download}" />
Text="{x:Static properties:Resources.ILSpyVersionAvailable}" />
<Button Name="downloadOrCheckUpdateButton" Click="DownloadOrCheckUpdateButtonClick"
Content="{x:Static properties:Resources.Download}" />
</StackPanel>
</DockPanel>
</Border>
@ -236,19 +169,19 @@ @@ -236,19 +169,19 @@
<StatusBar x:Name="statusBar" DockPanel.Dock="Bottom" Height="26" Visibility="Collapsed">
<StatusBarItem DockPanel.Dock="Right">
<TextBlock VerticalAlignment="Center"
HorizontalAlignment="Right"
x:Name="statusLabel"
ToolTip="{x:Static properties:Resources.Status}"
Text="{x:Static properties:Resources.StandBy}" />
HorizontalAlignment="Right"
x:Name="statusLabel"
ToolTip="{x:Static properties:Resources.Status}"
Text="{x:Static properties:Resources.StandBy}" />
</StatusBarItem>
</StatusBar>
<avalondock:DockingManager x:Name="dockManager"
DataContext="{Binding Workspace}"
AnchorablesSource="{Binding ToolPanes}"
DocumentsSource="{Binding TabPages}"
ActiveContent="{Binding ActiveTabPage, Mode=TwoWay, Converter={docking:TabPageGuardConverter}}"
AllowMixedOrientation="True">
DataContext="{Binding Workspace}"
AnchorablesSource="{Binding ToolPanes}"
DocumentsSource="{Binding TabPages}"
ActiveContent="{Binding ActiveTabPage, Mode=TwoWay, Converter={docking:TabPageGuardConverter}}"
AllowMixedOrientation="True">
<avalondock:DockingManager.DocumentHeaderTemplate>
<DataTemplate DataType="{x:Type viewModels:PaneModel}">

1446
ILSpy/MainWindow.xaml.cs

File diff suppressed because it is too large Load Diff

10
ILSpy/MainWindowViewModel.cs

@ -19,12 +19,14 @@ @@ -19,12 +19,14 @@
using ICSharpCode.ILSpy.Docking;
using ICSharpCode.ILSpyX;
using TomsToolbox.Wpf;
namespace ICSharpCode.ILSpy
{
class MainWindowViewModel
class MainWindowViewModel : ObservableObject
{
public DockWorkspace Workspace { get; set; }
public SessionSettings SessionSettings { get; set; }
public AssemblyListManager AssemblyListManager { get; set; }
public DockWorkspace Workspace => DockWorkspace.Instance;
public SessionSettings SessionSettings => SettingsService.Instance.SessionSettings;
public AssemblyListManager AssemblyListManager => SettingsService.Instance.AssemblyListManager;
}
}

2
ILSpy/Metadata/CoffHeaderTreeNode.cs

@ -28,6 +28,8 @@ using ICSharpCode.ILSpy.TreeNodes; @@ -28,6 +28,8 @@ using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.ViewModels;
using ICSharpCode.ILSpyX.Extensions;
using TomsToolbox.Essentials;
namespace ICSharpCode.ILSpy.Metadata
{
class CoffHeaderTreeNode : ILSpyTreeNode

2
ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs

@ -97,7 +97,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -97,7 +97,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnParentClick()
{
MainWindow.Instance.JumpToReference(new EntityReference("metadata", classLayout.Parent));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference("metadata", classLayout.Parent)));
}
string parentTooltip;

2
ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs

@ -88,7 +88,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -88,7 +88,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnParentClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, constant.Parent, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, constant.Parent, protocol: "metadata")));
}
string parentTooltip;

4
ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs

@ -83,7 +83,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -83,7 +83,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnParentClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, customAttr.Parent, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, customAttr.Parent, protocol: "metadata")));
}
string parentTooltip;
@ -94,7 +94,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -94,7 +94,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnConstructorClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, customAttr.Constructor, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, customAttr.Constructor, protocol: "metadata")));
}
string constructorTooltip;

2
ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs

@ -84,7 +84,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -84,7 +84,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnParentClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, declSecAttr.Parent, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, declSecAttr.Parent, protocol: "metadata")));
}
string parentTooltip;

4
ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs

@ -95,7 +95,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -95,7 +95,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnParentClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, eventMap.Parent, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, eventMap.Parent, protocol: "metadata")));
}
string parentTooltip;
@ -106,7 +106,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -106,7 +106,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnEventListClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, eventMap.EventList, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, eventMap.EventList, protocol: "metadata")));
}
string eventListTooltip;

2
ILSpy/Metadata/CorTables/EventTableTreeNode.cs

@ -103,7 +103,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -103,7 +103,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnTypeClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, eventDef.Type, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, eventDef.Type, protocol: "metadata")));
}
string typeTooltip;

2
ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs

@ -107,7 +107,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -107,7 +107,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnImplementationClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, type.Implementation, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, type.Implementation, protocol: "metadata")));
}
string implementationTooltip;

2
ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs

@ -96,7 +96,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -96,7 +96,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnFieldClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, fieldLayout.Field, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, fieldLayout.Field, protocol: "metadata")));
}
string fieldTooltip;

2
ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs

@ -95,7 +95,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -95,7 +95,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnParentClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, fieldMarshal.Parent, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, fieldMarshal.Parent, protocol: "metadata")));
}
string parentTooltip;

2
ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs

@ -99,7 +99,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -99,7 +99,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnFieldClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, fieldRVA.Field, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, fieldRVA.Field, protocol: "metadata")));
}
string fieldTooltip;

4
ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs

@ -84,7 +84,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -84,7 +84,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnOwnerClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, genericParamConstraint.Parameter, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, genericParamConstraint.Parameter, protocol: "metadata")));
}
string ownerTooltip;
@ -108,7 +108,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -108,7 +108,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnTypeClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, genericParamConstraint.Type, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, genericParamConstraint.Type, protocol: "metadata")));
}
string typeTooltip;

2
ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs

@ -92,7 +92,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -92,7 +92,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnOwnerClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, genericParam.Parent, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, genericParam.Parent, protocol: "metadata")));
}
string ownerTooltip;

4
ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs

@ -113,7 +113,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -113,7 +113,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnMemberForwardedClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, implMap.MemberForwarded, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, implMap.MemberForwarded, protocol: "metadata")));
}
string memberForwardedTooltip;
@ -124,7 +124,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -124,7 +124,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnImportScopeClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, implMap.ImportScope, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, implMap.ImportScope, protocol: "metadata")));
}
string importScopeTooltip;

4
ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs

@ -96,7 +96,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -96,7 +96,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnClassClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, interfaceImpl.Class, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, interfaceImpl.Class, protocol: "metadata")));
}
string classTooltip;
@ -107,7 +107,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -107,7 +107,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnInterfaceClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, interfaceImpl.Interface, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, interfaceImpl.Interface, protocol: "metadata")));
}
string interfaceTooltip;

2
ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs

@ -93,7 +93,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -93,7 +93,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnImplementationClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, manifestResource.Implementation, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, manifestResource.Implementation, protocol: "metadata")));
}
string implementationTooltip;

2
ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs

@ -83,7 +83,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -83,7 +83,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnParentClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, memberRef.Parent, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, memberRef.Parent, protocol: "metadata")));
}
string parentTooltip;

6
ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs

@ -82,7 +82,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -82,7 +82,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnMethodDeclarationClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, methodImpl.MethodDeclaration, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, methodImpl.MethodDeclaration, protocol: "metadata")));
}
string methodDeclarationTooltip;
@ -93,7 +93,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -93,7 +93,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnMethodBodyClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, methodImpl.MethodBody, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, methodImpl.MethodBody, protocol: "metadata")));
}
string methodBodyTooltip;
@ -104,7 +104,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -104,7 +104,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnTypeClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, methodImpl.Type, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, methodImpl.Type, protocol: "metadata")));
}
string typeTooltip;

4
ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs

@ -90,7 +90,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -90,7 +90,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnMethodClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, method, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, method, protocol: "metadata")));
}
string methodTooltip;
@ -101,7 +101,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -101,7 +101,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnAssociationClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, association, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, association, protocol: "metadata")));
}
string associationTooltip;

2
ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs

@ -85,7 +85,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -85,7 +85,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnMethodClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, methodSpec.Method, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, methodSpec.Method, protocol: "metadata")));
}
string methodTooltip;

2
ILSpy/Metadata/CorTables/MethodTableTreeNode.cs

@ -118,7 +118,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -118,7 +118,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnParamListClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, methodDef.GetParameters().FirstOrDefault(), protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, methodDef.GetParameters().FirstOrDefault(), protocol: "metadata")));
}
string paramListTooltip;

4
ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs

@ -95,7 +95,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -95,7 +95,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnNestedClassClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, nestedClass.Nested, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, nestedClass.Nested, protocol: "metadata")));
}
string nestedClassTooltip;
@ -106,7 +106,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -106,7 +106,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnEnclosingClassClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, nestedClass.Enclosing, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, nestedClass.Enclosing, protocol: "metadata")));
}
string enclosingClassTooltip;

4
ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs

@ -95,7 +95,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -95,7 +95,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnParentClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, propertyMap.Parent, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, propertyMap.Parent, protocol: "metadata")));
}
string parentTooltip;
@ -106,7 +106,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -106,7 +106,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnPropertyListClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, propertyMap.PropertyList, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, propertyMap.PropertyList, protocol: "metadata")));
}
string propertyListTooltip;

2
ILSpy/Metadata/CorTables/PtrTableTreeNode.cs

@ -112,7 +112,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -112,7 +112,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnHandleClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, handlePtr.Handle, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, handlePtr.Handle, protocol: "metadata")));
}
string handleTooltip;

6
ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs

@ -111,7 +111,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -111,7 +111,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnBaseTypeClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, typeDef.BaseType, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, typeDef.BaseType, protocol: "metadata")));
}
public string BaseTypeTooltip {
@ -142,7 +142,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -142,7 +142,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnFieldListClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, typeDef.GetFields().FirstOrDefault(), protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, typeDef.GetFields().FirstOrDefault(), protocol: "metadata")));
}
string fieldListTooltip;
@ -160,7 +160,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -160,7 +160,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnMethodListClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, typeDef.GetMethods().FirstOrDefault(), protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, typeDef.GetMethods().FirstOrDefault(), protocol: "metadata")));
}
string methodListTooltip;

2
ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs

@ -83,7 +83,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -83,7 +83,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnResolutionScopeClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, typeRef.ResolutionScope, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, typeRef.ResolutionScope, protocol: "metadata")));
}
string resolutionScopeTooltip;

1
ILSpy/Metadata/DebugMetadataTablesTreeNode.cs

@ -21,7 +21,6 @@ using System.Reflection.Metadata.Ecma335; @@ -21,7 +21,6 @@ using System.Reflection.Metadata.Ecma335;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpy.ViewModels;
namespace ICSharpCode.ILSpy.Metadata

2
ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs

@ -188,7 +188,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -188,7 +188,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnParentClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, debugInfo.Parent, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, debugInfo.Parent, protocol: "metadata")));
}
string parentTooltip;

2
ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs

@ -80,7 +80,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -80,7 +80,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnParentClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, localScope.Parent, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, localScope.Parent, protocol: "metadata")));
}
[ColumnInfo("X8", Kind = ColumnKind.HeapOffset)]

8
ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs

@ -81,7 +81,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -81,7 +81,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnMethodClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, localScope.Method, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, localScope.Method, protocol: "metadata")));
}
string methodTooltip;
@ -92,7 +92,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -92,7 +92,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnImportScopeClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, localScope.ImportScope, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, localScope.ImportScope, protocol: "metadata")));
}
[ColumnInfo("X8", Kind = ColumnKind.Token)]
@ -100,7 +100,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -100,7 +100,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnVariableListClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, localScope.GetLocalVariables().FirstOrDefault(), protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, localScope.GetLocalVariables().FirstOrDefault(), protocol: "metadata")));
}
[ColumnInfo("X8", Kind = ColumnKind.Token)]
@ -108,7 +108,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -108,7 +108,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnConstantListClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, localScope.GetLocalConstants().FirstOrDefault(), protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, localScope.GetLocalConstants().FirstOrDefault(), protocol: "metadata")));
}
public int StartOffset => localScope.StartOffset;

4
ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs

@ -83,7 +83,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -83,7 +83,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnDocumentClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, debugInfo.Document, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, debugInfo.Document, protocol: "metadata")));
}
public string DocumentTooltip {
@ -116,7 +116,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -116,7 +116,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnLocalSignatureClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, debugInfo.LocalSignature, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, debugInfo.LocalSignature, protocol: "metadata")));
}
public string LocalSignatureTooltip {

4
ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs

@ -83,7 +83,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -83,7 +83,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnMoveNextMethodClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, moveNextMethod, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, moveNextMethod, protocol: "metadata")));
}
string moveNextMethodTooltip;
@ -94,7 +94,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -94,7 +94,7 @@ namespace ICSharpCode.ILSpy.Metadata
public void OnKickofMethodClick()
{
MainWindow.Instance.JumpToReference(new EntityReference(metadataFile, kickoffMethod, protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, kickoffMethod, protocol: "metadata")));
}
string kickoffMethodTooltip;

24
ILSpy/Metadata/GoToTokenCommand.cs

@ -23,12 +23,13 @@ using System.Reflection; @@ -23,12 +23,13 @@ using System.Reflection;
using System.Reflection.Metadata.Ecma335;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.Metadata;
using ICSharpCode.ILSpy.Properties;
using TomsToolbox.Wpf;
namespace ICSharpCode.ILSpy.Commands
{
[ExportContextMenuEntry(Header = nameof(Resources.GoToToken), Order = 10)]
@ -38,7 +39,7 @@ namespace ICSharpCode.ILSpy.Commands @@ -38,7 +39,7 @@ namespace ICSharpCode.ILSpy.Commands
public void Execute(TextViewContext context)
{
int token = GetSelectedToken(context.DataGrid, out MetadataFile module).Value;
MainWindow.Instance.JumpToReference(new EntityReference(module, MetadataTokens.Handle(token), protocol: "metadata"));
MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(module, MetadataTokens.Handle(token), protocol: "metadata")));
}
public bool IsEnabled(TextViewContext context)
@ -75,7 +76,7 @@ namespace ICSharpCode.ILSpy.Commands @@ -75,7 +76,7 @@ namespace ICSharpCode.ILSpy.Commands
{
public void Execute(TextViewContext context)
{
string content = GetSelectedCellContent(context.DataGrid, context.MousePosition);
string content = GetSelectedCellContent(context.OriginalSource);
Clipboard.SetText(content);
}
@ -87,21 +88,14 @@ namespace ICSharpCode.ILSpy.Commands @@ -87,21 +88,14 @@ namespace ICSharpCode.ILSpy.Commands
public bool IsVisible(TextViewContext context)
{
return context.DataGrid?.Name == "MetadataView"
&& GetSelectedCellContent(context.DataGrid, context.MousePosition) != null;
&& GetSelectedCellContent(context.OriginalSource) != null;
}
private string GetSelectedCellContent(DataGrid grid, Point position)
private static string GetSelectedCellContent(DependencyObject originalSource)
{
position = grid.PointFromScreen(position);
var hit = VisualTreeHelper.HitTest(grid, position);
if (hit == null)
return null;
var cell = hit.VisualHit.GetParent<DataGridCell>();
if (cell == null)
return null;
return cell.DataContext.GetType()
.GetProperty(cell.Column.Header.ToString(), BindingFlags.Instance | BindingFlags.Public)
.GetValue(cell.DataContext).ToString();
var cell = originalSource.AncestorsAndSelf().OfType<DataGridCell>().FirstOrDefault();
return cell?.Column.OnCopyingCellClipboardContent(cell.DataContext).ToString();
}
}
}

2
ILSpy/Metadata/MetadataProtocolHandler.cs

@ -34,7 +34,7 @@ namespace ICSharpCode.ILSpy.Metadata @@ -34,7 +34,7 @@ namespace ICSharpCode.ILSpy.Metadata
newTabPage = true;
if (protocol != "metadata")
return null;
var assemblyTreeNode = MainWindow.Instance.FindTreeNode(module) as AssemblyTreeNode;
var assemblyTreeNode = MainWindow.Instance.AssemblyTreeModel.FindTreeNode(module) as AssemblyTreeNode;
if (assemblyTreeNode == null)
return null;
var mxNode = assemblyTreeNode.Children.OfType<MetadataTreeNode>().FirstOrDefault();

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save