diff --git a/BuildTools/update-assemblyinfo.ps1 b/BuildTools/update-assemblyinfo.ps1
index b07199c82..f4096cb74 100644
--- a/BuildTools/update-assemblyinfo.ps1
+++ b/BuildTools/update-assemblyinfo.ps1
@@ -69,6 +69,17 @@ function gitCommitHash() {
}
}
+function gitShortCommitHash() {
+ if (No-Git) {
+ return "00000000";
+ }
+ try {
+ return (git rev-parse --short=8 (git rev-list --max-count 1 HEAD));
+ } catch {
+ return "00000000";
+ }
+}
+
function gitBranch() {
if (No-Git) {
return "no-branch";
@@ -117,6 +128,7 @@ try {
$revision = gitVersion;
$branchName = gitBranch;
$gitCommitHash = gitCommitHash;
+ $gitShortCommitHash = gitShortCommitHash;
if ($branchName -match $masterBranches) {
$postfixBranchName = "";
@@ -150,7 +162,7 @@ try {
$out = $out.Replace('$INSERTMAJORVERSION$', $major);
$out = $out.Replace('$INSERTREVISION$', $revision);
$out = $out.Replace('$INSERTCOMMITHASH$', $gitCommitHash);
- $out = $out.Replace('$INSERTSHORTCOMMITHASH$', $gitCommitHash.Substring(0, 8));
+ $out = $out.Replace('$INSERTSHORTCOMMITHASH$', $gitShortCommitHash);
$out = $out.Replace('$INSERTDATE$', [System.DateTime]::Now.ToString("MM/dd/yyyy"));
$out = $out.Replace('$INSERTYEAR$', [System.DateTime]::Now.Year.ToString());
$out = $out.Replace('$INSERTBRANCHNAME$', $branchName);
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 0a153070f..f2fd119b5 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -9,34 +9,34 @@
-
+
-
+
-
-
+
+
-
+
-
-
+
+
-
-
-
+
+
+
diff --git a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
index e5c09c9c1..284b51401 100644
--- a/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
+++ b/ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
@@ -736,7 +736,7 @@ namespace ICSharpCode.Decompiler.Tests
var decompiled = await Tester.DecompileCSharp(exeFile, decompilerSettings ?? Tester.GetSettings(cscOptions)).ConfigureAwait(false);
// 3. Compile
- CodeAssert.FilesAreEqual(csFile, decompiled, Tester.GetPreprocessorSymbols(cscOptions).ToArray());
+ CodeAssert.FilesAreEqual(csFile, decompiled, Tester.GetPreprocessorSymbols(cscOptions).Append("EXPECTED_OUTPUT").ToArray());
Tester.RepeatOnIOError(() => File.Delete(decompiled));
}
}
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.cs
index 642a9576e..3b5bc08ec 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.cs
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/VariableNaming.cs
@@ -60,5 +60,108 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
#pragma warning restore CS0219
}
#endif
+
+ private static void NestedForLoopTest(int sizeX, int sizeY, int[] array)
+ {
+ for (int y = 0; y < sizeY; y++)
+ {
+ for (int x = 0; x < sizeX; x++)
+ {
+ array[y * sizeX + x] = 0;
+ }
+ }
+#if !EXPECTED_OUTPUT || (LEGACY_CSC && !OPT)
+ for (int y = 0; y < sizeY; y++)
+ {
+ for (int x = 0; x < sizeX; x++)
+ {
+ array[y * sizeX + x] = 1;
+ }
+ }
+#else
+ for (int i = 0; i < sizeY; i++)
+ {
+ for (int j = 0; j < sizeX; j++)
+ {
+ array[i * sizeX + j] = 1;
+ }
+ }
+#endif
+ }
+
+ private static void NestedForLoopTest2()
+ {
+ for (int i = 0; i < 10; i++)
+ {
+ Nop(i);
+ }
+#if EXPECTED_OUTPUT && !(LEGACY_CSC && !OPT)
+ for (int j = 0; j < 10; j++)
+ {
+ Nop(j);
+ }
+
+ for (int k = 0; k < 10; k++)
+ {
+ Nop(k);
+ }
+
+ for (int l = 0; l < 10; l++)
+ {
+ Nop(l);
+ }
+
+ for (int m = 0; m < 10; m++)
+ {
+ for (int n = 0; n < 10; n++)
+ {
+ Nop(n);
+ }
+ }
+
+ for (int num = 0; num < 10; num++)
+ {
+ for (int num2 = 0; num2 < 10; num2++)
+ {
+ Nop(num2);
+ }
+ }
+#else
+ for (int i = 0; i < 10; i++)
+ {
+ Nop(i);
+ }
+
+ for (int i = 0; i < 10; i++)
+ {
+ Nop(i);
+ }
+
+ for (int i = 0; i < 10; i++)
+ {
+ Nop(i);
+ }
+
+ for (int i = 0; i < 10; i++)
+ {
+ for (int j = 0; j < 10; j++)
+ {
+ Nop(j);
+ }
+ }
+
+ for (int i = 0; i < 10; i++)
+ {
+ for (int j = 0; j < 10; j++)
+ {
+ Nop(j);
+ }
+ }
+#endif
+ }
+
+ private static void Nop(int v)
+ {
+ }
}
}
diff --git a/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs b/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs
index 9b832955c..bee806143 100644
--- a/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs
+++ b/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs
@@ -289,27 +289,29 @@ namespace ICSharpCode.Decompiler.IL.Transforms
string nameWithoutNumber = SplitName(newName, out int newIndex);
if (reservedVariableNames.TryGetValue(nameWithoutNumber, out int lastUsedIndex))
{
- // name without number was already used
if (v.Type.IsKnownType(KnownTypeCode.Int32) && loopCounters.Contains(v))
{
// special case for loop counters,
// we don't want them to be named i, i2, ..., but i, j, ...
newName = GenerateNameForVariable(v);
+ nameWithoutNumber = newName;
+ newIndex = 1;
+ }
+ }
+ if (reservedVariableNames.TryGetValue(nameWithoutNumber, out lastUsedIndex))
+ {
+ // name without number was already used
+ if (newIndex > lastUsedIndex)
+ {
+ // new index is larger than last, so we can use it
}
else
{
- if (newIndex > lastUsedIndex)
- {
- // new index is larger than last, so we can use it
- }
- else
- {
- // new index is smaller or equal, so we use the next value
- newIndex = lastUsedIndex + 1;
- }
- // resolve conflicts by appending the index to the new name:
- newName = nameWithoutNumber + newIndex.ToString();
+ // new index is smaller or equal, so we use the next value
+ newIndex = lastUsedIndex + 1;
}
+ // resolve conflicts by appending the index to the new name:
+ newName = nameWithoutNumber + newIndex.ToString();
}
// update the last used index
reservedVariableNames[nameWithoutNumber] = newIndex;
diff --git a/ICSharpCode.Decompiler/Properties/AssemblyInfo.cs b/ICSharpCode.Decompiler/Properties/AssemblyInfo.cs
index 3f6d671f7..aeac8ac43 100644
--- a/ICSharpCode.Decompiler/Properties/AssemblyInfo.cs
+++ b/ICSharpCode.Decompiler/Properties/AssemblyInfo.cs
@@ -15,7 +15,7 @@ using System.Runtime.InteropServices;
[assembly: ComVisible(false)]
[assembly: AssemblyVersion(DecompilerVersionInfo.Major + "." + DecompilerVersionInfo.Minor + "." + DecompilerVersionInfo.Build + "." + DecompilerVersionInfo.Revision)]
-[assembly: AssemblyInformationalVersion(DecompilerVersionInfo.FullVersionWithShortCommitHash)]
+[assembly: AssemblyInformationalVersion(DecompilerVersionInfo.FullVersionWithCommitHash)]
[assembly: InternalsVisibleTo("ICSharpCode.Decompiler.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001004dcf3979c4e902efa4dd2163a039701ed5822e6f1134d77737296abbb97bf0803083cfb2117b4f5446a217782f5c7c634f9fe1fc60b4c11d62c5b3d33545036706296d31903ddcf750875db38a8ac379512f51620bb948c94d0831125fbc5fe63707cbb93f48c1459c4d1749eb7ac5e681a2f0d6d7c60fa527a3c0b8f92b02bf")]
diff --git a/ICSharpCode.Decompiler/Properties/DecompilerVersionInfo.template.cs b/ICSharpCode.Decompiler/Properties/DecompilerVersionInfo.template.cs
index ee12ad9b8..6d29f56fb 100644
--- a/ICSharpCode.Decompiler/Properties/DecompilerVersionInfo.template.cs
+++ b/ICSharpCode.Decompiler/Properties/DecompilerVersionInfo.template.cs
@@ -7,5 +7,6 @@
public const string VersionName = "preview2";
public const string FullVersion = Major + "." + Minor + "." + Build + ".$INSERTREVISION$$INSERTBRANCHPOSTFIX$$INSERTVERSIONNAMEPOSTFIX$";
- public const string FullVersionWithShortCommitHash = FullVersion + "-$INSERTSHORTCOMMITHASH$";
+ public const string FullVersionWithShortCommitHash = FullVersion + "+$INSERTSHORTCOMMITHASH$";
+ public const string FullVersionWithCommitHash = FullVersion + "+$INSERTCOMMITHASH$";
}
diff --git a/ICSharpCode.ILSpyCmd/Properties/AssemblyInfo.cs b/ICSharpCode.ILSpyCmd/Properties/AssemblyInfo.cs
index f89527a81..0a60d6bf6 100644
--- a/ICSharpCode.ILSpyCmd/Properties/AssemblyInfo.cs
+++ b/ICSharpCode.ILSpyCmd/Properties/AssemblyInfo.cs
@@ -1,12 +1,8 @@
#region Using directives
-using System;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
-using System.Resources;
-using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using System.Runtime.Versioning;
#endregion
@@ -15,7 +11,7 @@ using System.Runtime.Versioning;
[assembly: ComVisible(false)]
[assembly: AssemblyVersion(DecompilerVersionInfo.Major + "." + DecompilerVersionInfo.Minor + "." + DecompilerVersionInfo.Build + "." + DecompilerVersionInfo.Revision)]
-[assembly: AssemblyInformationalVersion(DecompilerVersionInfo.FullVersionWithShortCommitHash)]
+[assembly: AssemblyInformationalVersion(DecompilerVersionInfo.FullVersionWithCommitHash)]
[assembly: SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly",
Justification = "AssemblyInformationalVersion does not need to be a parsable version")]
diff --git a/ICSharpCode.ILSpyX/AssemblyList.cs b/ICSharpCode.ILSpyX/AssemblyList.cs
index b52e79117..190f45e52 100644
--- a/ICSharpCode.ILSpyX/AssemblyList.cs
+++ b/ICSharpCode.ILSpyX/AssemblyList.cs
@@ -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
}
}
- 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
{
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;
});
}
diff --git a/ICSharpCode.ILSpyX/AssemblyListManager.cs b/ICSharpCode.ILSpyX/AssemblyListManager.cs
index 8a886df5f..35e1021ce 100644
--- a/ICSharpCode.ILSpyX/AssemblyListManager.cs
+++ b/ICSharpCode.ILSpyX/AssemblyListManager.cs
@@ -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
public bool UseDebugSymbols { get; set; }
- public ObservableCollection AssemblyLists { get; } = new ObservableCollection();
+ public ObservableCollection AssemblyLists { get; } = [];
- public FileLoaderRegistry LoaderRegistry { get; } = new FileLoaderRegistry();
+ public FileLoaderRegistry LoaderRegistry { get; } = new();
///
/// Loads an assembly list from the ILSpySettings.
@@ -69,14 +69,13 @@ namespace ICSharpCode.ILSpyX
///
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)
diff --git a/ICSharpCode.ILSpyX/Extensions/CollectionExtensions.cs b/ICSharpCode.ILSpyX/Extensions/CollectionExtensions.cs
index 772c46476..1d4f359e1 100644
--- a/ICSharpCode.ILSpyX/Extensions/CollectionExtensions.cs
+++ b/ICSharpCode.ILSpyX/Extensions/CollectionExtensions.cs
@@ -27,7 +27,7 @@ namespace ICSharpCode.ILSpyX.Extensions
{
public static class CollectionExtensions
{
- public static void AddRange(this ICollection list, IEnumerable items)
+ internal static void AddRange(this ICollection list, IEnumerable items)
{
foreach (T item in items)
if (!list.Contains(item))
diff --git a/ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj b/ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj
index bcea038e2..21a9363b0 100644
--- a/ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj
+++ b/ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj
@@ -41,7 +41,6 @@
-
diff --git a/ICSharpCode.ILSpyX/LoadedPackage.cs b/ICSharpCode.ILSpyX/LoadedPackage.cs
index 47e80b962..78f80b349 100644
--- a/ICSharpCode.ILSpyX/LoadedPackage.cs
+++ b/ICSharpCode.ILSpyX/LoadedPackage.cs
@@ -51,14 +51,14 @@ namespace ICSharpCode.ILSpyX
public PackageKind Kind { get; }
- internal SingleFileBundle.Header BundleHeader { get; set; }
+ public SingleFileBundle.Header BundleHeader { get; set; }
///
/// List of all entries, including those in sub-directories within the package.
///
public IReadOnlyList Entries { get; }
- internal PackageFolder RootFolder { get; }
+ public PackageFolder RootFolder { get; }
public LoadedPackage(PackageKind kind, IEnumerable entries)
{
@@ -256,7 +256,7 @@ namespace ICSharpCode.ILSpyX
public abstract string FullName { get; }
}
- sealed class PackageFolder : IAssemblyResolver
+ public sealed class PackageFolder : IAssemblyResolver
{
///
/// Gets the short name of the folder.
@@ -326,7 +326,7 @@ namespace ICSharpCode.ILSpyX
readonly Dictionary assemblies = new Dictionary(StringComparer.OrdinalIgnoreCase);
- internal LoadedAssembly? ResolveFileName(string name)
+ public LoadedAssembly? ResolveFileName(string name)
{
if (package.LoadedAssembly == null)
return null;
diff --git a/ICSharpCode.ILSpyX/PdbProvider/PortableDebugInfoProvider.cs b/ICSharpCode.ILSpyX/PdbProvider/PortableDebugInfoProvider.cs
index ec4cb8faf..a5432f47c 100644
--- a/ICSharpCode.ILSpyX/PdbProvider/PortableDebugInfoProvider.cs
+++ b/ICSharpCode.ILSpyX/PdbProvider/PortableDebugInfoProvider.cs
@@ -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
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
}
}
- internal MetadataReader? GetMetadataReader()
+ public MetadataReader? GetMetadataReader()
{
try
{
diff --git a/ICSharpCode.ILSpyX/Properties/AssemblyInfo.cs b/ICSharpCode.ILSpyX/Properties/AssemblyInfo.cs
index 34d6f6fa1..f4c52a6e3 100644
--- a/ICSharpCode.ILSpyX/Properties/AssemblyInfo.cs
+++ b/ICSharpCode.ILSpyX/Properties/AssemblyInfo.cs
@@ -1,12 +1,8 @@
#region Using directives
-using System;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
-using System.Resources;
-using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
-using System.Runtime.Versioning;
#endregion
@@ -15,7 +11,7 @@ using System.Runtime.Versioning;
[assembly: ComVisible(false)]
[assembly: AssemblyVersion(DecompilerVersionInfo.Major + "." + DecompilerVersionInfo.Minor + "." + DecompilerVersionInfo.Build + "." + DecompilerVersionInfo.Revision)]
-[assembly: AssemblyInformationalVersion(DecompilerVersionInfo.FullVersionWithShortCommitHash)]
+[assembly: AssemblyInformationalVersion(DecompilerVersionInfo.FullVersionWithCommitHash)]
[assembly: SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly",
Justification = "AssemblyInformationalVersion does not need to be a parsable version")]
diff --git a/ICSharpCode.ILSpyX/Settings/ILSpySettings.cs b/ICSharpCode.ILSpyX/Settings/ILSpySettings.cs
index 63e94299b..d19998587 100644
--- a/ICSharpCode.ILSpyX/Settings/ILSpySettings.cs
+++ b/ICSharpCode.ILSpyX/Settings/ILSpySettings.cs
@@ -34,16 +34,11 @@ namespace ICSharpCode.ILSpyX.Settings
///
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
{
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
}
}
- static XDocument LoadWithoutCheckingCharacters(string fileName)
+ static XDocument LoadFile(string fileName)
{
return XDocument.Load(fileName, LoadOptions.None);
}
@@ -91,16 +80,15 @@ namespace ICSharpCode.ILSpyX.Settings
///
/// Saves a setting section.
///
- 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);
+ });
}
///
@@ -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.
///
- public static void Update(Action action)
+ public void Update(Action action)
{
using (new MutexProtector(ConfigFileMutex))
{
@@ -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
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 action)
- {
- Update(action);
- }
-
static string GetConfigFile()
{
if (null != SettingsFilePathProvider)
@@ -148,11 +132,6 @@ namespace ICSharpCode.ILSpyX.Settings
// return "ILSpy.xml";
}
- ISettingsProvider ISettingsProvider.Load()
- {
- return Load();
- }
-
const string ConfigFileMutex = "01A91708-49D1-410D-B8EB-4DE2662B3971";
///
@@ -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)
- {
- }
}
}
diff --git a/ICSharpCode.ILSpyX/Settings/IMiscSettings.cs b/ICSharpCode.ILSpyX/Settings/IMiscSettings.cs
deleted file mode 100644
index 363dba66b..000000000
--- a/ICSharpCode.ILSpyX/Settings/IMiscSettings.cs
+++ /dev/null
@@ -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);
- }
- }
-}
diff --git a/ICSharpCode.ILSpyX/Settings/ISettingsFilePathProvider.cs b/ICSharpCode.ILSpyX/Settings/ISettingsFilePathProvider.cs
index 15b16a09b..5e3ffba9b 100644
--- a/ICSharpCode.ILSpyX/Settings/ISettingsFilePathProvider.cs
+++ b/ICSharpCode.ILSpyX/Settings/ISettingsFilePathProvider.cs
@@ -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
diff --git a/ICSharpCode.ILSpyX/Settings/ISettingsProvider.cs b/ICSharpCode.ILSpyX/Settings/ISettingsProvider.cs
index 3f62dba76..1ddcec131 100644
--- a/ICSharpCode.ILSpyX/Settings/ISettingsProvider.cs
+++ b/ICSharpCode.ILSpyX/Settings/ISettingsProvider.cs
@@ -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
XElement this[XName section] { get; }
void Update(Action 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()?.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()?.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);
}
}
diff --git a/ICSharpCode.ILSpyX/Settings/ISettingsSection.cs b/ICSharpCode.ILSpyX/Settings/ISettingsSection.cs
deleted file mode 100644
index 1735289ef..000000000
--- a/ICSharpCode.ILSpyX/Settings/ISettingsSection.cs
+++ /dev/null
@@ -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
- {
- // This should be abstract, but that needs C# 11.0 (see IParseable)
- // Keep it to be enabled in the future
- public static TSelf Load(ISettingsProvider settingsProvider)
- {
- throw new NotImplementedException();
- }
- }
-}
diff --git a/ICSharpCode.ILSpyX/TreeView/SharpTreeNode.cs b/ICSharpCode.ILSpyX/TreeView/SharpTreeNode.cs
index e34675fc3..5f8e1cc31 100644
--- a/ICSharpCode.ILSpyX/TreeView/SharpTreeNode.cs
+++ b/ICSharpCode.ILSpyX/TreeView/SharpTreeNode.cs
@@ -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
return TreeTraversal.PreOrder(this.Children.Where(c => c.isVisible), n => n.Children.Where(c => c.isVisible));
}
- internal IEnumerable VisibleDescendantsAndSelf()
+ public IEnumerable VisibleDescendantsAndSelf()
{
return TreeTraversal.PreOrder(this, n => n.Children.Where(c => c.isVisible));
}
@@ -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)
{
@@ -658,8 +658,9 @@ namespace ICSharpCode.ILSpyX.TreeView
public bool IsLast {
get {
- return Parent == null ||
- Parent.Children[Parent.Children.Count - 1] == this;
+ return Parent == null
+ || Parent.Children.Count == 0
+ || Parent.Children[^1] == this;
}
}
diff --git a/ICSharpCode.ILSpyX/TreeView/TreeFlattener.cs b/ICSharpCode.ILSpyX/TreeView/TreeFlattener.cs
index 46cc5cafd..80803c194 100644
--- a/ICSharpCode.ILSpyX/TreeView/TreeFlattener.cs
+++ b/ICSharpCode.ILSpyX/TreeView/TreeFlattener.cs
@@ -26,7 +26,7 @@ using System.Diagnostics;
namespace ICSharpCode.ILSpyX.TreeView
{
- sealed class TreeFlattener : IList, INotifyCollectionChanged
+ public sealed class TreeFlattener : IList, INotifyCollectionChanged
{
///
/// The root node of the flat list tree.
diff --git a/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs b/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs
index 0b7d0ee6c..ce9e62a1e 100644
--- a/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs
+++ b/ILSpy.ReadyToRun/ReadyToRunDisassembler.cs
@@ -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
ReadyToRunMethod readyToRunMethod = runtimeFunction.Method;
WriteCommentLine(readyToRunMethod.SignatureString);
- if (ReadyToRunOptions.GetIsShowGCInfo(null))
+ var options = SettingsService.Instance.GetSettings();
+
+ 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
}
Dictionary 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
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
}
}
}
- if (ReadyToRunOptions.GetIsShowGCInfo(null))
+ if (options.IsShowGCInfo)
{
DecorateGCInfo(instr, baseInstrIP, readyToRunMethod.GcInfo);
}
diff --git a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml
index 137e0a6a1..388923678 100644
--- a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml
+++ b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml
@@ -1,7 +1,11 @@
+ 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}">
@@ -14,12 +18,12 @@
-
-
-
+
+
+
-
+
-
+
\ No newline at end of file
diff --git a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs
index fbe046ea4..d48d55ec1 100644
--- a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs
+++ b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs
@@ -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();
}
- 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"));
}
}
}
\ No newline at end of file
diff --git a/ILSpy.ReadyToRun/ReadyToRunOptions.cs b/ILSpy.ReadyToRun/ReadyToRunOptions.cs
index 365d1dd9a..9b13f7ba7 100644
--- a/ILSpy.ReadyToRun/ReadyToRunOptions.cs
+++ b/ILSpy.ReadyToRun/ReadyToRunOptions.cs
@@ -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;
}
}
}
diff --git a/ILSpy/AboutPage.cs b/ILSpy/AboutPage.cs
index 43303bf88..9d462e753 100644
--- a/ILSpy/AboutPage.cs
+++ b/ILSpy/AboutPage.cs
@@ -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
);
@@ -54,7 +54,7 @@ namespace ICSharpCode.ILSpy
Title = Resources.About,
EnableHyperlinks = true
};
- output.WriteLine(Resources.ILSpyVersion + DecompilerVersionInfo.FullVersion);
+ output.WriteLine(Resources.ILSpyVersion + DecompilerVersionInfo.FullVersionWithCommitHash);
string prodVersion = GetDotnetProductVersion();
output.WriteLine(Resources.NETFrameworkVersion + prodVersion);
@@ -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),
diff --git a/ILSpy/Analyzers/AnalyzeCommand.cs b/ILSpy/Analyzers/AnalyzeCommand.cs
index 889e6afa0..9a24f29b2 100644
--- a/ILSpy/Analyzers/AnalyzeCommand.cs
+++ b/ILSpy/Analyzers/AnalyzeCommand.cs
@@ -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())
+ foreach (var node in MainWindow.Instance.AssemblyTreeModel.SelectedNodes.OfType())
{
AnalyzerTreeView.Analyze(node.Member);
}
diff --git a/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs b/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs
index 213624ee1..4217e411c 100644
--- a/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs
+++ b/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs
@@ -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 removedAssemblies, ICollection addedAssemblies)
diff --git a/ILSpy/Analyzers/AnalyzerRootNode.cs b/ILSpy/Analyzers/AnalyzerRootNode.cs
index 17709687f..e1ce03438 100644
--- a/ILSpy/Analyzers/AnalyzerRootNode.cs
+++ b/ILSpy/Analyzers/AnalyzerRootNode.cs
@@ -2,7 +2,6 @@
using System.Collections.Specialized;
using System.Linq;
-using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX;
using ICSharpCode.ILSpyX.TreeView;
diff --git a/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs b/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs
index 0a7bbb95c..7c3d484bc 100644
--- a/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs
+++ b/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs
@@ -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)
diff --git a/ILSpy/Analyzers/AnalyzerTreeNode.cs b/ILSpy/Analyzers/AnalyzerTreeNode.cs
index 8972926a7..fb052303e 100644
--- a/ILSpy/Analyzers/AnalyzerTreeNode.cs
+++ b/ILSpy/Analyzers/AnalyzerTreeNode.cs
@@ -18,7 +18,6 @@
using System.Collections.Generic;
-using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX;
using ICSharpCode.ILSpyX.TreeView;
diff --git a/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs b/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs
index e7f83f638..7f343fb78 100644
--- a/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs
+++ b/ILSpy/Analyzers/TreeNodes/AnalyzedModuleTreeNode.cs
@@ -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;
diff --git a/ILSpy/App.xaml b/ILSpy/App.xaml
index 0cfda48ce..ce2e14086 100644
--- a/ILSpy/App.xaml
+++ b/ILSpy/App.xaml
@@ -1,15 +1,14 @@
+ 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">
+
+
\ No newline at end of file
diff --git a/ILSpy/AssemblyTree/AssemblyListPane.xaml.cs b/ILSpy/AssemblyTree/AssemblyListPane.xaml.cs
new file mode 100644
index 000000000..9b6e7fb79
--- /dev/null
+++ b/ILSpy/AssemblyTree/AssemblyListPane.xaml.cs
@@ -0,0 +1,44 @@
+using System.ComponentModel.Composition;
+using System.Windows;
+
+using ICSharpCode.ILSpyX.TreeView;
+
+using TomsToolbox.Wpf.Composition.Mef;
+
+namespace ICSharpCode.ILSpy.AssemblyTree
+{
+ ///
+ /// Interaction logic for AssemblyListPane.xaml
+ ///
+ [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);
+ }
+ }
+ }
+}
diff --git a/ILSpy/AssemblyTree/AssemblyTreeModel.cs b/ILSpy/AssemblyTree/AssemblyTreeModel.cs
new file mode 100644
index 000000000..1c6903a55
--- /dev/null
+++ b/ILSpy/AssemblyTree/AssemblyTreeModel.cs
@@ -0,0 +1,922 @@
+// 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 System.Text;
+using System.Windows.Navigation;
+
+using ICSharpCode.ILSpy.AppEnv;
+using ICSharpCode.ILSpy.Search;
+using ICSharpCode.Decompiler;
+
+using TomsToolbox.Essentials;
+using TomsToolbox.Wpf;
+
+namespace ICSharpCode.ILSpy.AssemblyTree
+{
+ [ExportToolPane]
+ [PartCreationPolicy(CreationPolicy.Shared)]
+ [Export]
+ public class AssemblyTreeModel : ToolPaneModel
+ {
+ public const string PaneContentId = "assemblyListPane";
+
+ AssemblyListPane activeView;
+ AssemblyListTreeNode assemblyListTreeNode;
+
+ readonly NavigationHistory history = new();
+ private bool isNavigatingHistory;
+
+ public AssemblyTreeModel()
+ {
+ Title = Resources.Assemblies;
+ ContentId = PaneContentId;
+ IsCloseable = false;
+ ShortcutKey = new KeyGesture(Key.F6);
+
+ MessageBus.Subscribers += JumpToReference;
+ MessageBus.Subscribers += (sender, e) => Settings_PropertyChanged(sender, e);
+
+ var selectionChangeThrottle = new DispatcherThrottle(DispatcherPriority.Input, 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();
+ 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 SelectedItems { get; } = [];
+
+ public string[] SelectedPath => GetPathForNode(SelectedItem);
+
+ readonly List 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;
+ }
+
+ ///
+ /// 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.
+ ///
+ 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();
+
+ 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 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(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(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 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(e.OldItems.Cast());
+ history.RemoveAll(n => n.TreeNodes.Any(
+ nd => nd.AncestorsAndSelf().OfType().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 nodes)
+ {
+ // 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);
+ }
+
+ ///
+ /// Retrieves a node using the .ToString() representations of its ancestors.
+ ///
+ 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;
+ }
+
+ ///
+ /// Gets the .ToString() representation of the node's ancestors.
+ ///
+ public static string[] GetPathForNode(SharpTreeNode node)
+ {
+ if (node == null)
+ return null;
+ List path = new List();
+ 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 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();
+ }
+
+ ///
+ /// Jumps to the specified reference.
+ ///
+ ///
+ /// 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.
+ ///
+ 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();
+ 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 fileNames, List 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()
+ {
+ if (SelectedItems.Count > 0)
+ {
+ if (!isNavigatingHistory)
+ {
+ var activeTabPage = DockWorkspace.Instance.ActiveTabPage;
+ var currentState = activeTabPage.GetState();
+ if (currentState != null)
+ history.UpdateCurrent(new NavigationState(activeTabPage, currentState));
+ history.Record(new NavigationState(activeTabPage, SelectedItems));
+ }
+
+ 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 void DecompileSelectedNodes(DecompilerTextViewState newState = null)
+ {
+ var activeTabPage = DockWorkspace.Instance.ActiveTabPage;
+
+ activeTabPage.SupportsLanguageSwitching = true;
+
+ if (SelectedItems.Count == 1)
+ {
+ if (SelectedItem is ILSpyTreeNode node && node.View(activeTabPage))
+ return;
+ }
+ if (newState?.ViewedUri != null)
+ {
+ 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 SelectedNodes {
+ get {
+ return GetTopLevelSelection().OfType();
+ }
+ }
+
+ #endregion
+
+ public void NavigateHistory(bool forward)
+ {
+ isNavigatingHistory = true;
+ this.Dispatcher.BeginInvoke(DispatcherPriority.Background, () => isNavigatingHistory = false);
+
+ 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);
+ }
+
+ 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();
+
+ 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);
+ }
+ }
+
+ private void UnselectAll()
+ {
+ SelectedItems.Clear();
+ }
+
+ public IEnumerable GetTopLevelSelection()
+ {
+ var selection = this.SelectedItems;
+ var selectionHash = new HashSet(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
+ {
+ public static readonly AssemblyComparer Instance = new();
+ int IComparer.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);
+ }
+ }
+}
diff --git a/ILSpy/Commands/BrowseBackCommand.cs b/ILSpy/Commands/BrowseBackCommand.cs
index cf424cbd4..ae53e19ef 100644
--- a/ILSpy/Commands/BrowseBackCommand.cs
+++ b/ILSpy/Commands/BrowseBackCommand.cs
@@ -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
[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);
+ }
}
}
}
diff --git a/ILSpy/Commands/BrowseForwardCommand.cs b/ILSpy/Commands/BrowseForwardCommand.cs
index 3a8276457..ea86ebc11 100644
--- a/ILSpy/Commands/BrowseForwardCommand.cs
+++ b/ILSpy/Commands/BrowseForwardCommand.cs
@@ -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
[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);
+ }
+ }
+
}
}
diff --git a/ILSpy/Commands/CheckForUpdatesCommand.cs b/ILSpy/Commands/CheckForUpdatesCommand.cs
index 58438c604..779f854a1 100644
--- a/ILSpy/Commands/CheckForUpdatesCommand.cs
+++ b/ILSpy/Commands/CheckForUpdatesCommand.cs
@@ -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
public override async void Execute(object parameter)
{
- await MainWindow.Instance.ShowMessageIfUpdatesAvailableAsync(ILSpySettings.Load(), forceCheck: true);
+ await MainWindow.Instance.ShowMessageIfUpdatesAvailableAsync(SettingsService.Instance.SpySettings, forceCheck: true);
}
}
}
diff --git a/ILSpy/Commands/CommandWrapper.cs b/ILSpy/Commands/CommandWrapper.cs
index 42b34ee05..809184391 100644
--- a/ILSpy/Commands/CommandWrapper.cs
+++ b/ILSpy/Commands/CommandWrapper.cs
@@ -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
{
return wrappedCommand.CanExecute(parameter);
}
+
+ protected abstract void OnExecute(object sender, ExecutedRoutedEventArgs e);
+
+ protected virtual void OnCanExecute(object sender, CanExecuteRoutedEventArgs e)
+ {
+ e.CanExecute = true;
+ }
}
}
diff --git a/ILSpy/Commands/DecompileAllCommand.cs b/ILSpy/Commands/DecompileAllCommand.cs
index c905c9a87..b041bf7a7 100644
--- a/ILSpy/Commands/DecompileAllCommand.cs
+++ b/ILSpy/Commands/DecompileAllCommand.cs
@@ -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
Docking.DockWorkspace.Instance.RunWithCancellation(ct => Task.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
{
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
{
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.Factory.StartNew(() => {
+ var nodes = MainWindow.Instance.AssemblyTreeModel.SelectedNodes.ToArray();
+ DockWorkspace dockWorkspace = DockWorkspace.Instance;
+ var options = SettingsService.Instance.CreateDecompilationOptions(dockWorkspace.ActiveTabPage);
+ dockWorkspace.RunWithCancellation(ct => Task.Factory.StartNew(() => {
options.CancellationToken = ct;
Stopwatch w = Stopwatch.StartNew();
for (int i = 0; i < numRuns; ++i)
@@ -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();
}
}
}
diff --git a/ILSpy/Commands/DecompileCommand.cs b/ILSpy/Commands/DecompileCommand.cs
index 0a7d1a385..ec35a0cbe 100644
--- a/ILSpy/Commands/DecompileCommand.cs
+++ b/ILSpy/Commands/DecompileCommand.cs
@@ -66,7 +66,7 @@ namespace ICSharpCode.ILSpy.Commands
selection = entity;
}
if (selection != null)
- MainWindow.Instance.JumpToReference(selection);
+ MessageBus.Send(this, new NavigateToReferenceEventArgs(selection));
}
}
}
diff --git a/ILSpy/Commands/DecompileInNewViewCommand.cs b/ILSpy/Commands/DecompileInNewViewCommand.cs
index 07e9bebcb..fd83244eb 100644
--- a/ILSpy/Commands/DecompileInNewViewCommand.cs
+++ b/ILSpy/Commands/DecompileInNewViewCommand.cs
@@ -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
{
if (context.SelectedTreeNodes != null)
{
- if (context.TreeView != MainWindow.Instance.AssemblyTreeView)
+ if (context.TreeView.DataContext != MainWindow.Instance.AssemblyTreeModel)
{
- return context.SelectedTreeNodes.OfType().Select(FindTreeNode).Where(n => n != null);
+ return context.SelectedTreeNodes.OfType().Select(FindTreeNode).ExceptNullItems();
}
else
{
- return context.SelectedTreeNodes.OfType().Where(n => n != null);
+ return context.SelectedTreeNodes.OfType();
}
}
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
{
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
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);
}
}
}
diff --git a/ILSpy/Commands/DisassembleAllCommand.cs b/ILSpy/Commands/DisassembleAllCommand.cs
index fc44d405a..07afced39 100644
--- a/ILSpy/Commands/DisassembleAllCommand.cs
+++ b/ILSpy/Commands/DisassembleAllCommand.cs
@@ -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
public override void Execute(object parameter)
{
- Docking.DockWorkspace.Instance.RunWithCancellation(ct => Task.Factory.StartNew(() => {
- AvalonEditTextOutput output = new AvalonEditTextOutput();
+ var dockWorkspace = Docking.DockWorkspace.Instance;
+
+ dockWorkspace.RunWithCancellation(ct => Task.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
{
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
}
});
return output;
- }, ct)).Then(output => Docking.DockWorkspace.Instance.ShowText(output)).HandleExceptions();
+ }, ct)).Then(dockWorkspace.ShowText).HandleExceptions();
}
}
}
diff --git a/ILSpy/Commands/GeneratePdbContextMenuEntry.cs b/ILSpy/Commands/GeneratePdbContextMenuEntry.cs
index b7c3997d0..4eb744992 100644
--- a/ILSpy/Commands/GeneratePdbContextMenuEntry.cs
+++ b/ILSpy/Commands/GeneratePdbContextMenuEntry.cs
@@ -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
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.Factory.StartNew(() => {
+ dockWorkspace.RunWithCancellation(ct => Task.Factory.StartNew(() => {
AvalonEditTextOutput output = new AvalonEditTextOutput();
Stopwatch stopwatch = Stopwatch.StartNew();
options.CancellationToken = ct;
@@ -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);
diff --git a/ILSpy/Commands/OpenCommand.cs b/ILSpy/Commands/OpenCommand.cs
index 7c66ac43a..06ac419e9 100644
--- a/ILSpy/Commands/OpenCommand.cs
+++ b/ILSpy/Commands/OpenCommand.cs
@@ -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
[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);
+ }
}
}
}
diff --git a/ILSpy/Commands/OpenFromGacCommand.cs b/ILSpy/Commands/OpenFromGacCommand.cs
index 393e00eeb..9d1c31214 100644
--- a/ILSpy/Commands/OpenFromGacCommand.cs
+++ b/ILSpy/Commands/OpenFromGacCommand.cs
@@ -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
[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
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);
+ }
}
}
}
diff --git a/ILSpy/Commands/Pdb2XmlCommand.cs b/ILSpy/Commands/Pdb2XmlCommand.cs
index c69777370..b624124cb 100644
--- a/ILSpy/Commands/Pdb2XmlCommand.cs
+++ b/ILSpy/Commands/Pdb2XmlCommand.cs
@@ -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());
+ Execute(MainWindow.Instance.AssemblyTreeModel.SelectedNodes.OfType());
}
internal static void Execute(IEnumerable nodes)
diff --git a/ILSpy/Commands/RefreshCommand.cs b/ILSpy/Commands/RefreshCommand.cs
index cfb03bf34..e01e70f0e 100644
--- a/ILSpy/Commands/RefreshCommand.cs
+++ b/ILSpy/Commands/RefreshCommand.cs
@@ -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
[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();
}
}
}
diff --git a/ILSpy/Commands/RemoveAssembliesWithLoadErrors.cs b/ILSpy/Commands/RemoveAssembliesWithLoadErrors.cs
index c8696104b..9cc357374 100644
--- a/ILSpy/Commands/RemoveAssembliesWithLoadErrors.cs
+++ b/ILSpy/Commands/RemoveAssembliesWithLoadErrors.cs
@@ -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
{
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();
}
}
}
diff --git a/ILSpy/Commands/SaveCodeContextMenuEntry.cs b/ILSpy/Commands/SaveCodeContextMenuEntry.cs
index d7e38ada3..41d45728e 100644
--- a/ILSpy/Commands/SaveCodeContextMenuEntry.cs
+++ b/ILSpy/Commands/SaveCodeContextMenuEntry.cs
@@ -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
public static void Execute(IReadOnlyList 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
// 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(), options);
});
diff --git a/ILSpy/Commands/SaveCommand.cs b/ILSpy/Commands/SaveCommand.cs
index 8b8871e0a..9e43df69b 100644
--- a/ILSpy/Commands/SaveCommand.cs
+++ b/ILSpy/Commands/SaveCommand.cs
@@ -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
[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());
}
}
}
diff --git a/ILSpy/Commands/SelectPdbContextMenuEntry.cs b/ILSpy/Commands/SelectPdbContextMenuEntry.cs
index 061ff7e6b..db4fa7373 100644
--- a/ILSpy/Commands/SelectPdbContextMenuEntry.cs
+++ b/ILSpy/Commands/SelectPdbContextMenuEntry.cs
@@ -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;
diff --git a/ILSpy/Commands/SetThemeCommand.cs b/ILSpy/Commands/SetThemeCommand.cs
index 2d1a0b32a..1f9a1226c 100644
--- a/ILSpy/Commands/SetThemeCommand.cs
+++ b/ILSpy/Commands/SetThemeCommand.cs
@@ -1,5 +1,4 @@
-using ICSharpCode.ILSpy.Util;
-
+
namespace ICSharpCode.ILSpy.Commands
{
public class SetThemeCommand : SimpleCommand
@@ -7,7 +6,9 @@ namespace ICSharpCode.ILSpy.Commands
public override void Execute(object parameter)
{
if (parameter is string theme)
+ {
SettingsService.Instance.SessionSettings.Theme = theme;
+ }
}
}
}
diff --git a/ILSpy/Commands/ShowCFGContextMenuEntry.cs b/ILSpy/Commands/ShowCFGContextMenuEntry.cs
index b4e8be003..2067752cc 100644
--- a/ILSpy/Commands/ShowCFGContextMenuEntry.cs
+++ b/ILSpy/Commands/ShowCFGContextMenuEntry.cs
@@ -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
{
diff --git a/ILSpy/Commands/SortAssemblyListCommand.cs b/ILSpy/Commands/SortAssemblyListCommand.cs
index 7621778a7..5b7dc67e1 100644
--- a/ILSpy/Commands/SortAssemblyListCommand.cs
+++ b/ILSpy/Commands/SortAssemblyListCommand.cs
@@ -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
+ sealed class SortAssemblyListCommand : SimpleCommand
{
public override void Execute(object parameter)
{
- using (MainWindow.Instance.AssemblyTreeView.LockUpdates())
- MainWindow.Instance.CurrentAssemblyList.Sort(this);
- }
-
- int IComparer.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
{
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;
- }
- }
}
}
}
diff --git a/ILSpy/ContextMenuEntry.cs b/ILSpy/ContextMenuEntry.cs
index fcbdb1bae..4da82c40d 100644
--- a/ILSpy/ContextMenuEntry.cs
+++ b/ILSpy/ContextMenuEntry.cs
@@ -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;
using ICSharpCode.ILSpyX.TreeView;
using TomsToolbox.Composition;
+using TomsToolbox.Essentials;
namespace ICSharpCode.ILSpy
{
@@ -86,36 +85,40 @@ namespace ICSharpCode.ILSpy
///
public TextViewPosition? Position { get; private set; }
- public Point MousePosition { get; private set; }
+ ///
+ /// Returns the original source of the context menu event.
+ ///
+ 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
internal class ContextMenuProvider
{
+ private static readonly WeakEventSource ContextMenuClosedEventSource = new();
+
+ public static event EventHandler ContextMenuClosed {
+ add => ContextMenuClosedEventSource.Subscribe(value);
+ remove => ContextMenuClosedEventSource.Unsubscribe(value);
+ }
+
///
/// Enables extensible context menu support for the specified tree view.
///
@@ -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[] entries;
- private ContextMenuProvider()
+ private ContextMenuProvider(Control control)
{
entries = App.ExportProvider.GetExports().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
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
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
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
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[]>();
IExport[] topLevelGroup = null;
foreach (var group in entries.OrderBy(c => c.Metadata.Order).GroupBy(c => c.Metadata.ParentMenuID))
@@ -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
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))
{
diff --git a/ILSpy/Controls/TreeView/SharpTreeView.cs b/ILSpy/Controls/TreeView/SharpTreeView.cs
index faa7cb2f0..80558388e 100644
--- a/ILSpy/Controls/TreeView/SharpTreeView.cs
+++ b/ILSpy/Controls/TreeView/SharpTreeView.cs
@@ -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
///
public IEnumerable GetTopLevelSelection()
{
- var selection = this.SelectedItems.OfType();
- var selectionHash = new HashSet(selection);
- return selection.Where(item => item.Ancestors().All(a => !selectionHash.Contains(a)));
+ var selection = this.SelectedItems.OfType().ToHashSet();
+
+ return selection.Where(item => item.Ancestors().All(a => !selection.Contains(a)));
}
#endregion
diff --git a/ILSpy/DecompilationOptions.cs b/ILSpy/DecompilationOptions.cs
index e5d480c3e..c7c87322d 100644
--- a/ILSpy/DecompilationOptions.cs
+++ b/ILSpy/DecompilationOptions.cs
@@ -23,6 +23,8 @@ using ICSharpCode.Decompiler;
using ICSharpCode.ILSpy.Options;
using ICSharpCode.ILSpyX;
+using DecompilerSettings = ICSharpCode.ILSpy.Options.DecompilerSettings;
+
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;
diff --git a/ILSpy/Docking/DockLayoutSettings.cs b/ILSpy/Docking/DockLayoutSettings.cs
index fc776db79..73ca3aa59 100644
--- a/ILSpy/Docking/DockLayoutSettings.cs
+++ b/ILSpy/Docking/DockLayoutSettings.cs
@@ -19,7 +19,6 @@
using System;
using System.IO;
using System.Linq;
-using System.Xml;
using System.Xml.Linq;
using AvalonDock.Layout.Serialization;
diff --git a/ILSpy/Docking/DockWorkspace.cs b/ILSpy/Docking/DockWorkspace.cs
index a7b4c7102..9ca68cc26 100644
--- a/ILSpy/Docking/DockWorkspace.cs
+++ b/ILSpy/Docking/DockWorkspace.cs
@@ -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
{
private static SessionSettings SessionSettings => SettingsService.Instance.SessionSettings;
+ private readonly IExportProvider exportProvider = App.ExportProvider;
+
public static readonly DockWorkspace Instance = new();
+ private readonly ObservableCollection tabPages = [];
+ private readonly ObservableCollection 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.Subscribers += (sender, e) => CurrentAssemblyList_Changed(sender, e);
}
@@ -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().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().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)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 TabPages { get; } = new PaneCollection();
+ public void AddTabPage(TabPageModel tabPage = null)
+ {
+ tabPages.Add(tabPage ?? new TabPageModel());
+ }
+
+ public ReadOnlyObservableCollection TabPages { get; }
- public ObservableCollection ToolPanes { get; } = new ObservableCollection();
+ public ReadOnlyObservableCollection 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
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
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("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
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
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);
diff --git a/ILSpy/Docking/PaneCollection.cs b/ILSpy/Docking/PaneCollection.cs
deleted file mode 100644
index 72b1b851b..000000000
--- a/ILSpy/Docking/PaneCollection.cs
+++ /dev/null
@@ -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 : INotifyCollectionChanged, ICollection
- where T : PaneModel, new()
- {
- private ObservableCollection observableCollection = new ObservableCollection();
-
- 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 GetEnumerator() => observableCollection.GetEnumerator();
- IEnumerator IEnumerable.GetEnumerator() => observableCollection.GetEnumerator();
- }
-}
diff --git a/ILSpy/ExtensionMethods.cs b/ILSpy/ExtensionMethods.cs
index 374ad026e..39d623fd9 100644
--- a/ILSpy/ExtensionMethods.cs
+++ b/ILSpy/ExtensionMethods.cs
@@ -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
{
///
@@ -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(child);
@@ -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();
+ }
+ }
+ }
}
}
diff --git a/ILSpy/GlobalUsings.cs b/ILSpy/GlobalUsings.cs
new file mode 100644
index 000000000..12310c612
--- /dev/null
+++ b/ILSpy/GlobalUsings.cs
@@ -0,0 +1 @@
+global using ICSharpCode.ILSpy.Util;
\ No newline at end of file
diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj
index 36a8e7b44..9b0dd6259 100644
--- a/ILSpy/ILSpy.csproj
+++ b/ILSpy/ILSpy.csproj
@@ -1,5 +1,4 @@
-
-
+
WinExe
diff --git a/ILSpy/LanguageSettings.cs b/ILSpy/LanguageSettings.cs
index ef7613ccf..3748038bd 100644
--- a/ILSpy/LanguageSettings.cs
+++ b/ILSpy/LanguageSettings.cs
@@ -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
{
///
/// Represents the filters applied to the tree view.
///
- public class LanguageSettings : INotifyPropertyChanged
+ public class LanguageSettings : ObservableObject, IChildSettings
{
///
/// This dictionary is necessary to remember language versions across language changes. For example,
@@ -40,14 +38,17 @@ namespace ICSharpCode.ILSpy
///
private readonly Dictionary languageVersionHistory = new Dictionary();
- 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
}
}
- 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.
diff --git a/ILSpy/Languages/CSharpILMixedLanguage.cs b/ILSpy/Languages/CSharpILMixedLanguage.cs
index 4f7ca57cc..4d3436d23 100644
--- a/ILSpy/Languages/CSharpILMixedLanguage.cs
+++ b/ILSpy/Languages/CSharpILMixedLanguage.cs
@@ -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;
diff --git a/ILSpy/Languages/CSharpLanguage.cs b/ILSpy/Languages/CSharpLanguage.cs
index df801511c..f7cf47367 100644
--- a/ILSpy/Languages/CSharpLanguage.cs
+++ b/ILSpy/Languages/CSharpLanguage.cs
@@ -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
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().Single());
+ MainWindow.Instance.AssemblyTreeModel.SelectNode(assemblyNode.Children.OfType().Single());
});
}
diff --git a/ILSpy/Languages/ILLanguage.cs b/ILSpy/Languages/ILLanguage.cs
index 22d060b37..dae303124 100644
--- a/ILSpy/Languages/ILLanguage.cs
+++ b/ILSpy/Languages/ILLanguage.cs
@@ -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
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)
{
diff --git a/ILSpy/Languages/Languages.cs b/ILSpy/Languages/Languages.cs
index a58df78da..980f90acc 100644
--- a/ILSpy/Languages/Languages.cs
+++ b/ILSpy/Languages/Languages.cs
@@ -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
///
public static ReadOnlyCollection AllLanguages { get; } = Initialize(App.ExportProvider);
- static ReadOnlyCollection Initialize(IExportProvider ep)
+ static ReadOnlyCollection Initialize(IExportProvider exportProvider)
{
- var languages = ep.GetExportedValues().ToList();
+ var languages = exportProvider.GetExportedValues().ToList();
languages.Sort((a, b) => string.Compare(a.Name, b.Name, StringComparison.Ordinal));
#if DEBUG
@@ -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)
diff --git a/ILSpy/MainWindow.xaml b/ILSpy/MainWindow.xaml
index 39407e92e..dcc13af3b 100644
--- a/ILSpy/MainWindow.xaml
+++ b/ILSpy/MainWindow.xaml
@@ -1,72 +1,25 @@
-
-
+
-
-
-
-
-
-
-
-
-
@@ -76,40 +29,15 @@
-
-
-
-
-
-
-
-
-
-
-
+
@@ -122,9 +50,12 @@
@@ -183,52 +117,52 @@
+ ItemsSource="{Binding AssemblyListManager.AssemblyLists}"
+ ToolTip="{x:Static properties:Resources.SelectAssemblyListDropdownTooltip}"
+ SelectedItem="{Binding SessionSettings.ActiveAssemblyList}" />
+ ToolTip="{x:Static properties:Resources.ShowPublicOnlyTypesMembers}">
+ Style="{StaticResource DarkModeAwareImageStyle}" />
+ ToolTip="{x:Static properties:Resources.ShowInternalTypesMembers}">
+ Style="{StaticResource DarkModeAwareImageStyle}" />
+ ToolTip="{x:Static properties:Resources.ShowAllTypesAndMembers}">
+ Style="{StaticResource DarkModeAwareImageStyle}" />
+ IsEnabled="{Binding Workspace.ActiveTabPage.SupportsLanguageSwitching}"
+ ItemsSource="{x:Static local:Languages.AllLanguages}"
+ ToolTip="{x:Static properties:Resources.SelectLanguageDropdownTooltip}"
+ SelectedItem="{Binding SessionSettings.LanguageSettings.Language}" />
+ 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}" />
-
+
-
+ Text="{x:Static properties:Resources.ILSpyVersionAvailable}" />
+
@@ -236,19 +170,19 @@
+ HorizontalAlignment="Right"
+ x:Name="statusLabel"
+ ToolTip="{x:Static properties:Resources.Status}"
+ Text="{x:Static properties:Resources.StandBy}" />
+ DataContext="{Binding Workspace}"
+ AnchorablesSource="{Binding ToolPanes}"
+ DocumentsSource="{Binding TabPages}"
+ ActiveContent="{Binding ActiveTabPage, Mode=TwoWay, Converter={docking:TabPageGuardConverter}}"
+ AllowMixedOrientation="True">
diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs
index 235594f7a..c5232ef83 100644
--- a/ILSpy/MainWindow.xaml.cs
+++ b/ILSpy/MainWindow.xaml.cs
@@ -17,52 +17,26 @@
// DEALINGS IN THE SOFTWARE.
using System;
-using System.Collections.Generic;
-using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
-using System.IO;
+using System.Drawing;
using System.Linq;
-using System.Reflection.Metadata;
-using System.Reflection.Metadata.Ecma335;
-using System.Text;
using System.Threading.Tasks;
using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;
-using System.Windows.Navigation;
-using System.Windows.Threading;
using AvalonDock.Layout.Serialization;
-using ICSharpCode.Decompiler;
-using ICSharpCode.Decompiler.Documentation;
-using ICSharpCode.Decompiler.Metadata;
-using ICSharpCode.Decompiler.TypeSystem;
-using ICSharpCode.Decompiler.TypeSystem.Implementation;
-using ICSharpCode.ILSpy.AppEnv;
-using ICSharpCode.ILSpy.Commands;
+using ICSharpCode.ILSpy.AssemblyTree;
using ICSharpCode.ILSpy.Docking;
-using ICSharpCode.ILSpy.Options;
-using ICSharpCode.ILSpy.Search;
-using ICSharpCode.ILSpy.TextView;
-using ICSharpCode.ILSpy.Themes;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpy.Updates;
-using ICSharpCode.ILSpy.ViewModels;
-using ICSharpCode.ILSpyX;
using ICSharpCode.ILSpyX.FileLoaders;
using ICSharpCode.ILSpyX.Settings;
-using ICSharpCode.ILSpy.Controls.TreeView;
-using ICSharpCode.ILSpy.Util;
-using ICSharpCode.ILSpyX.Extensions;
-
-using Microsoft.Win32;
using ICSharpCode.ILSpyX.TreeView;
-using TomsToolbox.Composition;
+using Screen = System.Windows.Forms.Screen;
namespace ICSharpCode.ILSpy
{
@@ -71,99 +45,36 @@ namespace ICSharpCode.ILSpy
///
partial class MainWindow : Window
{
- bool refreshInProgress, changingActiveTab;
- readonly NavigationHistory history = new NavigationHistory();
-
- AssemblyList assemblyList;
- AssemblyListTreeNode assemblyListTreeNode;
-
static MainWindow instance;
+ private readonly MainWindowViewModel mainWindowViewModel = new();
+
public static MainWindow Instance {
get { return instance; }
}
- public SharpTreeView AssemblyTreeView {
+ public AssemblyTreeModel AssemblyTreeModel {
get {
- return FindResource("AssemblyTreeView") as SharpTreeView;
+ return App.ExportProvider.GetExportedValue();
}
}
- public DecompilationOptions CreateDecompilationOptions()
- {
- var decompilerView = DockWorkspace.Instance.ActiveTabPage.Content as IProgress;
- return new DecompilationOptions(CurrentLanguageVersion, SettingsService.Instance.DecompilerSettings, SettingsService.Instance.DisplaySettings) { Progress = decompilerView };
- }
-
public MainWindow()
{
instance = this;
- var sessionSettings = SettingsService.Instance.SessionSettings;
-
// Make sure Images are initialized on the UI thread.
this.Icon = Images.ILSpyIcon;
- this.DataContext = new MainWindowViewModel {
- Workspace = DockWorkspace.Instance,
- SessionSettings = sessionSettings,
- AssemblyListManager = SettingsService.Instance.AssemblyListManager
- };
+ this.DataContext = mainWindowViewModel;
- SettingsService.Instance.AssemblyListManager.CreateDefaultAssemblyLists();
- if (!string.IsNullOrEmpty(sessionSettings.CurrentCulture))
- {
- System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(sessionSettings.CurrentCulture);
- }
InitializeComponent();
- InitToolPanes();
- DockWorkspace.Instance.InitializeLayout(dockManager);
-
- MessageBus.Subscribers += (sender, e) => SessionSettings_PropertyChanged(sender, e);
- MessageBus.Subscribers += (sender, e) => LanguageSettings_PropertyChanged(sender, e);
- MessageBus.Subscribers += DockWorkspace_ActiveTabPageChanged;
-
- InitMainMenu();
- InitWindowMenu();
- InitToolbar();
- InitFileLoaders();
- ContextMenuProvider.Add(AssemblyTreeView);
-
- this.Loaded += MainWindow_Loaded;
- }
- private void DockWorkspace_ActiveTabPageChanged(object sender, EventArgs e)
- {
- DockWorkspace dock = DockWorkspace.Instance;
+ mainWindowViewModel.Workspace.InitializeLayout(dockManager);
- var windowMenuItem = mainMenu.Items.OfType().First(m => (string)m.Tag == nameof(Properties.Resources._Window));
- foreach (MenuItem menuItem in windowMenuItem.Items.OfType())
- {
- if (menuItem.IsCheckable && menuItem.Tag is TabPageModel)
- {
- menuItem.IsChecked = menuItem.Tag == dock.ActiveTabPage;
- }
- }
- }
+ MenuService.Instance.Init(mainMenu, toolBar, InputBindings);
- private void SessionSettings_PropertyChanged(object sender, PropertyChangedEventArgs e)
- {
- var sessionSettings = SettingsService.Instance.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;
- }
+ InitFileLoaders();
}
void SetWindowBounds(Rect bounds)
@@ -174,367 +85,6 @@ namespace ICSharpCode.ILSpy
this.Height = bounds.Height;
}
- #region Toolbar extensibility
-
- void InitToolbar()
- {
- int navigationPos = 0;
- int openPos = 1;
- var toolbarCommands = App.ExportProvider.GetExports("ToolbarCommand");
- foreach (var commandGroup in toolbarCommands.OrderBy(c => c.Metadata.ToolbarOrder).GroupBy(c => Properties.Resources.ResourceManager.GetString(c.Metadata.ToolbarCategory)))
- {
- if (commandGroup.Key == Properties.Resources.ResourceManager.GetString("Navigation"))
- {
- foreach (var command in commandGroup)
- {
- toolBar.Items.Insert(navigationPos++, MakeToolbarItem(command));
- openPos++;
- }
- }
- else if (commandGroup.Key == Properties.Resources.ResourceManager.GetString("Open"))
- {
- foreach (var command in commandGroup)
- {
- toolBar.Items.Insert(openPos++, MakeToolbarItem(command));
- }
- }
- else
- {
- toolBar.Items.Add(new Separator());
- foreach (var command in commandGroup)
- {
- toolBar.Items.Add(MakeToolbarItem(command));
- }
- }
- }
-
- }
-
- Button MakeToolbarItem(IExport command)
- {
- return new Button {
- Style = ThemeManager.Current.CreateToolBarButtonStyle(),
- Command = CommandWrapper.Unwrap(command.Value),
- ToolTip = Properties.Resources.ResourceManager.GetString(command.Metadata.ToolTip),
- Tag = command.Metadata.Tag,
- Content = new Image {
- Width = 16,
- Height = 16,
- Source = Images.Load(command.Value, command.Metadata.ToolbarIcon)
- }
- };
- }
- #endregion
-
- #region Main Menu extensibility
-
- void InitMainMenu()
- {
- var mainMenuCommands = App.ExportProvider.GetExports("MainMenuCommand");
- // Start by constructing the individual flat menus
- var parentMenuItems = new Dictionary();
- var menuGroups = mainMenuCommands.OrderBy(c => c.Metadata.MenuOrder).GroupBy(c => c.Metadata.ParentMenuID);
- foreach (var menu in menuGroups)
- {
- // Get or add the target menu item and add all items grouped by menu category
- var parentMenuItem = GetOrAddParentMenuItem(menu.Key, menu.Key);
- foreach (var category in menu.GroupBy(c => c.Metadata.MenuCategory))
- {
- if (parentMenuItem.Items.Count > 0)
- {
- parentMenuItem.Items.Add(new Separator() { Tag = category.Key });
- }
- foreach (var entry in category)
- {
- if (menuGroups.Any(g => g.Key == entry.Metadata.MenuID))
- {
- var menuItem = GetOrAddParentMenuItem(entry.Metadata.MenuID, entry.Metadata.Header);
- // replace potential dummy text with real name
- menuItem.Header = GetResourceString(entry.Metadata.Header);
- parentMenuItem.Items.Add(menuItem);
- }
- else
- {
- MenuItem menuItem = new MenuItem();
- menuItem.Command = CommandWrapper.Unwrap(entry.Value);
- menuItem.Tag = entry.Metadata.MenuID;
- menuItem.Header = GetResourceString(entry.Metadata.Header);
- if (!string.IsNullOrEmpty(entry.Metadata.MenuIcon))
- {
- menuItem.Icon = new Image {
- Width = 16,
- Height = 16,
- Source = Images.Load(entry.Value, entry.Metadata.MenuIcon)
- };
- }
-
- menuItem.IsEnabled = entry.Metadata.IsEnabled;
- if (entry.Value is ToggleableCommand toggle)
- {
- menuItem.IsCheckable = true;
- menuItem.SetBinding(MenuItem.IsCheckedProperty, new Binding("IsChecked") { Source = entry.Value, Mode = BindingMode.OneWay });
- }
-
- menuItem.InputGestureText = entry.Metadata.InputGestureText;
- parentMenuItem.Items.Add(menuItem);
- }
- }
- }
- }
-
- foreach (var (key, item) in parentMenuItems)
- {
- if (item.Parent == null)
- {
- mainMenu.Items.Add(item);
- }
- }
-
- MenuItem GetOrAddParentMenuItem(string menuID, string resourceKey)
- {
- if (!parentMenuItems.TryGetValue(menuID, out var parentMenuItem))
- {
- var topLevelMenuItem = mainMenu.Items.OfType().FirstOrDefault(m => (string)m.Tag == menuID);
- if (topLevelMenuItem == null)
- {
- parentMenuItem = new MenuItem();
- parentMenuItem.Header = GetResourceString(resourceKey);
- parentMenuItem.Tag = menuID;
- parentMenuItems.Add(menuID, parentMenuItem);
- }
- else
- {
- parentMenuItems.Add(menuID, topLevelMenuItem);
- parentMenuItem = topLevelMenuItem;
- }
- }
- return parentMenuItem;
- }
- }
-
- internal static string GetResourceString(string key)
- {
- if (string.IsNullOrEmpty(key))
- {
- return null;
- }
- string value = Properties.Resources.ResourceManager.GetString(key);
- if (!string.IsNullOrEmpty(value))
- {
- return value;
- }
- return key;
- }
- #endregion
-
- #region Tool Pane extensibility
-
- private void InitToolPanes()
- {
- var toolPanes = App.ExportProvider.GetExportedValues("ToolPane").OrderBy(item => item.Title);
-
- DockWorkspace.Instance.ToolPanes.AddRange(toolPanes);
- }
-
- private void InitWindowMenu()
- {
- var windowMenuItem = mainMenu.Items.OfType().First(m => (string)m.Tag == nameof(Properties.Resources._Window));
- Separator separatorBeforeTools, separatorBeforeDocuments;
- windowMenuItem.Items.Add(separatorBeforeTools = new Separator());
- windowMenuItem.Items.Add(separatorBeforeDocuments = new Separator());
-
- var dock = DockWorkspace.Instance;
- dock.ToolPanes.CollectionChanged += ToolsChanged;
- dock.TabPages.CollectionChanged += TabsChanged;
-
- ToolsChanged(dock.ToolPanes, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
- TabsChanged(dock.TabPages, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
-
- void ToolsChanged(object sender, NotifyCollectionChangedEventArgs e)
- {
- int endIndex = windowMenuItem.Items.IndexOf(separatorBeforeDocuments);
- int startIndex = windowMenuItem.Items.IndexOf(separatorBeforeTools) + 1;
- int insertionIndex;
- switch (e.Action)
- {
- case NotifyCollectionChangedAction.Add:
- insertionIndex = Math.Min(endIndex, startIndex + e.NewStartingIndex);
- foreach (ToolPaneModel pane in e.NewItems)
- {
- MenuItem menuItem = CreateMenuItem(pane);
- windowMenuItem.Items.Insert(insertionIndex, menuItem);
- insertionIndex++;
- }
- break;
- case NotifyCollectionChangedAction.Remove:
- foreach (ToolPaneModel pane in e.OldItems)
- {
- for (int i = endIndex - 1; i >= startIndex; i--)
- {
- MenuItem item = (MenuItem)windowMenuItem.Items[i];
- if (pane == item.Tag)
- {
- windowMenuItem.Items.RemoveAt(i);
- item.Tag = null;
- endIndex--;
- break;
- }
- }
- }
- break;
- case NotifyCollectionChangedAction.Replace:
- break;
- case NotifyCollectionChangedAction.Move:
- break;
- case NotifyCollectionChangedAction.Reset:
- for (int i = endIndex - 1; i >= startIndex; i--)
- {
- MenuItem item = (MenuItem)windowMenuItem.Items[0];
- item.Tag = null;
- windowMenuItem.Items.RemoveAt(i);
- endIndex--;
- }
- insertionIndex = endIndex;
- foreach (ToolPaneModel pane in dock.ToolPanes)
- {
- MenuItem menuItem = CreateMenuItem(pane);
- windowMenuItem.Items.Insert(insertionIndex, menuItem);
- insertionIndex++;
- }
- break;
- }
-
- MenuItem CreateMenuItem(ToolPaneModel pane)
- {
- MenuItem menuItem = new MenuItem();
- menuItem.Command = pane.AssociatedCommand ?? new ToolPaneCommand(pane.ContentId);
- menuItem.Header = pane.Title;
- menuItem.Tag = pane;
- var shortcutKey = pane.ShortcutKey;
- if (shortcutKey != null)
- {
- InputBindings.Add(new InputBinding(menuItem.Command, shortcutKey));
- menuItem.InputGestureText = shortcutKey.GetDisplayStringForCulture(System.Globalization.CultureInfo.CurrentUICulture);
- }
- if (!string.IsNullOrEmpty(pane.Icon))
- {
- menuItem.Icon = new Image {
- Width = 16,
- Height = 16,
- Source = Images.Load(pane, pane.Icon)
- };
- }
-
- return menuItem;
- }
- }
-
- void TabsChanged(object sender, NotifyCollectionChangedEventArgs e)
- {
- int endIndex = windowMenuItem.Items.Count;
- int startIndex = windowMenuItem.Items.IndexOf(separatorBeforeDocuments) + 1;
- int insertionIndex;
- switch (e.Action)
- {
- case NotifyCollectionChangedAction.Add:
- insertionIndex = Math.Min(endIndex, startIndex + e.NewStartingIndex);
- foreach (TabPageModel pane in e.NewItems)
- {
- MenuItem menuItem = CreateMenuItem(pane);
- pane.PropertyChanged += TabPageChanged;
- windowMenuItem.Items.Insert(insertionIndex, menuItem);
- insertionIndex++;
- }
- break;
- case NotifyCollectionChangedAction.Remove:
- foreach (TabPageModel pane in e.OldItems)
- {
- for (int i = endIndex - 1; i >= startIndex; i--)
- {
- MenuItem item = (MenuItem)windowMenuItem.Items[i];
- if (pane == item.Tag)
- {
- windowMenuItem.Items.RemoveAt(i);
- pane.PropertyChanged -= TabPageChanged;
- item.Tag = null;
- endIndex--;
- break;
- }
- }
- }
- break;
- case NotifyCollectionChangedAction.Replace:
- break;
- case NotifyCollectionChangedAction.Move:
- break;
- case NotifyCollectionChangedAction.Reset:
- for (int i = endIndex - 1; i >= startIndex; i--)
- {
- MenuItem item = (MenuItem)windowMenuItem.Items[i];
- windowMenuItem.Items.RemoveAt(i);
- ((TabPageModel)item.Tag).PropertyChanged -= TabPageChanged;
- endIndex--;
- }
- insertionIndex = endIndex;
- foreach (TabPageModel pane in dock.TabPages)
- {
- MenuItem menuItem = CreateMenuItem(pane);
- pane.PropertyChanged += TabPageChanged;
- windowMenuItem.Items.Insert(insertionIndex, menuItem);
- insertionIndex++;
- }
- break;
- }
-
- MenuItem CreateMenuItem(TabPageModel pane)
- {
- MenuItem menuItem = new MenuItem();
- menuItem.Command = new TabPageCommand(pane);
- menuItem.Header = pane.Title.Length > 20 ? pane.Title.Substring(20) + "..." : pane.Title;
- menuItem.Tag = pane;
- menuItem.IsCheckable = true;
-
- return menuItem;
- }
- }
-
- static void TabPageChanged(object sender, PropertyChangedEventArgs e)
- {
- var windowMenuItem = Instance.mainMenu.Items.OfType().First(m => (string)m.Tag == nameof(Properties.Resources._Window));
- foreach (MenuItem menuItem in windowMenuItem.Items.OfType())
- {
- if (menuItem.IsCheckable && menuItem.Tag == sender)
- {
- string title = ((TabPageModel)sender).Title;
- menuItem.Header = title.Length > 20 ? title.Substring(0, 20) + "..." : title;
- }
- }
- }
- }
-
- public void ShowInTopPane(string title, object content)
- {
- var model = DockWorkspace.Instance.ToolPanes.OfType().FirstOrDefault(p => p.Content == content);
- if (model == null)
- {
- model = new LegacyToolPaneModel(title, content, LegacyToolPaneLocation.Top);
- DockWorkspace.Instance.ToolPanes.Add(model);
- }
- model.Show();
- }
-
- public void ShowInBottomPane(string title, object content)
- {
- var model = DockWorkspace.Instance.ToolPanes.OfType().FirstOrDefault(p => p.Content == content);
- if (model == null)
- {
- model = new LegacyToolPaneModel(title, content, LegacyToolPaneLocation.Bottom);
- DockWorkspace.Instance.ToolPanes.Add(model);
- }
- model.Show();
- }
- #endregion
-
#region File Loader extensibility
void InitFileLoaders()
@@ -549,27 +99,22 @@ namespace ICSharpCode.ILSpy
#endregion
#region Message Hook
+
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
- PresentationSource source = PresentationSource.FromVisual(this);
+
+ var source = PresentationSource.FromVisual(this);
var sessionSettings = SettingsService.Instance.SessionSettings;
// Validate and Set Window Bounds
- Rect bounds = Rect.Transform(sessionSettings.WindowBounds, source.CompositionTarget.TransformToDevice);
- var boundsRect = new System.Drawing.Rectangle((int)bounds.Left, (int)bounds.Top, (int)bounds.Width, (int)bounds.Height);
- bool boundsOK = false;
- foreach (var screen in System.Windows.Forms.Screen.AllScreens)
- {
- var intersection = System.Drawing.Rectangle.Intersect(boundsRect, screen.WorkingArea);
- if (intersection.Width > 10 && intersection.Height > 10)
- boundsOK = true;
- }
- if (boundsOK)
- SetWindowBounds(sessionSettings.WindowBounds);
- else
- SetWindowBounds(SessionSettings.DefaultWindowBounds);
+ var windowBounds = Rect.Transform(sessionSettings.WindowBounds, source?.CompositionTarget?.TransformToDevice ?? Matrix.Identity);
+ var boundsRect = new Rectangle((int)windowBounds.Left, (int)windowBounds.Top, (int)windowBounds.Width, (int)windowBounds.Height);
+
+ bool areBoundsValid = Screen.AllScreens.Any(screen => Rectangle.Intersect(boundsRect, screen.WorkingArea) is { Width: > 10, Height: > 10 });
+
+ SetWindowBounds(areBoundsValid ? sessionSettings.WindowBounds : SessionSettings.DefaultWindowBounds);
this.WindowState = sessionSettings.WindowState;
}
@@ -599,281 +144,11 @@ namespace ICSharpCode.ILSpy
}
}
- public AssemblyList CurrentAssemblyList {
- get { return assemblyList; }
- }
-
- List commandLineLoadedAssemblies = new List();
-
- internal async Task HandleSingleInstanceCommandLineArguments(string[] args)
- {
- var cmdArgs = CommandLineArguments.Create(args);
-
- await Dispatcher.InvokeAsync(() => {
- if (HandleCommandLineArguments(cmdArgs))
- {
- if (!cmdArgs.NoActivate && WindowState == WindowState.Minimized)
- WindowState = WindowState.Normal;
-
- HandleCommandLineArgumentsAfterShowList(cmdArgs);
- }
- });
- }
-
- 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;
- }
-
- ///
- /// 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.
- ///
- void HandleCommandLineArgumentsAfterShowList(CommandLineArguments args, ILSpySettings 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();
-
- searchPane.SearchTerm = args.Search;
- searchPane.Show();
- }
- }
-
- async void NavigateOnLaunch(string navigateTo, string[] activeTreeViewPath, ILSpySettings spySettings, List relevantAssemblies)
- {
- var initialSelection = AssemblyTreeView.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(ex => { });
- NamespaceTreeNode nsNode = asmNode.FindNamespaceNode(namespaceName);
- if (nsNode != null)
- {
- found = true;
- if (AssemblyTreeView.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 (AssemblyTreeView.SelectedItem == initialSelection)
- {
- JumpToReference(mr);
- }
- }
- }
- if (!found && AssemblyTreeView.SelectedItem == initialSelection)
- {
- AvalonEditTextOutput output = new AvalonEditTextOutput();
- output.Write(string.Format("Cannot find '{0}' in command line specified assemblies.", navigateTo));
- 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 && AssemblyTreeView.SelectedItem == initialSelection)
- {
- SelectNode(asmNode);
- }
- }
- else if (spySettings != null)
- {
- SharpTreeNode node = null;
- if (activeTreeViewPath?.Length > 0)
- {
- foreach (var asm in CurrentAssemblyList.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(ex => { });
- }
- }
- node = FindNodeByPath(activeTreeViewPath, true);
- }
- if (AssemblyTreeView.SelectedItem == initialSelection)
- {
- if (node != null)
- {
- SelectNode(node);
-
- // only if not showing the about page, perform the update check:
- await ShowMessageIfUpdatesAvailableAsync(spySettings);
- }
- else
- {
- DockWorkspace.Instance.ActiveTabPage.ShowTextView(AboutPage.Display);
- }
- }
- }
- }
-
- internal static IEntity FindEntityInRelevantAssemblies(string navigateTo, IEnumerable relevantAssemblies)
- {
- ITypeReference typeRef = null;
- 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
- : (IEntity)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;
- }
- }
-
- void MainWindow_Loaded(object sender, RoutedEventArgs e)
- {
- DockWorkspace.Instance.TabPages.Add();
-
- var loadPreviousAssemblies = Options.MiscSettingsPanel.CurrentMiscSettings.LoadPreviousAssemblies;
-
- var sessionSettings = SettingsService.Instance.SessionSettings;
-
- if (loadPreviousAssemblies)
- {
- // Load AssemblyList only in Loaded event so that WPF is initialized before we start the CPU-heavy stuff.
- // This makes the UI come up a bit faster.
- this.assemblyList = SettingsService.Instance.AssemblyListManager.LoadList(sessionSettings.ActiveAssemblyList);
- }
- else
- {
- SettingsService.Instance.AssemblyListManager.ClearAll();
- this.assemblyList = SettingsService.Instance.AssemblyListManager.CreateList(AssemblyListManager.DefaultListName);
- }
-
- HandleCommandLineArguments(App.CommandLineArguments);
-
- if (assemblyList.GetAssemblies().Length == 0
- && assemblyList.ListName == AssemblyListManager.DefaultListName
- && loadPreviousAssemblies)
- {
- LoadInitialAssemblies();
- }
-
- ShowAssemblyList(this.assemblyList);
-
- if (sessionSettings.ActiveAutoLoadedAssembly != null
- && File.Exists(sessionSettings.ActiveAutoLoadedAssembly))
- {
- this.assemblyList.Open(sessionSettings.ActiveAutoLoadedAssembly, true);
- }
-
- Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() => OpenAssemblies(SettingsService.Instance.SpySettings)));
- }
-
- void OpenAssemblies(ILSpySettings spySettings)
- {
- HandleCommandLineArgumentsAfterShowList(App.CommandLineArguments, spySettings);
-
- AvalonEditTextOutput output = new AvalonEditTextOutput();
- 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;
- }
-
#region Update Check
+
string updateAvailableDownloadUrl;
- public async Task ShowMessageIfUpdatesAvailableAsync(ILSpySettings spySettings, bool forceCheck = false)
+ public async Task ShowMessageIfUpdatesAvailableAsync(ISettingsProvider spySettings, bool forceCheck = false)
{
string downloadUrl;
if (forceCheck)
@@ -889,21 +164,21 @@ namespace ICSharpCode.ILSpy
AdjustUpdateUIAfterCheck(downloadUrl, forceCheck);
}
- void updatePanelCloseButtonClick(object sender, RoutedEventArgs e)
+ void UpdatePanelCloseButtonClick(object sender, RoutedEventArgs e)
{
updatePanel.Visibility = Visibility.Collapsed;
}
- async void downloadOrCheckUpdateButtonClick(object sender, RoutedEventArgs e)
+ async void DownloadOrCheckUpdateButtonClick(object sender, RoutedEventArgs e)
{
if (updateAvailableDownloadUrl != null)
{
- MainWindow.OpenLink(updateAvailableDownloadUrl);
+ OpenLink(updateAvailableDownloadUrl);
}
else
{
updatePanel.Visibility = Visibility.Collapsed;
- string downloadUrl = await NotifyOfUpdatesStrategy.CheckForUpdatesAsync(ILSpySettings.Load());
+ string downloadUrl = await NotifyOfUpdatesStrategy.CheckForUpdatesAsync(SettingsService.Instance.SpySettings);
AdjustUpdateUIAfterCheck(downloadUrl, true);
}
}
@@ -923,327 +198,8 @@ namespace ICSharpCode.ILSpy
downloadOrCheckUpdateButton.Content = Properties.Resources.CheckAgain;
}
}
- #endregion
-
- 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 != CurrentAssemblyList.ListName)
- {
- ShowAssemblyList(list);
- SelectNode(AssemblyTreeView.Root);
- }
- }
- void ShowAssemblyList(AssemblyList assemblyList)
- {
- history.Clear();
- if (this.assemblyList != null)
- {
- this.assemblyList.CollectionChanged -= assemblyList_Assemblies_CollectionChanged;
- }
-
- this.assemblyList = assemblyList;
- assemblyList.CollectionChanged += assemblyList_Assemblies_CollectionChanged;
-
- assemblyListTreeNode = new AssemblyListTreeNode(assemblyList);
- assemblyListTreeNode.Select = x => SelectNode(x, inNewTabPage: false);
- AssemblyTreeView.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_Assemblies_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
- {
- if (e.Action == NotifyCollectionChangedAction.Reset)
- {
- history.RemoveAll(_ => true);
- }
- if (e.OldItems != null)
- {
- var oldAssemblies = new HashSet(e.OldItems.Cast());
- history.RemoveAll(n => n.TreeNodes.Any(
- nd => nd.AncestorsAndSelf().OfType().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);
- }
-
- void LanguageSettings_PropertyChanged(object sender, PropertyChangedEventArgs e)
- {
- if (e.PropertyName == "Language" || e.PropertyName == "LanguageVersion")
- {
- DecompileSelectedNodes(recordHistory: false);
- }
- }
-
- internal AssemblyListTreeNode AssemblyListTreeNode {
- get { return assemblyListTreeNode; }
- }
-
- #region Node Selection
-
- public void SelectNode(SharpTreeNode obj)
- {
- SelectNode(obj, false);
- }
-
- public void SelectNode(SharpTreeNode obj, bool inNewTabPage)
- {
- SelectNode(obj, inNewTabPage, true);
- }
-
- public void SelectNode(SharpTreeNode obj, bool inNewTabPage, bool setFocus)
- {
- if (obj != null)
- {
- if (!obj.AncestorsAndSelf().Any(node => node.IsHidden))
- {
- if (inNewTabPage)
- {
- DockWorkspace.Instance.TabPages.Add();
- AssemblyTreeView.SelectedItem = null;
- }
-
- // Set both the selection and focus to ensure that keyboard navigation works as expected.
- if (setFocus)
- {
- AssemblyTreeView.FocusNode(obj);
- }
- else
- {
- AssemblyTreeView.ScrollIntoView(obj);
- }
- AssemblyTreeView.SelectedItem = obj;
- }
- else
- {
- MessageBox.Show(Properties.Resources.NavigationFailed, "ILSpy", MessageBoxButton.OK, MessageBoxImage.Exclamation);
- }
- }
- }
-
- public void SelectNodes(IEnumerable nodes)
- {
- SelectNodes(nodes, false);
- }
-
- public void SelectNodes(IEnumerable nodes, bool inNewTabPage)
- {
- SelectNodes(nodes, inNewTabPage, true);
- }
-
- public void SelectNodes(IEnumerable nodes, bool inNewTabPage, bool setFocus)
- {
- SelectNodes(nodes, inNewTabPage, setFocus, false);
- }
-
- internal void SelectNodes(IEnumerable nodes, bool inNewTabPage,
- bool setFocus, bool changingActiveTab)
- {
- if (inNewTabPage)
- {
- DockWorkspace.Instance.TabPages.Add();
- }
-
- // Ensure nodes exist
- var nodesList = nodes.Select(n => FindNodeByPath(GetPathForNode(n), true))
- .Where(n => n != null).ToArray();
-
- if (!nodesList.Any() || !nodesList.All(n => !n.AncestorsAndSelf().Any(a => a.IsHidden)))
- {
- return;
- }
-
- this.changingActiveTab = changingActiveTab || inNewTabPage;
- try
- {
- if (setFocus)
- {
- AssemblyTreeView.FocusNode(nodesList[0]);
- }
- else
- {
- AssemblyTreeView.ScrollIntoView(nodesList[0]);
- }
-
- AssemblyTreeView.SetSelectedNodes(nodesList);
- }
- finally
- {
- this.changingActiveTab = false;
- }
- }
-
- ///
- /// Retrieves a node using the .ToString() representations of its ancestors.
- ///
- public SharpTreeNode FindNodeByPath(string[] path, bool returnBestMatch)
- {
- if (path == null)
- return null;
- SharpTreeNode node = AssemblyTreeView.Root;
- SharpTreeNode bestMatch = node;
- foreach (var element in path)
- {
- if (node == null)
- break;
- bestMatch = node;
- node.EnsureLazyChildren();
- var ilSpyTreeNode = node as ILSpyTreeNode;
- if (ilSpyTreeNode != null)
- ilSpyTreeNode.EnsureChildrenFiltered();
- node = node.Children.FirstOrDefault(c => c.ToString() == element);
- }
- if (returnBestMatch)
- return node ?? bestMatch;
- else
- return node;
- }
-
- ///
- /// Gets the .ToString() representation of the node's ancestors.
- ///
- public static string[] GetPathForNode(SharpTreeNode node)
- {
- if (node == null)
- return null;
- List path = new List();
- 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 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;
- }
- }
-
- public void JumpToReference(object reference)
- {
- JumpToReference(reference, inNewTabPage: false);
- }
-
- public void JumpToReference(object reference, bool inNewTabPage)
- {
- JumpToReferenceAsync(reference, inNewTabPage).HandleExceptions();
- }
-
- ///
- /// Jumps to the specified reference.
- ///
- ///
- /// 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.
- ///
- public Task JumpToReferenceAsync(object reference)
- {
- return JumpToReferenceAsync(reference, inNewTabPage: false);
- }
-
- public Task JumpToReferenceAsync(object reference, bool inNewTabPage)
- {
- decompilationTask = TaskHelper.CompletedTask;
- switch (reference)
- {
- case Decompiler.Disassembler.OpCodeInfo opCode:
- OpenLink(opCode.Link);
- break;
- case EntityReference unresolvedEntity:
- string protocol = unresolvedEntity.Protocol ?? "decompile";
- var file = unresolvedEntity.ResolveAssembly(assemblyList);
- if (file == null)
- {
- break;
- }
- if (protocol != "decompile")
- {
- var protocolHandlers = App.ExportProvider.GetExports();
- foreach (var handler in protocolHandlers)
- {
- var node = handler.Value.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 static void OpenLink(string link)
{
@@ -1274,356 +230,44 @@ namespace ICSharpCode.ILSpy
// just ignore all of them.
}
}
- #endregion
-
- #region Open/Refresh
- void OpenCommandExecuted(object sender, ExecutedRoutedEventArgs e)
- {
- e.Handled = true;
- OpenFileDialog dlg = new OpenFileDialog();
- dlg.Filter = ".NET assemblies|*.dll;*.exe;*.winmd;*.wasm|Nuget Packages (*.nupkg)|*.nupkg|Portable Program Database (*.pdb)|*.pdb|All files|*.*";
- dlg.Multiselect = true;
- dlg.RestoreDirectory = true;
- if (dlg.ShowDialog() == true)
- {
- OpenFiles(dlg.FileNames);
- }
- }
-
- public void OpenFiles(string[] fileNames, bool focusNode = true)
- {
- if (fileNames == null)
- throw new ArgumentNullException(nameof(fileNames));
-
- if (focusNode)
- AssemblyTreeView.UnselectAll();
-
- LoadAssemblies(fileNames, focusNode: focusNode);
- }
-
- void LoadAssemblies(IEnumerable fileNames, List loadedAssemblies = null, bool focusNode = true)
- {
- SharpTreeNode lastNode = null;
- foreach (string file in fileNames)
- {
- var asm = assemblyList.OpenAssembly(file);
- if (asm != null)
- {
- if (loadedAssemblies != null)
- {
- loadedAssemblies.Add(asm);
- }
- else
- {
- var node = assemblyListTreeNode.FindAssemblyNode(asm);
- if (node != null && focusNode)
- {
- AssemblyTreeView.SelectedItems.Add(node);
- lastNode = node;
- }
- }
- }
-
- if (lastNode != null && focusNode)
- AssemblyTreeView.FocusNode(lastNode);
- }
- }
-
- void RefreshCommandExecuted(object sender, ExecutedRoutedEventArgs e)
- {
- try
- {
- refreshInProgress = true;
- var path = GetPathForNode(AssemblyTreeView.SelectedItem as SharpTreeNode);
- ShowAssemblyList(SettingsService.Instance.AssemblyListManager.LoadList(assemblyList.ListName));
- SelectNode(FindNodeByPath(path, true), inNewTabPage: false, AssemblyTreeView.IsFocused);
- }
- finally
- {
- refreshInProgress = false;
- }
- }
-
- void SearchCommandExecuted(object sender, ExecutedRoutedEventArgs e)
- {
- DockWorkspace.Instance.ShowToolPane(SearchPaneModel.PaneContentId);
- }
- #endregion
-
- #region Decompile (TreeView_SelectionChanged)
- bool delayDecompilationRequestDueToContextMenu;
-
- protected override void OnContextMenuClosing(ContextMenuEventArgs e)
- {
- base.OnContextMenuClosing(e);
-
- if (delayDecompilationRequestDueToContextMenu)
- {
- delayDecompilationRequestDueToContextMenu = false;
- var state = DockWorkspace.Instance.ActiveTabPage.GetState() as DecompilerTextViewState;
- DecompileSelectedNodes(state);
- }
- }
-
- void TreeView_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- DecompilerTextViewState state = null;
- if (refreshInProgress || changingActiveTab)
- {
- state = DockWorkspace.Instance.ActiveTabPage.GetState() as DecompilerTextViewState;
- }
-
- this.delayDecompilationRequestDueToContextMenu = Mouse.RightButton == MouseButtonState.Pressed;
- if (!changingActiveTab && !delayDecompilationRequestDueToContextMenu)
- {
- DecompileSelectedNodes(state);
- }
-
- SelectionChanged?.Invoke(sender, e);
- }
-
- Task decompilationTask;
- bool ignoreDecompilationRequests;
-
- void DecompileSelectedNodes(DecompilerTextViewState newState = null, bool recordHistory = true)
- {
- if (ignoreDecompilationRequests)
- return;
-
- if (AssemblyTreeView.SelectedItems.Count == 0 && refreshInProgress)
- return;
-
- if (recordHistory)
- {
- var tabPage = DockWorkspace.Instance.ActiveTabPage;
- var currentState = tabPage.GetState();
- if (currentState != null)
- history.UpdateCurrent(new NavigationState(tabPage, currentState));
- history.Record(new NavigationState(tabPage, AssemblyTreeView.SelectedItems.OfType()));
- }
-
- DockWorkspace.Instance.ActiveTabPage.SupportsLanguageSwitching = true;
-
- if (AssemblyTreeView.SelectedItems.Count == 1)
- {
- ILSpyTreeNode node = AssemblyTreeView.SelectedItem as ILSpyTreeNode;
- if (node != null && node.View(DockWorkspace.Instance.ActiveTabPage))
- return;
- }
- if (newState?.ViewedUri != null)
- {
- NavigateTo(new RequestNavigateEventArgs(newState.ViewedUri, null), recordHistory: false);
- return;
- }
- var options = MainWindow.Instance.CreateDecompilationOptions();
- options.TextViewState = newState;
- decompilationTask = DockWorkspace.Instance.ActiveTabPage.ShowTextViewAsync(
- textView => textView.DecompileAsync(this.CurrentLanguage, this.SelectedNodes, options)
- );
- }
-
- void SaveCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
- {
- e.Handled = true;
- e.CanExecute = SaveCodeContextMenuEntry.CanExecute(SelectedNodes.ToList());
- }
-
- void SaveCommandExecuted(object sender, ExecutedRoutedEventArgs e)
- {
- SaveCodeContextMenuEntry.Execute(SelectedNodes.ToList());
- }
-
- public void RefreshDecompiledView()
- {
- try
- {
- refreshInProgress = true;
- DecompileSelectedNodes();
- }
- finally
- {
- refreshInProgress = false;
- }
- }
-
- public Language CurrentLanguage => SettingsService.Instance.SessionSettings.LanguageSettings.Language;
-
- public LanguageVersion CurrentLanguageVersion => SettingsService.Instance.SessionSettings.LanguageSettings.LanguageVersion;
-
- public event SelectionChangedEventHandler SelectionChanged;
-
- public IEnumerable SelectedNodes {
- get {
- return AssemblyTreeView.GetTopLevelSelection().OfType();
- }
- }
- #endregion
-
- #region Back/Forward navigation
- void BackCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
- {
- e.Handled = true;
- e.CanExecute = history.CanNavigateBack;
- }
-
- void BackCommandExecuted(object sender, ExecutedRoutedEventArgs e)
- {
- if (history.CanNavigateBack)
- {
- e.Handled = true;
- NavigateHistory(false);
- }
- }
-
- void ForwardCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
- {
- e.Handled = true;
- e.CanExecute = history.CanNavigateForward;
- }
-
- void ForwardCommandExecuted(object sender, ExecutedRoutedEventArgs e)
- {
- if (history.CanNavigateForward)
- {
- e.Handled = true;
- NavigateHistory(true);
- }
- }
-
- 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();
-
- ignoreDecompilationRequests = true;
- AssemblyTreeView.SelectedItems.Clear();
- DockWorkspace.Instance.ActiveTabPage = newState.TabPage;
- foreach (var node in newState.TreeNodes)
- {
- AssemblyTreeView.SelectedItems.Add(node);
- }
- if (newState.TreeNodes.Any())
- AssemblyTreeView.FocusNode(newState.TreeNodes.First());
- ignoreDecompilationRequests = false;
- DecompileSelectedNodes(newState.ViewState as DecompilerTextViewState, false);
- }
- #endregion
-
- internal void NavigateTo(RequestNavigateEventArgs e, bool recordHistory = true, bool inNewTabPage = false)
- {
- if (e.Uri.Scheme == "resource")
- {
- if (inNewTabPage)
- {
- DockWorkspace.Instance.TabPages.Add();
- }
-
- 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));
- ignoreDecompilationRequests = true;
- UnselectAll();
- ignoreDecompilationRequests = false;
- history.Record(new NavigationState(tabPage, new ViewState { ViewedUri = e.Uri }));
- }
- }
protected override void OnStateChanged(EventArgs e)
{
base.OnStateChanged(e);
// store window state in settings only if it's not minimized
- if (this.WindowState != System.Windows.WindowState.Minimized)
+ if (this.WindowState != WindowState.Minimized)
SettingsService.Instance.SessionSettings.WindowState = this.WindowState;
}
protected override void OnClosing(CancelEventArgs e)
{
base.OnClosing(e);
- var sessionSettings = SettingsService.Instance.SessionSettings;
- sessionSettings.ActiveAssemblyList = assemblyList.ListName;
- sessionSettings.ActiveTreeViewPath = GetPathForNode(AssemblyTreeView.SelectedItem as SharpTreeNode);
- sessionSettings.ActiveAutoLoadedAssembly = GetAutoLoadedAssemblyNode(AssemblyTreeView.SelectedItem as SharpTreeNode);
- sessionSettings.WindowBounds = this.RestoreBounds;
- sessionSettings.DockLayout.Serialize(new XmlLayoutSerializer(dockManager));
- sessionSettings.Save();
- }
+ var snapshot = SettingsService.Instance.CreateSnapshot();
- private string GetAutoLoadedAssemblyNode(SharpTreeNode node)
- {
- if (node == null)
- return null;
- while (!(node is TreeNodes.AssemblyTreeNode) && node.Parent != null)
- {
- node = node.Parent;
- }
- //this should be an assembly node
- var assyNode = node as TreeNodes.AssemblyTreeNode;
- var loadedAssy = assyNode.LoadedAssembly;
- if (!(loadedAssy.IsLoaded && loadedAssy.IsAutoLoaded))
- return null;
+ var sessionSettings = snapshot.GetSettings();
- return loadedAssy.FileName;
- }
+ sessionSettings.ActiveAssemblyList = AssemblyTreeModel.AssemblyList.ListName;
+ sessionSettings.ActiveTreeViewPath = AssemblyTreeModel.SelectedPath;
+ sessionSettings.ActiveAutoLoadedAssembly = GetAutoLoadedAssemblyNode(AssemblyTreeModel.SelectedItem);
+ sessionSettings.WindowBounds = this.RestoreBounds;
+ sessionSettings.DockLayout.Serialize(new XmlLayoutSerializer(dockManager));
- public void UnselectAll()
- {
- AssemblyTreeView.UnselectAll();
+ snapshot.Save();
}
- public void SetStatus(string status, Brush foreground)
+ private static string GetAutoLoadedAssemblyNode(SharpTreeNode node)
{
- if (this.statusBar.Visibility == Visibility.Collapsed)
- this.statusBar.Visibility = Visibility.Visible;
- this.statusLabel.Foreground = foreground;
- this.statusLabel.Text = status;
- }
+ var assemblyTreeNode = node?
+ .AncestorsAndSelf()
+ .OfType()
+ .FirstOrDefault();
- public ItemCollection GetMainMenuItems()
- {
- return mainMenu.Items;
- }
+ var loadedAssembly = assemblyTreeNode?.LoadedAssembly;
- public ItemCollection GetToolBarItems()
- {
- return toolBar.Items;
+ return loadedAssembly is not { IsLoaded: true, IsAutoLoaded: true }
+ ? null
+ : loadedAssembly.FileName;
}
}
}
diff --git a/ILSpy/MainWindowViewModel.cs b/ILSpy/MainWindowViewModel.cs
index 16b2cc0fd..270f007ec 100644
--- a/ILSpy/MainWindowViewModel.cs
+++ b/ILSpy/MainWindowViewModel.cs
@@ -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;
}
}
diff --git a/ILSpy/Metadata/CoffHeaderTreeNode.cs b/ILSpy/Metadata/CoffHeaderTreeNode.cs
index bcce1ef1a..36b9c8be8 100644
--- a/ILSpy/Metadata/CoffHeaderTreeNode.cs
+++ b/ILSpy/Metadata/CoffHeaderTreeNode.cs
@@ -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
@@ -104,7 +106,6 @@ namespace ICSharpCode.ILSpy.Metadata
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
- language.WriteCommentLine(output, "COFF Header");
}
}
diff --git a/ILSpy/Metadata/CorTables/AssemblyRefTableTreeNode.cs b/ILSpy/Metadata/CorTables/AssemblyRefTableTreeNode.cs
index 43cc98f86..d47f49a1a 100644
--- a/ILSpy/Metadata/CorTables/AssemblyRefTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/AssemblyRefTableTreeNode.cs
@@ -22,7 +22,6 @@ using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -30,12 +29,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class AssemblyRefTableTreeNode : MetadataTableTreeNode
{
public AssemblyRefTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.AssemblyReference, metadataFile)
+ : base(TableIndex.AssemblyRef, metadataFile)
{
}
- public override object Text => $"23 AssemblyRef ({metadataFile.Metadata.GetTableRowCount(TableIndex.AssemblyRef)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -116,10 +113,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.assemblyRef = metadataFile.Metadata.GetAssemblyReference(handle);
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "AssemblyRef");
- }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/CorTables/AssemblyTableTreeNode.cs b/ILSpy/Metadata/CorTables/AssemblyTableTreeNode.cs
index f4f2f52ab..66332e212 100644
--- a/ILSpy/Metadata/CorTables/AssemblyTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/AssemblyTableTreeNode.cs
@@ -21,7 +21,6 @@ using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -29,12 +28,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class AssemblyTableTreeNode : MetadataTableTreeNode
{
public AssemblyTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.AssemblyDefinition, metadataFile)
+ : base(TableIndex.Assembly, metadataFile)
{
}
- public override object Text => $"20 Assembly ({metadataFile.Metadata.GetTableRowCount(TableIndex.Assembly)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -99,10 +96,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.assembly = metadata.GetAssemblyDefinition();
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "Assembly");
- }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs b/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs
index 6607b16b5..4d654da91 100644
--- a/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ClassLayoutTableTreeNode.cs
@@ -22,7 +22,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -30,12 +29,10 @@ namespace ICSharpCode.ILSpy.Metadata
class ClassLayoutTableTreeNode : MetadataTableTreeNode
{
public ClassLayoutTableTreeNode(MetadataFile metadataFile)
- : base((HandleKind)0x0F, metadataFile)
+ : base(TableIndex.ClassLayout, metadataFile)
{
}
- public override object Text => $"0F ClassLayout ({metadataFile.Metadata.GetTableRowCount(TableIndex.ClassLayout)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -100,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;
@@ -124,10 +121,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.parentTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "ClassLayouts");
- }
}
}
diff --git a/ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs b/ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs
index f51aa9a85..2b2ea571f 100644
--- a/ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ConstantTableTreeNode.cs
@@ -20,7 +20,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.ViewModels;
@@ -29,12 +28,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class ConstantTableTreeNode : MetadataTableTreeNode
{
public ConstantTableTreeNode(MetadataFile metadataFile)
- : base((HandleKind)0x0B, metadataFile)
+ : base(TableIndex.Constant, metadataFile)
{
}
- public override object Text => $"0B Constant ({metadataFile.Metadata.GetTableRowCount(TableIndex.Constant)})";
-
public override bool View(TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -91,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;
@@ -114,10 +111,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.parentTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "Constants");
- }
}
}
diff --git a/ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs b/ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs
index 706a1f34e..370532d14 100644
--- a/ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/CustomAttributeTableTreeNode.cs
@@ -20,7 +20,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -28,12 +27,10 @@ namespace ICSharpCode.ILSpy.Metadata
class CustomAttributeTableTreeNode : MetadataTableTreeNode
{
public CustomAttributeTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.CustomAttribute, metadataFile)
+ : base(TableIndex.CustomAttribute, metadataFile)
{
}
- public override object Text => $"0C CustomAttribute ({metadataFile.Metadata.GetTableRowCount(TableIndex.CustomAttribute)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -86,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;
@@ -97,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;
@@ -121,10 +118,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.constructorTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "CustomAttributes");
- }
}
}
diff --git a/ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs b/ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs
index b43a109fd..f37bdb87d 100644
--- a/ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/DeclSecurityTableTreeNode.cs
@@ -21,7 +21,6 @@ using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -29,12 +28,10 @@ namespace ICSharpCode.ILSpy.Metadata
class DeclSecurityTableTreeNode : MetadataTableTreeNode
{
public DeclSecurityTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.DeclarativeSecurityAttribute, metadataFile)
+ : base(TableIndex.DeclSecurity, metadataFile)
{
}
- public override object Text => $"0E DeclSecurity ({metadataFile.Metadata.GetTableRowCount(TableIndex.DeclSecurity)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -87,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;
@@ -119,10 +116,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.parentTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "DeclSecurityAttrs");
- }
}
}
diff --git a/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs b/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs
index d5b822b79..3018d8970 100644
--- a/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/EventMapTableTreeNode.cs
@@ -21,7 +21,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -29,12 +28,10 @@ namespace ICSharpCode.ILSpy.Metadata
class EventMapTableTreeNode : MetadataTableTreeNode
{
public EventMapTableTreeNode(MetadataFile metadataFile)
- : base((HandleKind)0x12, metadataFile)
+ : base(TableIndex.EventMap, metadataFile)
{
}
- public override object Text => $"12 EventMap ({metadataFile.Metadata.GetTableRowCount(TableIndex.EventMap)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -98,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;
@@ -109,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;
@@ -129,10 +126,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.eventListTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "EventMap");
- }
}
}
diff --git a/ILSpy/Metadata/CorTables/EventTableTreeNode.cs b/ILSpy/Metadata/CorTables/EventTableTreeNode.cs
index 680952090..14dabb3e0 100644
--- a/ILSpy/Metadata/CorTables/EventTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/EventTableTreeNode.cs
@@ -21,7 +21,6 @@ using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TreeNodes;
@@ -31,12 +30,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class EventTableTreeNode : MetadataTableTreeNode
{
public EventTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.EventDefinition, metadataFile)
+ : base(TableIndex.Event, metadataFile)
{
}
- public override object Text => $"14 Event ({metadataFile.Metadata.GetTableRowCount(TableIndex.Event)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -106,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;
@@ -120,10 +117,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.typeTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "EventDefs");
- }
}
}
diff --git a/ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs b/ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs
index 4cf078465..f1075c16b 100644
--- a/ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ExportedTypeTableTreeNode.cs
@@ -21,7 +21,6 @@ using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -29,12 +28,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class ExportedTypeTableTreeNode : MetadataTableTreeNode
{
public ExportedTypeTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.ExportedType, metadataFile)
+ : base(TableIndex.ExportedType, metadataFile)
{
}
- public override object Text => $"27 ExportedType ({metadataFile.Metadata.GetTableRowCount(TableIndex.ExportedType)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -110,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;
@@ -124,10 +121,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.implementationTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "ExportedType");
- }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs
index 38c41bff7..6fe92c597 100644
--- a/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/FieldLayoutTableTreeNode.cs
@@ -22,7 +22,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -30,12 +29,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class FieldLayoutTableTreeNode : MetadataTableTreeNode
{
public FieldLayoutTableTreeNode(MetadataFile metadataFile)
- : base((HandleKind)0x10, metadataFile)
+ : base(TableIndex.FieldLayout, metadataFile)
{
}
- public override object Text => $"10 FieldLayout ({metadataFile.Metadata.GetTableRowCount(TableIndex.FieldLayout)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -99,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;
@@ -120,10 +117,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.fieldTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "FieldLayouts");
- }
}
}
diff --git a/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs
index db2091180..befd90a8c 100644
--- a/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/FieldMarshalTableTreeNode.cs
@@ -21,7 +21,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -29,12 +28,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class FieldMarshalTableTreeNode : MetadataTableTreeNode
{
public FieldMarshalTableTreeNode(MetadataFile metadataFile)
- : base((HandleKind)0x0D, metadataFile)
+ : base(TableIndex.FieldMarshal, metadataFile)
{
}
- public override object Text => $"0D FieldMarshal ({metadataFile.Metadata.GetTableRowCount(TableIndex.FieldMarshal)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -98,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;
@@ -120,10 +117,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.parentTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "FieldMarshals");
- }
}
}
diff --git a/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs
index 43f6e738f..959225bdb 100644
--- a/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/FieldRVATableTreeNode.cs
@@ -22,7 +22,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -30,7 +29,7 @@ namespace ICSharpCode.ILSpy.Metadata
internal class FieldRVATableTreeNode : MetadataTableTreeNode
{
public FieldRVATableTreeNode(MetadataFile metadataFile)
- : base((HandleKind)0x1D, metadataFile)
+ : base(TableIndex.FieldRva, metadataFile)
{
}
@@ -100,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;
@@ -121,10 +120,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.fieldTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "FieldRVAs");
- }
}
}
diff --git a/ILSpy/Metadata/CorTables/FieldTableTreeNode.cs b/ILSpy/Metadata/CorTables/FieldTableTreeNode.cs
index 16c3ca9d2..c8e8e310d 100644
--- a/ILSpy/Metadata/CorTables/FieldTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/FieldTableTreeNode.cs
@@ -16,13 +16,11 @@
// 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.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TreeNodes;
@@ -32,12 +30,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class FieldTableTreeNode : MetadataTableTreeNode
{
public FieldTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.FieldDefinition, metadataFile)
+ : base(TableIndex.Field, metadataFile)
{
}
- public override object Text => $"04 Field ({metadataFile.Metadata.GetTableRowCount(TableIndex.Field)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -115,29 +111,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.signatureTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "FieldDefs");
- }
- }
-}
-
-class Time : IDisposable
-{
- readonly System.Diagnostics.Stopwatch stopwatch;
- readonly string title;
-
- public Time(string title)
- {
- this.title = title;
- this.stopwatch = new System.Diagnostics.Stopwatch();
- stopwatch.Start();
- }
-
- public void Dispose()
- {
- stopwatch.Stop();
- System.Diagnostics.Debug.WriteLine(title + " took " + stopwatch.ElapsedMilliseconds + "ms");
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/CorTables/FileTableTreeNode.cs b/ILSpy/Metadata/CorTables/FileTableTreeNode.cs
index 183c2a75f..f48edcb39 100644
--- a/ILSpy/Metadata/CorTables/FileTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/FileTableTreeNode.cs
@@ -20,7 +20,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -28,12 +27,10 @@ namespace ICSharpCode.ILSpy.Metadata
class FileTableTreeNode : MetadataTableTreeNode
{
public FileTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.AssemblyFile, metadataFile)
+ : base(TableIndex.File, metadataFile)
{
}
- public override object Text => $"26 File ({metadataFile.Metadata.GetTableRowCount(TableIndex.File)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -110,9 +107,5 @@ namespace ICSharpCode.ILSpy.Metadata
}
}
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "Files");
- }
}
}
diff --git a/ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs b/ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs
index a65be0a87..0e2180210 100644
--- a/ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/GenericParamConstraintTableTreeNode.cs
@@ -29,12 +29,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class GenericParamConstraintTableTreeNode : MetadataTableTreeNode
{
public GenericParamConstraintTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.GenericParameterConstraint, metadataFile)
+ : base(TableIndex.GenericParamConstraint, metadataFile)
{
}
- public override object Text => $"2C GenericParamConstraint ({metadataFile.Metadata.GetTableRowCount(TableIndex.GenericParamConstraint)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -86,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;
@@ -110,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;
@@ -125,10 +123,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.typeTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "GenericParamConstraints");
- }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs b/ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs
index 6d8ce43e9..29509426b 100644
--- a/ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/GenericParamTableTreeNode.cs
@@ -21,7 +21,6 @@ using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -29,12 +28,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class GenericParamTableTreeNode : MetadataTableTreeNode
{
public GenericParamTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.GenericParameter, metadataFile)
+ : base(TableIndex.GenericParam, metadataFile)
{
}
- public override object Text => $"2A GenericParam ({metadataFile.Metadata.GetTableRowCount(TableIndex.GenericParam)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -95,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;
@@ -113,10 +110,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.ownerTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "GenericParams");
- }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs b/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs
index 2976597b0..efe6e6fa1 100644
--- a/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ImplMapTableTreeNode.cs
@@ -22,7 +22,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using Mono.Cecil;
@@ -32,14 +31,10 @@ namespace ICSharpCode.ILSpy.Metadata
class ImplMapTableTreeNode : MetadataTableTreeNode
{
public ImplMapTableTreeNode(MetadataFile metadataFile)
- : base((HandleKind)0x1C, metadataFile)
+ : base(TableIndex.ImplMap, metadataFile)
{
}
- public override object Text => $"1C ImplMap ({metadataFile.Metadata.GetTableRowCount(TableIndex.ImplMap)})";
-
-
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -118,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;
@@ -129,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;
@@ -154,10 +149,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.memberForwardedTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "ImplMap");
- }
}
}
diff --git a/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs b/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs
index 92cefd2c4..04b87015d 100644
--- a/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/InterfaceImplTableTreeNode.cs
@@ -21,7 +21,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -29,12 +28,10 @@ namespace ICSharpCode.ILSpy.Metadata
class InterfaceImplTableTreeNode : MetadataTableTreeNode
{
public InterfaceImplTableTreeNode(MetadataFile metadataFile)
- : base((HandleKind)0x09, metadataFile)
+ : base(TableIndex.InterfaceImpl, metadataFile)
{
}
- public override object Text => $"09 InterfaceImpl ({metadataFile.Metadata.GetTableRowCount(TableIndex.InterfaceImpl)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -99,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;
@@ -110,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;
@@ -128,10 +125,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.classTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "InterfaceImpls");
- }
}
}
diff --git a/ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs b/ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs
index 1247899d7..5bd75eb91 100644
--- a/ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ManifestResourceTableTreeNode.cs
@@ -21,7 +21,6 @@ using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -29,12 +28,10 @@ namespace ICSharpCode.ILSpy.Metadata
class ManifestResourceTableTreeNode : MetadataTableTreeNode
{
public ManifestResourceTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.ManifestResource, metadataFile)
+ : base(TableIndex.ManifestResource, metadataFile)
{
}
- public override object Text => $"28 ManifestResource ({metadataFile.Metadata.GetTableRowCount(TableIndex.ManifestResource)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -96,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;
@@ -110,10 +107,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.implementationTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "ManifestResources");
- }
}
}
diff --git a/ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs b/ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs
index 17d368a68..9f858434d 100644
--- a/ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/MemberRefTableTreeNode.cs
@@ -20,7 +20,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -28,12 +27,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class MemberRefTableTreeNode : MetadataTableTreeNode
{
public MemberRefTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.MemberReference, metadataFile)
+ : base(TableIndex.MemberRef, metadataFile)
{
}
- public override object Text => $"0A MemberRef ({metadataFile.Metadata.GetTableRowCount(TableIndex.MemberRef)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -86,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;
@@ -111,10 +108,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.parentTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "MemberRefs");
- }
}
}
diff --git a/ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs b/ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs
index e69470480..2344f6ff1 100644
--- a/ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/MethodImplTableTreeNode.cs
@@ -20,7 +20,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -28,12 +27,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class MethodImplTableTreeNode : MetadataTableTreeNode
{
public MethodImplTableTreeNode(MetadataFile metadataFile)
- : base((HandleKind)0x19, metadataFile)
+ : base(TableIndex.MethodImpl, metadataFile)
{
}
- public override object Text => $"19 MethodImpl ({metadataFile.Metadata.GetTableRowCount(TableIndex.MethodImpl)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -85,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;
@@ -96,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;
@@ -107,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;
@@ -123,10 +120,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.methodDeclarationTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "MethodImpls");
- }
}
}
diff --git a/ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs b/ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs
index 423473367..49cb863f0 100644
--- a/ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/MethodSemanticsTableTreeNode.cs
@@ -21,7 +21,6 @@ using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -29,12 +28,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class MethodSemanticsTableTreeNode : MetadataTableTreeNode
{
public MethodSemanticsTableTreeNode(MetadataFile metadataFile)
- : base((HandleKind)0x18, metadataFile)
+ : base(TableIndex.MethodSemantics, metadataFile)
{
}
- public override object Text => $"18 MethodSemantics ({metadataFile.Metadata.GetTableRowCount(TableIndex.MethodSemantics)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -93,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;
@@ -104,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;
@@ -121,10 +118,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.associationTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "MethodDefs");
- }
}
}
diff --git a/ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs b/ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs
index 64b6b5ee5..d25a71dd3 100644
--- a/ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/MethodSpecTableTreeNode.cs
@@ -29,12 +29,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class MethodSpecTableTreeNode : MetadataTableTreeNode
{
public MethodSpecTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.MethodSpecification, metadataFile)
+ : base(TableIndex.MethodSpec, metadataFile)
{
}
- public override object Text => $"2B MethodSpec ({metadataFile.Metadata.GetTableRowCount(TableIndex.MethodSpec)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -87,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;
@@ -121,10 +119,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.methodTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "MethodSpecs");
- }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/CorTables/MethodTableTreeNode.cs b/ILSpy/Metadata/CorTables/MethodTableTreeNode.cs
index eaa49d1d6..cfea5f2ae 100644
--- a/ILSpy/Metadata/CorTables/MethodTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/MethodTableTreeNode.cs
@@ -22,7 +22,6 @@ using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TreeNodes;
@@ -32,12 +31,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class MethodTableTreeNode : MetadataTableTreeNode
{
public MethodTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.MethodDefinition, metadataFile)
+ : base(TableIndex.MethodDef, metadataFile)
{
}
- public override object Text => $"06 Method ({metadataFile.Metadata.GetTableRowCount(TableIndex.MethodDef)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -121,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;
@@ -145,10 +142,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.paramListTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "MethodDefs");
- }
}
}
diff --git a/ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs b/ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs
index 8ef4ab4f6..46ed75734 100644
--- a/ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ModuleRefTableTreeNode.cs
@@ -20,7 +20,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -28,12 +27,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class ModuleRefTableTreeNode : MetadataTableTreeNode
{
public ModuleRefTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.ModuleReference, metadataFile)
+ : base(TableIndex.ModuleRef, metadataFile)
{
}
- public override object Text => $"1A ModuleRef ({metadataFile.Metadata.GetTableRowCount(TableIndex.ModuleRef)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -92,10 +89,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.moduleRef = metadataFile.Metadata.GetModuleReference(handle);
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "ModuleRefs");
- }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/CorTables/ModuleTableTreeNode.cs b/ILSpy/Metadata/CorTables/ModuleTableTreeNode.cs
index 6073d85bb..490d0ed5c 100644
--- a/ILSpy/Metadata/CorTables/ModuleTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ModuleTableTreeNode.cs
@@ -20,7 +20,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -28,12 +27,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class ModuleTableTreeNode : MetadataTableTreeNode
{
public ModuleTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.ModuleDefinition, metadataFile)
+ : base(TableIndex.Module, metadataFile)
{
}
- public override object Text => $"00 Module ({metadataFile.Metadata.GetTableRowCount(TableIndex.Module)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -100,10 +97,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.moduleDef = metadataFile.Metadata.GetModuleDefinition();
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "Modules");
- }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs b/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs
index d75043bfa..e95619be7 100644
--- a/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/NestedClassTableTreeNode.cs
@@ -21,7 +21,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -29,12 +28,10 @@ namespace ICSharpCode.ILSpy.Metadata
class NestedClassTableTreeNode : MetadataTableTreeNode
{
public NestedClassTableTreeNode(MetadataFile metadataFile)
- : base((HandleKind)0x29, metadataFile)
+ : base(TableIndex.NestedClass, metadataFile)
{
}
- public override object Text => $"29 NestedClass ({metadataFile.Metadata.GetTableRowCount(TableIndex.NestedClass)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -98,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;
@@ -109,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;
@@ -128,10 +125,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.enclosingClassTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "NestedClass");
- }
}
}
diff --git a/ILSpy/Metadata/CorTables/ParamTableTreeNode.cs b/ILSpy/Metadata/CorTables/ParamTableTreeNode.cs
index 0d69aa9d1..905159883 100644
--- a/ILSpy/Metadata/CorTables/ParamTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/ParamTableTreeNode.cs
@@ -21,7 +21,6 @@ using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -29,12 +28,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class ParamTableTreeNode : MetadataTableTreeNode
{
public ParamTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.Parameter, metadataFile)
+ : base(TableIndex.Param, metadataFile)
{
}
- public override object Text => $"08 Param ({metadataFile.Metadata.GetTableRowCount(TableIndex.Param)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -101,10 +98,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.param = metadataFile.Metadata.GetParameter(handle);
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "Params");
- }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs b/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs
index 1a7897ae3..6071961f3 100644
--- a/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/PropertyMapTableTreeNode.cs
@@ -21,7 +21,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -29,12 +28,10 @@ namespace ICSharpCode.ILSpy.Metadata
class PropertyMapTableTreeNode : MetadataTableTreeNode
{
public PropertyMapTableTreeNode(MetadataFile metadataFile)
- : base((HandleKind)0x15, metadataFile)
+ : base(TableIndex.PropertyMap, metadataFile)
{
}
- public override object Text => $"15 PropertyMap ({metadataFile.Metadata.GetTableRowCount(TableIndex.PropertyMap)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -98,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;
@@ -109,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;
@@ -129,10 +126,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.parentTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "PropertyMap");
- }
}
}
diff --git a/ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs b/ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs
index 65209e85c..05ff38b71 100644
--- a/ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/PropertyTableTreeNode.cs
@@ -21,7 +21,6 @@ using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TreeNodes;
@@ -31,12 +30,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class PropertyTableTreeNode : MetadataTableTreeNode
{
public PropertyTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.PropertyDefinition, metadataFile)
+ : base(TableIndex.Property, metadataFile)
{
}
- public override object Text => $"17 Property ({metadataFile.Metadata.GetTableRowCount(TableIndex.Property)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -111,10 +108,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.signatureTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "PropertyDefs");
- }
}
}
diff --git a/ILSpy/Metadata/CorTables/PtrTableTreeNode.cs b/ILSpy/Metadata/CorTables/PtrTableTreeNode.cs
new file mode 100644
index 000000000..cf196ef03
--- /dev/null
+++ b/ILSpy/Metadata/CorTables/PtrTableTreeNode.cs
@@ -0,0 +1,135 @@
+// Copyright (c) 2024 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.Collections.Generic;
+using System.Reflection.Metadata;
+using System.Reflection.Metadata.Ecma335;
+
+using ICSharpCode.Decompiler.Metadata;
+
+namespace ICSharpCode.ILSpy.Metadata
+{
+ class PtrTableTreeNode : MetadataTableTreeNode
+ {
+ readonly TableIndex referencedTableKind;
+
+ public PtrTableTreeNode(TableIndex kind, MetadataFile metadataFile)
+ : base(kind, metadataFile)
+ {
+ if (kind is not (TableIndex.EventPtr or TableIndex.FieldPtr or TableIndex.MethodPtr or TableIndex.ParamPtr or TableIndex.PropertyPtr))
+ {
+ throw new ArgumentOutOfRangeException("PtrTable does not support " + kind);
+ }
+
+ this.referencedTableKind = kind switch {
+ TableIndex.EventPtr => TableIndex.Event,
+ TableIndex.FieldPtr => TableIndex.Field,
+ TableIndex.MethodPtr => TableIndex.MethodDef,
+ TableIndex.ParamPtr => TableIndex.Param,
+ TableIndex.PropertyPtr => TableIndex.Property,
+ _ => throw new NotImplementedException(), // unreachable
+ };
+ }
+
+ public override bool View(ViewModels.TabPageModel tabPage)
+ {
+ tabPage.Title = Text.ToString();
+ tabPage.SupportsLanguageSwitching = false;
+
+ var view = Helpers.PrepareDataGrid(tabPage, this);
+ var metadata = metadataFile.Metadata;
+
+ var list = new List();
+ PtrEntry scrollTargetEntry = default;
+
+ var length = metadata.GetTableRowCount(Kind);
+ ReadOnlySpan ptr = metadata.AsReadOnlySpan();
+
+ int handleDefSize = metadataFile.Metadata.GetTableRowCount(referencedTableKind) < ushort.MaxValue ? 2 : 4;
+
+ for (int rid = 1; rid <= length; rid++)
+ {
+ var entry = new PtrEntry(metadataFile, Kind, referencedTableKind, handleDefSize, ptr, rid);
+ if (entry.RID == this.scrollTarget)
+ {
+ scrollTargetEntry = entry;
+ }
+ list.Add(entry);
+ }
+
+ view.ItemsSource = list;
+
+ tabPage.Content = view;
+
+ if (scrollTargetEntry.RID > 0)
+ {
+ ScrollItemIntoView(view, scrollTargetEntry);
+ }
+
+ return true;
+ }
+
+ readonly struct HandlePtr
+ {
+ public readonly EntityHandle Handle;
+
+ public HandlePtr(ReadOnlySpan ptr, TableIndex kind, int handleSize)
+ {
+ Handle = MetadataTokens.EntityHandle(((int)kind << 24) | Helpers.GetValueLittleEndian(ptr, handleSize));
+ }
+ }
+
+ struct PtrEntry
+ {
+ readonly MetadataFile metadataFile;
+ readonly HandlePtr handlePtr;
+ readonly TableIndex kind;
+
+ public int RID { get; }
+
+ public int Token => ((int)kind << 24) | RID;
+
+ public int Offset { get; }
+
+ [ColumnInfo("X8", Kind = ColumnKind.Token)]
+ public int Handle => MetadataTokens.GetToken(handlePtr.Handle);
+
+ public void OnHandleClick()
+ {
+ MessageBus.Send(this, new NavigateToReferenceEventArgs(new EntityReference(metadataFile, handlePtr.Handle, protocol: "metadata")));
+ }
+
+ string handleTooltip;
+ public string HandleTooltip => GenerateTooltip(ref handleTooltip, metadataFile, handlePtr.Handle);
+
+ public PtrEntry(MetadataFile metadataFile, TableIndex kind, TableIndex handleKind, int handleDefSize, ReadOnlySpan ptr, int row)
+ {
+ this.metadataFile = metadataFile;
+ this.RID = row;
+ this.kind = kind;
+ var rowOffset = metadataFile.Metadata.GetTableMetadataOffset(kind)
+ + metadataFile.Metadata.GetTableRowSize(kind) * (row - 1);
+ this.Offset = metadataFile.MetadataOffset + rowOffset;
+
+ this.handlePtr = new HandlePtr(ptr.Slice(rowOffset), handleKind, handleDefSize);
+ this.handleTooltip = null;
+ }
+ }
+ }
+}
diff --git a/ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs b/ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs
index 476ace744..24c5cf163 100644
--- a/ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/StandAloneSigTableTreeNode.cs
@@ -20,7 +20,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -28,12 +27,10 @@ namespace ICSharpCode.ILSpy.Metadata
class StandAloneSigTableTreeNode : MetadataTableTreeNode
{
public StandAloneSigTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.StandaloneSignature, metadataFile)
+ : base(TableIndex.StandAloneSig, metadataFile)
{
}
- public override object Text => $"11 StandAloneSig ({metadataFile.Metadata.GetTableRowCount(TableIndex.StandAloneSig)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -94,10 +91,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.signatureTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "StandAloneSigs");
- }
}
}
diff --git a/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs b/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs
index 0155d1e53..129f76907 100644
--- a/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/TypeDefTableTreeNode.cs
@@ -33,12 +33,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class TypeDefTableTreeNode : MetadataTableTreeNode
{
public TypeDefTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.TypeDefinition, metadataFile)
+ : base(TableIndex.TypeDef, metadataFile)
{
}
- public override object Text => $"02 TypeDef ({metadataFile.Metadata.GetTableRowCount(TableIndex.TypeDef)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -113,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 {
@@ -144,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;
@@ -162,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;
@@ -186,10 +184,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.fieldListTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "TypeDefs");
- }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs b/ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs
index 0f9e98ce2..6b086fea1 100644
--- a/ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/TypeRefTableTreeNode.cs
@@ -20,7 +20,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -28,12 +27,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class TypeRefTableTreeNode : MetadataTableTreeNode
{
public TypeRefTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.TypeReference, metadataFile)
+ : base(TableIndex.TypeRef, metadataFile)
{
}
- public override object Text => $"01 TypeRef ({metadataFile.Metadata.GetTableRowCount(TableIndex.TypeRef)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -86,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;
@@ -108,10 +105,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.resolutionScopeTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "TypeRefs");
- }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs b/ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs
index 1f8fc2106..e1d796f2b 100644
--- a/ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs
+++ b/ILSpy/Metadata/CorTables/TypeSpecTableTreeNode.cs
@@ -29,12 +29,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class TypeSpecTableTreeNode : MetadataTableTreeNode
{
public TypeSpecTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.TypeSpecification, metadataFile)
+ : base(TableIndex.TypeSpec, metadataFile)
{
}
- public override object Text => $"1B TypeSpec ({metadataFile.Metadata.GetTableRowCount(TableIndex.TypeSpec)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -104,10 +102,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.typeSpec = metadata.GetTypeSpecification(handle);
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "TypeSpecs");
- }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/DataDirectoriesTreeNode.cs b/ILSpy/Metadata/DataDirectoriesTreeNode.cs
index 4746ec1a0..775d5b38d 100644
--- a/ILSpy/Metadata/DataDirectoriesTreeNode.cs
+++ b/ILSpy/Metadata/DataDirectoriesTreeNode.cs
@@ -78,7 +78,6 @@ namespace ICSharpCode.ILSpy.Metadata
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
- language.WriteCommentLine(output, "Data Directories");
}
class DataDirectoryEntry
diff --git a/ILSpy/Metadata/DebugMetadataTablesTreeNode.cs b/ILSpy/Metadata/DebugMetadataTablesTreeNode.cs
index 9ec211751..d3067d713 100644
--- a/ILSpy/Metadata/DebugMetadataTablesTreeNode.cs
+++ b/ILSpy/Metadata/DebugMetadataTablesTreeNode.cs
@@ -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
diff --git a/ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs b/ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs
index b7e19fa3d..b020f5a97 100644
--- a/ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/CustomDebugInformationTableTreeNode.cs
@@ -24,7 +24,6 @@ using System.Reflection.Metadata.Ecma335;
using System.Windows;
using System.Windows.Controls;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.DebugInfo;
using ICSharpCode.Decompiler.Metadata;
@@ -33,12 +32,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class CustomDebugInformationTableTreeNode : DebugMetadataTableTreeNode
{
public CustomDebugInformationTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.CustomDebugInformation, metadataFile)
+ : base(TableIndex.CustomDebugInformation, metadataFile)
{
}
- public override object Text => $"37 CustomDebugInformation ({metadataFile.Metadata.GetTableRowCount(TableIndex.CustomDebugInformation)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -191,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;
@@ -323,10 +320,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.kind = GetKind(metadataFile.Metadata, debugInfo.Kind);
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "CustomDebugInformation");
- }
}
}
diff --git a/ILSpy/Metadata/DebugTables/DocumentTableTreeNode.cs b/ILSpy/Metadata/DebugTables/DocumentTableTreeNode.cs
index 877dafbe9..320fdffff 100644
--- a/ILSpy/Metadata/DebugTables/DocumentTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/DocumentTableTreeNode.cs
@@ -21,7 +21,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.DebugInfo;
using ICSharpCode.Decompiler.Metadata;
@@ -30,12 +29,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class DocumentTableTreeNode : DebugMetadataTableTreeNode
{
public DocumentTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.Document, metadataFile)
+ : base(TableIndex.Document, metadataFile)
{
}
- public override object Text => $"30 Document ({metadataFile.Metadata.GetTableRowCount(TableIndex.Document)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -139,10 +136,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.document = metadataFile.Metadata.GetDocument(handle);
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "Document");
- }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs b/ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs
index b6b878aca..65639ad1f 100644
--- a/ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/ImportScopeTableTreeNode.cs
@@ -20,7 +20,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -28,12 +27,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class ImportScopeTableTreeNode : DebugMetadataTableTreeNode
{
public ImportScopeTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.ImportScope, metadataFile)
+ : base(TableIndex.ImportScope, metadataFile)
{
}
- public override object Text => $"35 ImportScope ({metadataFile.Metadata.GetTableRowCount(TableIndex.ImportScope)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -83,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)]
@@ -98,10 +95,5 @@ namespace ICSharpCode.ILSpy.Metadata
+ metadataFile.Metadata.GetTableRowSize(TableIndex.ImportScope) * (MetadataTokens.GetRowNumber(handle) - 1);
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "ImportScope");
- }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/DebugTables/LocalConstantTableTreeNode.cs b/ILSpy/Metadata/DebugTables/LocalConstantTableTreeNode.cs
index 6075499e5..d5ab73d5b 100644
--- a/ILSpy/Metadata/DebugTables/LocalConstantTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/LocalConstantTableTreeNode.cs
@@ -20,7 +20,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -28,12 +27,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class LocalConstantTableTreeNode : DebugMetadataTableTreeNode
{
public LocalConstantTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.LocalConstant, metadataFile)
+ : base(TableIndex.LocalConstant, metadataFile)
{
}
- public override object Text => $"34 LocalConstant ({metadataFile.Metadata.GetTableRowCount(TableIndex.LocalConstant)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -94,10 +91,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.localConst = metadataFile.Metadata.GetLocalConstant(handle);
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "Document");
- }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs b/ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs
index 59b0d01e7..f25412f98 100644
--- a/ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/LocalScopeTableTreeNode.cs
@@ -21,7 +21,6 @@ using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -29,12 +28,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class LocalScopeTableTreeNode : DebugMetadataTableTreeNode
{
public LocalScopeTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.LocalScope, metadataFile)
+ : base(TableIndex.LocalScope, metadataFile)
{
}
- public override object Text => $"32 LocalScope ({metadataFile.Metadata.GetTableRowCount(TableIndex.LocalScope)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -84,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;
@@ -95,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)]
@@ -103,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)]
@@ -111,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;
@@ -128,10 +125,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.methodTooltip = null;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "LocalScope");
- }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/DebugTables/LocalVariableTableTreeNode.cs b/ILSpy/Metadata/DebugTables/LocalVariableTableTreeNode.cs
index 978ecd499..1add2eae6 100644
--- a/ILSpy/Metadata/DebugTables/LocalVariableTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/LocalVariableTableTreeNode.cs
@@ -20,7 +20,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -28,12 +27,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class LocalVariableTableTreeNode : DebugMetadataTableTreeNode
{
public LocalVariableTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.LocalVariable, metadataFile)
+ : base(TableIndex.LocalVariable, metadataFile)
{
}
- public override object Text => $"33 LocalVariable ({metadataFile.Metadata.GetTableRowCount(TableIndex.LocalVariable)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -100,10 +97,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.localVar = metadataFile.Metadata.GetLocalVariable(handle);
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "Document");
- }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs b/ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs
index 591e388f6..5453ce6f7 100644
--- a/ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/MethodDebugInformationTableTreeNode.cs
@@ -30,12 +30,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class MethodDebugInformationTableTreeNode : DebugMetadataTableTreeNode
{
public MethodDebugInformationTableTreeNode(MetadataFile metadataFile)
- : base(HandleKind.MethodDebugInformation, metadataFile)
+ : base(TableIndex.MethodDebugInformation, metadataFile)
{
}
- public override object Text => $"31 MethodDebugInformation ({metadataFile.Metadata.GetTableRowCount(TableIndex.MethodDebugInformation)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -85,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 {
@@ -118,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 {
@@ -151,10 +149,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.debugInfo = metadataFile.Metadata.GetMethodDebugInformation(handle);
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "MethodDebugInformation");
- }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs b/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs
index 8882adbdd..d4f778ed2 100644
--- a/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs
+++ b/ILSpy/Metadata/DebugTables/StateMachineMethodTableTreeNode.cs
@@ -20,7 +20,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -28,12 +27,10 @@ namespace ICSharpCode.ILSpy.Metadata
internal class StateMachineMethodTableTreeNode : DebugMetadataTableTreeNode
{
public StateMachineMethodTableTreeNode(MetadataFile metadataFile)
- : base((HandleKind)0x36, metadataFile)
+ : base(TableIndex.StateMachineMethod, metadataFile)
{
}
- public override object Text => $"36 StateMachineMethod ({metadataFile.Metadata.GetTableRowCount(TableIndex.StateMachineMethod)})";
-
public override bool View(ViewModels.TabPageModel tabPage)
{
tabPage.Title = Text.ToString();
@@ -86,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;
@@ -97,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;
@@ -119,10 +116,5 @@ namespace ICSharpCode.ILSpy.Metadata
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "StateMachineMethod");
- }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/DosHeaderTreeNode.cs b/ILSpy/Metadata/DosHeaderTreeNode.cs
index 29cb3833b..14c458cc2 100644
--- a/ILSpy/Metadata/DosHeaderTreeNode.cs
+++ b/ILSpy/Metadata/DosHeaderTreeNode.cs
@@ -88,7 +88,6 @@ namespace ICSharpCode.ILSpy.Metadata
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
- language.WriteCommentLine(output, "DOS Header");
}
}
}
diff --git a/ILSpy/Metadata/GoToTokenCommand.cs b/ILSpy/Metadata/GoToTokenCommand.cs
index 1c0caca2b..164f9b451 100644
--- a/ILSpy/Metadata/GoToTokenCommand.cs
+++ b/ILSpy/Metadata/GoToTokenCommand.cs
@@ -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
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
{
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
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();
- 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().FirstOrDefault();
+
+ return cell?.Column.OnCopyingCellClipboardContent(cell.DataContext).ToString();
}
}
}
diff --git a/ILSpy/Metadata/Heaps/BlobHeapTreeNode.cs b/ILSpy/Metadata/Heaps/BlobHeapTreeNode.cs
index 7dc0c62b1..764e362f9 100644
--- a/ILSpy/Metadata/Heaps/BlobHeapTreeNode.cs
+++ b/ILSpy/Metadata/Heaps/BlobHeapTreeNode.cs
@@ -20,7 +20,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -77,10 +76,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.handle = handle;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "Blob Heap");
- }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/Heaps/GuidHeapTreeNode.cs b/ILSpy/Metadata/Heaps/GuidHeapTreeNode.cs
index 17de531ab..d0874b5e0 100644
--- a/ILSpy/Metadata/Heaps/GuidHeapTreeNode.cs
+++ b/ILSpy/Metadata/Heaps/GuidHeapTreeNode.cs
@@ -20,7 +20,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -75,10 +74,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.handle = handle;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "Guid Heap");
- }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/Heaps/StringHeapTreeNode.cs b/ILSpy/Metadata/Heaps/StringHeapTreeNode.cs
index 91f679de9..061043947 100644
--- a/ILSpy/Metadata/Heaps/StringHeapTreeNode.cs
+++ b/ILSpy/Metadata/Heaps/StringHeapTreeNode.cs
@@ -20,7 +20,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -76,10 +75,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.handle = handle;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "String Heap");
- }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/Heaps/UserStringHeapTreeNode.cs b/ILSpy/Metadata/Heaps/UserStringHeapTreeNode.cs
index f2a7fd00d..10a1cd0e8 100644
--- a/ILSpy/Metadata/Heaps/UserStringHeapTreeNode.cs
+++ b/ILSpy/Metadata/Heaps/UserStringHeapTreeNode.cs
@@ -20,7 +20,6 @@ using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
-using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.ILSpy.Metadata
@@ -76,10 +75,5 @@ namespace ICSharpCode.ILSpy.Metadata
this.handle = handle;
}
}
-
- public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
- {
- language.WriteCommentLine(output, "UserString Heap");
- }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/MetadataHeapTreeNode.cs b/ILSpy/Metadata/MetadataHeapTreeNode.cs
index 67a12036a..4c3a39e92 100644
--- a/ILSpy/Metadata/MetadataHeapTreeNode.cs
+++ b/ILSpy/Metadata/MetadataHeapTreeNode.cs
@@ -20,6 +20,7 @@ using System.Reflection.Metadata;
using System.Windows.Controls;
using System.Windows.Threading;
+using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.TreeNodes;
@@ -54,5 +55,9 @@ namespace ICSharpCode.ILSpy.Metadata
view.Loaded -= View_Loaded;
this.scrollTarget = default;
}
+
+ public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
+ {
+ }
}
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/MetadataProtocolHandler.cs b/ILSpy/Metadata/MetadataProtocolHandler.cs
index c49e300d7..8a50cac36 100644
--- a/ILSpy/Metadata/MetadataProtocolHandler.cs
+++ b/ILSpy/Metadata/MetadataProtocolHandler.cs
@@ -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().FirstOrDefault();
diff --git a/ILSpy/Metadata/MetadataTableTreeNode.cs b/ILSpy/Metadata/MetadataTableTreeNode.cs
index 54f2d47ae..2df51f1c6 100644
--- a/ILSpy/Metadata/MetadataTableTreeNode.cs
+++ b/ILSpy/Metadata/MetadataTableTreeNode.cs
@@ -34,13 +34,15 @@ namespace ICSharpCode.ILSpy.Metadata
protected readonly MetadataFile metadataFile;
protected int scrollTarget;
- public HandleKind Kind { get; }
+ public TableIndex Kind { get; }
+
+ public override object Text => $"{(int)Kind:X2} {Kind} ({metadataFile.Metadata.GetTableRowCount(Kind)})";
public override object Icon => Images.MetadataTable;
- public MetadataTableTreeNode(HandleKind kind, MetadataFile metadataFile)
+ public MetadataTableTreeNode(TableIndex table, MetadataFile metadataFile)
{
- this.Kind = kind;
+ this.Kind = table;
this.metadataFile = metadataFile;
}
@@ -130,13 +132,31 @@ namespace ICSharpCode.ILSpy.Metadata
}
return tooltip;
}
+
+ public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
+ {
+ }
}
internal abstract class DebugMetadataTableTreeNode : MetadataTableTreeNode
{
- public DebugMetadataTableTreeNode(HandleKind kind, MetadataFile metadataFile)
+ public DebugMetadataTableTreeNode(TableIndex kind, MetadataFile metadataFile)
: base(kind, metadataFile)
{
}
}
+
+ internal class UnsupportedMetadataTableTreeNode : MetadataTableTreeNode
+ {
+ public UnsupportedMetadataTableTreeNode(TableIndex kind, MetadataFile file)
+ : base(kind, file)
+ {
+ }
+ public override object Text => $"{(int)Kind:X2} {Kind.ToString()} [unsupported] ({metadataFile.Metadata.GetTableRowCount(Kind)})";
+
+ public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
+ {
+ output.WriteLine($"Unsupported table '{(int)Kind:X2} {Kind}' contains {metadataFile.Metadata.GetTableRowCount(Kind)} rows.");
+ }
+ }
}
\ No newline at end of file
diff --git a/ILSpy/Metadata/MetadataTablesTreeNode.cs b/ILSpy/Metadata/MetadataTablesTreeNode.cs
index 1572ed4e3..1fb55be81 100644
--- a/ILSpy/Metadata/MetadataTablesTreeNode.cs
+++ b/ILSpy/Metadata/MetadataTablesTreeNode.cs
@@ -23,7 +23,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
@@ -141,8 +140,14 @@ namespace ICSharpCode.ILSpy.Metadata
return new StateMachineMethodTableTreeNode(metadataFile);
case TableIndex.CustomDebugInformation:
return new CustomDebugInformationTableTreeNode(metadataFile);
+ case TableIndex.FieldPtr:
+ case TableIndex.EventPtr:
+ case TableIndex.MethodPtr:
+ case TableIndex.ParamPtr:
+ case TableIndex.PropertyPtr:
+ return new PtrTableTreeNode(table, metadataFile);
default:
- throw new ArgumentException($"Unsupported table index: {table}");
+ return new UnsupportedMetadataTableTreeNode(table, metadataFile);
}
}
diff --git a/ILSpy/Metadata/MetadataTreeNode.cs b/ILSpy/Metadata/MetadataTreeNode.cs
index 4aedf30a7..50f739868 100644
--- a/ILSpy/Metadata/MetadataTreeNode.cs
+++ b/ILSpy/Metadata/MetadataTreeNode.cs
@@ -108,7 +108,7 @@ namespace ICSharpCode.ILSpy.Metadata
public MetadataTableTreeNode FindNodeByHandleKind(HandleKind kind)
{
return this.Children.OfType().Single()
- .Children.OfType().SingleOrDefault(x => x.Kind == kind);
+ .Children.OfType().SingleOrDefault(x => x.Kind == (TableIndex)kind);
}
}
diff --git a/ILSpy/Metadata/OptionalHeaderTreeNode.cs b/ILSpy/Metadata/OptionalHeaderTreeNode.cs
index dc1be30ec..8353ead80 100644
--- a/ILSpy/Metadata/OptionalHeaderTreeNode.cs
+++ b/ILSpy/Metadata/OptionalHeaderTreeNode.cs
@@ -27,6 +27,8 @@ using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpyX.Extensions;
+using TomsToolbox.Essentials;
+
namespace ICSharpCode.ILSpy.Metadata
{
class OptionalHeaderTreeNode : ILSpyTreeNode
diff --git a/ILSpy/Options/DecompilerSettings.cs b/ILSpy/Options/DecompilerSettings.cs
new file mode 100644
index 000000000..14f1d32e9
--- /dev/null
+++ b/ILSpy/Options/DecompilerSettings.cs
@@ -0,0 +1,52 @@
+using System.ComponentModel;
+
+using ICSharpCode.ILSpyX.Settings;
+using System.Linq;
+using System.Reflection;
+using System.Xml.Linq;
+
+#nullable enable
+
+namespace ICSharpCode.ILSpy.Options
+{
+ public class DecompilerSettings : Decompiler.DecompilerSettings, ISettingsSection
+ {
+ static readonly PropertyInfo[] properties = typeof(Decompiler.DecompilerSettings).GetProperties()
+ .Where(p => p.GetCustomAttribute()?.Browsable != false)
+ .ToArray();
+
+ public XName SectionName => "DecompilerSettings";
+
+ public XElement SaveToXml()
+ {
+ var section = new XElement(SectionName);
+
+ foreach (var p in properties)
+ {
+ section.SetAttributeValue(p.Name, p.GetValue(this));
+ }
+
+ return section;
+ }
+
+ public void LoadFromXml(XElement section)
+ {
+ foreach (var p in properties)
+ {
+ var value = (bool?)section.Attribute(p.Name);
+ if (value.HasValue)
+ p.SetValue(this, value.Value);
+ }
+ }
+
+ public new DecompilerSettings Clone()
+ {
+ var section = SaveToXml();
+
+ var newSettings = new DecompilerSettings();
+ newSettings.LoadFromXml(section);
+
+ return newSettings;
+ }
+ }
+}
diff --git a/ILSpy/Options/DecompilerSettingsPanel.xaml.cs b/ILSpy/Options/DecompilerSettingsPanel.xaml.cs
index d530079dc..e65f72087 100644
--- a/ILSpy/Options/DecompilerSettingsPanel.xaml.cs
+++ b/ILSpy/Options/DecompilerSettingsPanel.xaml.cs
@@ -19,47 +19,22 @@
using System.ComponentModel.Composition;
using System.Xml.Linq;
-using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX.Settings;
+using TomsToolbox.Wpf.Composition.Mef;
+
namespace ICSharpCode.ILSpy.Options
{
///
/// Interaction logic for DecompilerSettingsPanel.xaml
///
- [ExportOptionPage(Title = nameof(Properties.Resources.Decompiler), Order = 10)]
+ [DataTemplate(typeof(DecompilerSettingsViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
- internal partial class DecompilerSettingsPanel : IOptionPage
+ internal partial class DecompilerSettingsPanel
{
public DecompilerSettingsPanel()
{
InitializeComponent();
}
-
- public static Decompiler.DecompilerSettings LoadDecompilerSettings(ILSpySettings settings)
- {
- return ISettingsProvider.LoadDecompilerSettings(settings);
- }
-
- public void Load(ILSpySettings settings)
- {
- this.DataContext = new DecompilerSettingsViewModel(LoadDecompilerSettings(settings));
- }
-
- public void Save(XElement root)
- {
- var newSettings = ((DecompilerSettingsViewModel)this.DataContext).ToDecompilerSettings();
- ISettingsProvider.SaveDecompilerSettings(root, newSettings);
-
- SettingsService.Instance.DecompilerSettings = newSettings;
- SettingsService.Instance.AssemblyListManager.ApplyWinRTProjections = newSettings.ApplyWindowsRuntimeProjections;
- SettingsService.Instance.AssemblyListManager.UseDebugSymbols = newSettings.UseDebugSymbols;
- }
-
- public void LoadDefaults()
- {
- SettingsService.Instance.DecompilerSettings = new();
- this.DataContext = new DecompilerSettingsViewModel(SettingsService.Instance.DecompilerSettings);
- }
}
}
diff --git a/ILSpy/Options/DecompilerSettingsViewModel.cs b/ILSpy/Options/DecompilerSettingsViewModel.cs
index 3a574cca9..27cc520de 100644
--- a/ILSpy/Options/DecompilerSettingsViewModel.cs
+++ b/ILSpy/Options/DecompilerSettingsViewModel.cs
@@ -18,6 +18,7 @@
using System.Collections.Generic;
using System.ComponentModel;
+using System.ComponentModel.Composition;
using System.Linq;
using System.Reflection;
@@ -28,44 +29,63 @@ using TomsToolbox.Wpf;
namespace ICSharpCode.ILSpy.Options
{
- public sealed class DecompilerSettingsViewModel : ObservableObjectBase
+ [ExportOptionPage(Order = 10)]
+ [PartCreationPolicy(CreationPolicy.NonShared)]
+ public sealed class DecompilerSettingsViewModel : ObservableObjectBase, IOptionPage
{
- public DecompilerSettingsGroupViewModel[] Settings { get; }
+ private static readonly PropertyInfo[] propertyInfos = typeof(Decompiler.DecompilerSettings).GetProperties()
+ .Where(p => p.GetCustomAttribute()?.Browsable != false)
+ .ToArray();
- public DecompilerSettingsViewModel(Decompiler.DecompilerSettings settings)
+ public string Title => Resources.Decompiler;
+
+ private DecompilerSettingsGroupViewModel[] settings;
+ public DecompilerSettingsGroupViewModel[] Settings {
+ get => settings;
+ set => SetProperty(ref settings, value);
+ }
+
+ private DecompilerSettings decompilerSettings;
+
+ public void Load(SettingsSnapshot snapshot)
{
- Settings = typeof(Decompiler.DecompilerSettings).GetProperties()
- .Where(p => p.GetCustomAttribute()?.Browsable != false)
- .Select(p => new DecompilerSettingsItemViewModel(p) { IsEnabled = p.GetValue(settings) is true })
+ decompilerSettings = snapshot.GetSettings();
+ LoadSettings();
+ }
+
+ private void LoadSettings()
+ {
+ this.Settings = propertyInfos
+ .Select(p => new DecompilerSettingsItemViewModel(p, decompilerSettings))
.OrderBy(item => item.Category, NaturalStringComparer.Instance)
.GroupBy(p => p.Category)
.Select(g => new DecompilerSettingsGroupViewModel(g.Key, g.OrderBy(i => i.Description).ToArray()))
.ToArray();
}
- public Decompiler.DecompilerSettings ToDecompilerSettings()
+ public void LoadDefaults()
{
- var settings = new Decompiler.DecompilerSettings();
+ var defaults = new Decompiler.DecompilerSettings();
- foreach (var item in Settings.SelectMany(group => group.Settings))
+ foreach (var propertyInfo in propertyInfos)
{
- item.Property.SetValue(settings, item.IsEnabled);
+ propertyInfo.SetValue(decompilerSettings, propertyInfo.GetValue(defaults));
}
- return settings;
+ LoadSettings();
}
}
public sealed class DecompilerSettingsGroupViewModel : ObservableObjectBase
{
- private bool? _areAllItemsChecked;
+ private bool? areAllItemsChecked;
public DecompilerSettingsGroupViewModel(string category, DecompilerSettingsItemViewModel[] settings)
{
Settings = settings;
Category = category;
- _areAllItemsChecked = GetAreAllItemsChecked(Settings);
+ areAllItemsChecked = GetAreAllItemsChecked(Settings);
foreach (DecompilerSettingsItemViewModel viewModel in settings)
{
@@ -74,9 +94,9 @@ namespace ICSharpCode.ILSpy.Options
}
public bool? AreAllItemsChecked {
- get => _areAllItemsChecked;
+ get => areAllItemsChecked;
set {
- SetProperty(ref _areAllItemsChecked, value);
+ SetProperty(ref areAllItemsChecked, value);
if (!value.HasValue)
return;
@@ -114,15 +134,20 @@ namespace ICSharpCode.ILSpy.Options
}
}
- public sealed class DecompilerSettingsItemViewModel(PropertyInfo property) : ObservableObjectBase
+ public sealed class DecompilerSettingsItemViewModel(PropertyInfo property, DecompilerSettings decompilerSettings) : ObservableObjectBase
{
- private bool _isEnabled;
+ private bool isEnabled = property.GetValue(decompilerSettings) is true;
- public PropertyInfo Property { get; } = property;
+ public PropertyInfo Property => property;
public bool IsEnabled {
- get => _isEnabled;
- set => SetProperty(ref _isEnabled, value);
+ get => isEnabled;
+ set {
+ if (SetProperty(ref isEnabled, value))
+ {
+ property.SetValue(decompilerSettings, value);
+ }
+ }
}
public string Description { get; set; } = GetResourceString(property.GetCustomAttribute()?.Description ?? property.Name);
diff --git a/ILSpy/Options/DisplaySettings.cs b/ILSpy/Options/DisplaySettings.cs
index f59c31a95..9eb07b394 100644
--- a/ILSpy/Options/DisplaySettings.cs
+++ b/ILSpy/Options/DisplaySettings.cs
@@ -16,341 +16,190 @@
// 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.Runtime.CompilerServices;
using System.Windows.Media;
+using System.Xml.Linq;
-using ICSharpCode.ILSpy.Themes;
+using TomsToolbox.Wpf;
namespace ICSharpCode.ILSpy.Options
{
///
/// Description of DisplaySettings.
///
- public class DisplaySettings : INotifyPropertyChanged
+ public class DisplaySettings : ObservableObject, ISettingsSection
{
- public DisplaySettings()
- {
- this.theme = ThemeManager.Current.DefaultTheme;
- this.selectedFont = new FontFamily("Consolas");
- this.selectedFontSize = 10.0 * 4 / 3;
- this.sortResults = true;
- this.indentationUseTabs = true;
- this.indentationSize = 4;
- this.indentationTabSize = 4;
- this.highlightMatchingBraces = true;
- }
-
- #region INotifyPropertyChanged implementation
- public event PropertyChangedEventHandler PropertyChanged;
-
- protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
- {
- PropertyChanged?.Invoke(this, e);
- }
-
- protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
- {
- OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
- }
- #endregion
-
- string theme;
-
- public string Theme {
- get { return theme; }
- set {
- if (theme != value)
- {
- theme = value;
- OnPropertyChanged();
- }
- }
- }
-
FontFamily selectedFont;
-
public FontFamily SelectedFont {
- get { return selectedFont; }
- set {
- if (selectedFont != value)
- {
- selectedFont = value;
- OnPropertyChanged();
- }
- }
+ get => selectedFont;
+ set => SetProperty(ref selectedFont, value);
}
double selectedFontSize;
-
public double SelectedFontSize {
- get { return selectedFontSize; }
- set {
- if (selectedFontSize != value)
- {
- selectedFontSize = value;
- OnPropertyChanged();
- }
- }
+ get => selectedFontSize;
+ set => SetProperty(ref selectedFontSize, value);
}
bool showLineNumbers;
-
public bool ShowLineNumbers {
- get { return showLineNumbers; }
- set {
- if (showLineNumbers != value)
- {
- showLineNumbers = value;
- OnPropertyChanged();
- }
- }
+ get => showLineNumbers;
+ set => SetProperty(ref showLineNumbers, value);
}
bool showMetadataTokens;
-
public bool ShowMetadataTokens {
- get { return showMetadataTokens; }
- set {
- if (showMetadataTokens != value)
- {
- showMetadataTokens = value;
- OnPropertyChanged();
- }
- }
+ get => showMetadataTokens;
+ set => SetProperty(ref showMetadataTokens, value);
}
bool showMetadataTokensInBase10;
-
public bool ShowMetadataTokensInBase10 {
- get { return showMetadataTokensInBase10; }
- set {
- if (showMetadataTokensInBase10 != value)
- {
- showMetadataTokensInBase10 = value;
- OnPropertyChanged();
- }
- }
+ get => showMetadataTokensInBase10;
+ set => SetProperty(ref showMetadataTokensInBase10, value);
}
bool enableWordWrap;
-
public bool EnableWordWrap {
- get { return enableWordWrap; }
- set {
- if (enableWordWrap != value)
- {
- enableWordWrap = value;
- OnPropertyChanged();
- }
- }
+ get => enableWordWrap;
+ set => SetProperty(ref enableWordWrap, value);
}
- bool sortResults = true;
-
+ bool sortResults;
public bool SortResults {
- get { return sortResults; }
- set {
- if (sortResults != value)
- {
- sortResults = value;
- OnPropertyChanged();
- }
- }
+ get => sortResults;
+ set => SetProperty(ref sortResults, value);
}
- bool foldBraces = false;
-
+ bool foldBraces;
public bool FoldBraces {
- get { return foldBraces; }
- set {
- if (foldBraces != value)
- {
- foldBraces = value;
- OnPropertyChanged();
- }
- }
+ get => foldBraces;
+ set => SetProperty(ref foldBraces, value);
}
- bool expandMemberDefinitions = false;
-
+ bool expandMemberDefinitions;
public bool ExpandMemberDefinitions {
- get { return expandMemberDefinitions; }
- set {
- if (expandMemberDefinitions != value)
- {
- expandMemberDefinitions = value;
- OnPropertyChanged();
- }
- }
+ get => expandMemberDefinitions;
+ set => SetProperty(ref expandMemberDefinitions, value);
}
- bool expandUsingDeclarations = false;
-
+ bool expandUsingDeclarations;
public bool ExpandUsingDeclarations {
- get { return expandUsingDeclarations; }
- set {
- if (expandUsingDeclarations != value)
- {
- expandUsingDeclarations = value;
- OnPropertyChanged();
- }
- }
+ get => expandUsingDeclarations;
+ set => SetProperty(ref expandUsingDeclarations, value);
}
bool showDebugInfo;
-
public bool ShowDebugInfo {
- get { return showDebugInfo; }
- set {
- if (showDebugInfo != value)
- {
- showDebugInfo = value;
- OnPropertyChanged();
- }
- }
+ get => showDebugInfo;
+ set => SetProperty(ref showDebugInfo, value);
}
- bool indentationUseTabs = true;
-
+ bool indentationUseTabs;
public bool IndentationUseTabs {
- get { return indentationUseTabs; }
- set {
- if (indentationUseTabs != value)
- {
- indentationUseTabs = value;
- OnPropertyChanged();
- }
- }
+ get => indentationUseTabs;
+ set => SetProperty(ref indentationUseTabs, value);
}
- int indentationTabSize = 4;
-
+ int indentationTabSize;
public int IndentationTabSize {
- get { return indentationTabSize; }
- set {
- if (indentationTabSize != value)
- {
- indentationTabSize = value;
- OnPropertyChanged();
- }
- }
+ get => indentationTabSize;
+ set => SetProperty(ref indentationTabSize, value);
}
- int indentationSize = 4;
-
+ int indentationSize;
public int IndentationSize {
- get { return indentationSize; }
- set {
- if (indentationSize != value)
- {
- indentationSize = value;
- OnPropertyChanged();
- }
- }
+ get => indentationSize;
+ set => SetProperty(ref indentationSize, value);
}
- bool highlightMatchingBraces = true;
-
+ bool highlightMatchingBraces;
public bool HighlightMatchingBraces {
- get { return highlightMatchingBraces; }
- set {
- if (highlightMatchingBraces != value)
- {
- highlightMatchingBraces = value;
- OnPropertyChanged();
- }
- }
+ get => highlightMatchingBraces;
+ set => SetProperty(ref highlightMatchingBraces, value);
}
- bool highlightCurrentLine = false;
-
+ bool highlightCurrentLine;
public bool HighlightCurrentLine {
- get { return highlightCurrentLine; }
- set {
- if (highlightCurrentLine != value)
- {
- highlightCurrentLine = value;
- OnPropertyChanged();
- }
- }
+ get => highlightCurrentLine;
+ set => SetProperty(ref highlightCurrentLine, value);
}
- bool hideEmptyMetadataTables = true;
-
+ bool hideEmptyMetadataTables;
public bool HideEmptyMetadataTables {
- get { return hideEmptyMetadataTables; }
- set {
- if (hideEmptyMetadataTables != value)
- {
- hideEmptyMetadataTables = value;
- OnPropertyChanged();
- }
- }
+ get => hideEmptyMetadataTables;
+ set => SetProperty(ref hideEmptyMetadataTables, value);
}
- bool useNestedNamespaceNodes = true;
-
+ bool useNestedNamespaceNodes;
public bool UseNestedNamespaceNodes {
- get { return useNestedNamespaceNodes; }
- set {
- if (useNestedNamespaceNodes != value)
- {
- useNestedNamespaceNodes = value;
- OnPropertyChanged();
- }
- }
+ get => useNestedNamespaceNodes;
+ set => SetProperty(ref useNestedNamespaceNodes, value);
}
private bool styleWindowTitleBar;
-
public bool StyleWindowTitleBar {
- get { return styleWindowTitleBar; }
- set {
- if (styleWindowTitleBar != value)
- {
- styleWindowTitleBar = value;
- OnPropertyChanged();
- }
- }
+ get => styleWindowTitleBar;
+ set => SetProperty(ref styleWindowTitleBar, value);
}
private bool showRawOffsetsAndBytesBeforeInstruction;
-
public bool ShowRawOffsetsAndBytesBeforeInstruction {
- get { return showRawOffsetsAndBytesBeforeInstruction; }
- set {
- if (showRawOffsetsAndBytesBeforeInstruction != value)
- {
- showRawOffsetsAndBytesBeforeInstruction = value;
- OnPropertyChanged();
- }
- }
+ get => showRawOffsetsAndBytesBeforeInstruction;
+ set => SetProperty(ref showRawOffsetsAndBytesBeforeInstruction, value);
}
- public void CopyValues(DisplaySettings s)
+ public XName SectionName => "DisplaySettings";
+
+ public void LoadFromXml(XElement section)
+ {
+ SelectedFont = new FontFamily((string)section.Attribute("Font") ?? "Consolas");
+ SelectedFontSize = (double?)section.Attribute("FontSize") ?? 10.0 * 4 / 3;
+ ShowLineNumbers = (bool?)section.Attribute("ShowLineNumbers") ?? false;
+ ShowMetadataTokens = (bool?)section.Attribute("ShowMetadataTokens") ?? false;
+ ShowMetadataTokensInBase10 = (bool?)section.Attribute("ShowMetadataTokensInBase10") ?? false;
+ ShowDebugInfo = (bool?)section.Attribute("ShowDebugInfo") ?? false;
+ EnableWordWrap = (bool?)section.Attribute("EnableWordWrap") ?? false;
+ SortResults = (bool?)section.Attribute("SortResults") ?? true;
+ FoldBraces = (bool?)section.Attribute("FoldBraces") ?? false;
+ ExpandMemberDefinitions = (bool?)section.Attribute("ExpandMemberDefinitions") ?? false;
+ ExpandUsingDeclarations = (bool?)section.Attribute("ExpandUsingDeclarations") ?? false;
+ IndentationUseTabs = (bool?)section.Attribute("IndentationUseTabs") ?? true;
+ IndentationSize = (int?)section.Attribute("IndentationSize") ?? 4;
+ IndentationTabSize = (int?)section.Attribute("IndentationTabSize") ?? 4;
+ HighlightMatchingBraces = (bool?)section.Attribute("HighlightMatchingBraces") ?? true;
+ HighlightCurrentLine = (bool?)section.Attribute("HighlightCurrentLine") ?? false;
+ HideEmptyMetadataTables = (bool?)section.Attribute("HideEmptyMetadataTables") ?? true;
+ UseNestedNamespaceNodes = (bool?)section.Attribute("UseNestedNamespaceNodes") ?? false;
+ ShowRawOffsetsAndBytesBeforeInstruction = (bool?)section.Attribute("ShowRawOffsetsAndBytesBeforeInstruction") ?? false;
+ StyleWindowTitleBar = (bool?)section.Attribute("StyleWindowTitleBar") ?? false;
+ }
+
+ public XElement SaveToXml()
{
- this.Theme = s.Theme;
- this.SelectedFont = s.selectedFont;
- this.SelectedFontSize = s.selectedFontSize;
- this.ShowLineNumbers = s.showLineNumbers;
- this.ShowMetadataTokens = s.showMetadataTokens;
- this.ShowMetadataTokensInBase10 = s.showMetadataTokensInBase10;
- this.ShowDebugInfo = s.showDebugInfo;
- this.EnableWordWrap = s.enableWordWrap;
- this.SortResults = s.sortResults;
- this.FoldBraces = s.foldBraces;
- this.ExpandMemberDefinitions = s.expandMemberDefinitions;
- this.ExpandUsingDeclarations = s.expandUsingDeclarations;
- this.IndentationUseTabs = s.indentationUseTabs;
- this.IndentationTabSize = s.indentationTabSize;
- this.IndentationSize = s.indentationSize;
- this.HighlightMatchingBraces = s.highlightMatchingBraces;
- this.HighlightCurrentLine = s.highlightCurrentLine;
- this.HideEmptyMetadataTables = s.hideEmptyMetadataTables;
- this.UseNestedNamespaceNodes = s.useNestedNamespaceNodes;
- this.ShowRawOffsetsAndBytesBeforeInstruction = s.showRawOffsetsAndBytesBeforeInstruction;
- this.StyleWindowTitleBar = s.styleWindowTitleBar;
+ var section = new XElement(SectionName);
+
+ section.SetAttributeValue("Font", SelectedFont.Source);
+ section.SetAttributeValue("FontSize", SelectedFontSize);
+ section.SetAttributeValue("ShowLineNumbers", ShowLineNumbers);
+ section.SetAttributeValue("ShowMetadataTokens", ShowMetadataTokens);
+ section.SetAttributeValue("ShowMetadataTokensInBase10", ShowMetadataTokensInBase10);
+ section.SetAttributeValue("ShowDebugInfo", ShowDebugInfo);
+ section.SetAttributeValue("EnableWordWrap", EnableWordWrap);
+ section.SetAttributeValue("SortResults", SortResults);
+ section.SetAttributeValue("FoldBraces", FoldBraces);
+ section.SetAttributeValue("ExpandMemberDefinitions", ExpandMemberDefinitions);
+ section.SetAttributeValue("ExpandUsingDeclarations", ExpandUsingDeclarations);
+ section.SetAttributeValue("IndentationUseTabs", IndentationUseTabs);
+ section.SetAttributeValue("IndentationSize", IndentationSize);
+ section.SetAttributeValue("IndentationTabSize", IndentationTabSize);
+ section.SetAttributeValue("HighlightMatchingBraces", HighlightMatchingBraces);
+ section.SetAttributeValue("HighlightCurrentLine", HighlightCurrentLine);
+ section.SetAttributeValue("HideEmptyMetadataTables", HideEmptyMetadataTables);
+ section.SetAttributeValue("UseNestedNamespaceNodes", UseNestedNamespaceNodes);
+ section.SetAttributeValue("ShowRawOffsetsAndBytesBeforeInstruction", ShowRawOffsetsAndBytesBeforeInstruction);
+ section.SetAttributeValue("StyleWindowTitleBar", StyleWindowTitleBar);
+
+ return section;
}
}
}
diff --git a/ILSpy/Options/DisplaySettingsPanel.xaml b/ILSpy/Options/DisplaySettingsPanel.xaml
index 1170a8f5b..9fb50d7a9 100644
--- a/ILSpy/Options/DisplaySettingsPanel.xaml
+++ b/ILSpy/Options/DisplaySettingsPanel.xaml
@@ -3,19 +3,15 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:properties="clr-namespace:ICSharpCode.ILSpy.Properties"
xmlns:local="clr-namespace:ICSharpCode.ILSpy.Options"
- xmlns:system="clr-namespace:System;assembly=mscorlib"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:themes="clr-namespace:ICSharpCode.ILSpy.Themes"
- d:DataContext="{d:DesignInstance local:DisplaySettings}">
-
-
-
+ d:DataContext="{d:DesignInstance local:DisplaySettingsViewModel}">
-
+
@@ -30,78 +26,58 @@
-
+
-
-
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
-
-
-
+
+
+
+
-
+
-
+
-
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
+
+
diff --git a/ILSpy/Options/DisplaySettingsPanel.xaml.cs b/ILSpy/Options/DisplaySettingsPanel.xaml.cs
index 9645dacc7..3b51a16ba 100644
--- a/ILSpy/Options/DisplaySettingsPanel.xaml.cs
+++ b/ILSpy/Options/DisplaySettingsPanel.xaml.cs
@@ -27,17 +27,19 @@ using System.Windows.Media;
using System.Windows.Threading;
using System.Xml.Linq;
-using ICSharpCode.ILSpy.Util;
using ICSharpCode.ILSpyX.Settings;
+using TomsToolbox.Wpf.Composition.Mef;
+using TomsToolbox.Wpf.Converters;
+
namespace ICSharpCode.ILSpy.Options
{
///
/// Interaction logic for DisplaySettingsPanel.xaml
///
- [ExportOptionPage(Title = nameof(Properties.Resources.Display), Order = 20)]
[PartCreationPolicy(CreationPolicy.NonShared)]
- public partial class DisplaySettingsPanel : UserControl, IOptionPage
+ [DataTemplate(typeof(DisplaySettingsViewModel))]
+ public partial class DisplaySettingsPanel
{
public DisplaySettingsPanel()
{
@@ -45,132 +47,6 @@ namespace ICSharpCode.ILSpy.Options
DataObject.AddPastingHandler(tabSizeTextBox, OnPaste);
DataObject.AddPastingHandler(indentSizeTextBox, OnPaste);
-
- Task task = new Task(FontLoader);
- task.Start();
- task.ContinueWith(
- delegate (Task continuation) {
- App.Current.Dispatcher.Invoke(
- DispatcherPriority.Normal,
- (Action)(
- () => {
- fontSelector.ItemsSource = task.Result;
- if (continuation.Exception != null)
- {
- foreach (var ex in continuation.Exception.InnerExceptions)
- {
- MessageBox.Show(ex.ToString());
- }
- }
- })
- );
- }
- );
- }
-
- public void Load(ILSpySettings settings)
- {
- this.DataContext = LoadDisplaySettings(settings);
- }
-
- static bool IsSymbolFont(FontFamily fontFamily)
- {
- foreach (var tf in fontFamily.GetTypefaces())
- {
- GlyphTypeface glyph;
- try
- {
- if (tf.TryGetGlyphTypeface(out glyph))
- return glyph.Symbol;
- }
- catch (Exception)
- {
- return true;
- }
- }
- return false;
- }
-
- static FontFamily[] FontLoader()
- {
- return (from ff in Fonts.SystemFontFamilies
- where !IsSymbolFont(ff)
- orderby ff.Source
- select ff).ToArray();
- }
-
- public static DisplaySettings LoadDisplaySettings(ILSpySettings settings, SessionSettings sessionSettings = null)
- {
- XElement e = settings["DisplaySettings"];
- var s = new DisplaySettings();
- s.SelectedFont = new FontFamily((string)e.Attribute("Font") ?? "Consolas");
- s.SelectedFontSize = (double?)e.Attribute("FontSize") ?? 10.0 * 4 / 3;
- s.ShowLineNumbers = (bool?)e.Attribute("ShowLineNumbers") ?? false;
- s.ShowMetadataTokens = (bool?)e.Attribute("ShowMetadataTokens") ?? false;
- s.ShowMetadataTokensInBase10 = (bool?)e.Attribute("ShowMetadataTokensInBase10") ?? false;
- s.ShowDebugInfo = (bool?)e.Attribute("ShowDebugInfo") ?? false;
- s.EnableWordWrap = (bool?)e.Attribute("EnableWordWrap") ?? false;
- s.SortResults = (bool?)e.Attribute("SortResults") ?? true;
- s.FoldBraces = (bool?)e.Attribute("FoldBraces") ?? false;
- s.ExpandMemberDefinitions = (bool?)e.Attribute("ExpandMemberDefinitions") ?? false;
- s.ExpandUsingDeclarations = (bool?)e.Attribute("ExpandUsingDeclarations") ?? false;
- s.IndentationUseTabs = (bool?)e.Attribute("IndentationUseTabs") ?? true;
- s.IndentationSize = (int?)e.Attribute("IndentationSize") ?? 4;
- s.IndentationTabSize = (int?)e.Attribute("IndentationTabSize") ?? 4;
- s.HighlightMatchingBraces = (bool?)e.Attribute("HighlightMatchingBraces") ?? true;
- s.HighlightCurrentLine = (bool?)e.Attribute("HighlightCurrentLine") ?? false;
- s.HideEmptyMetadataTables = (bool?)e.Attribute("HideEmptyMetadataTables") ?? true;
- s.UseNestedNamespaceNodes = (bool?)e.Attribute("UseNestedNamespaceNodes") ?? false;
- s.ShowRawOffsetsAndBytesBeforeInstruction = (bool?)e.Attribute("ShowRawOffsetsAndBytesBeforeInstruction") ?? false;
- s.StyleWindowTitleBar = (bool?)e.Attribute("StyleWindowTitleBar") ?? false;
-
- s.Theme = (sessionSettings ?? SettingsService.Instance.SessionSettings).Theme;
-
- return s;
- }
-
- public void Save(XElement root)
- {
- var s = (DisplaySettings)this.DataContext;
-
- var section = new XElement("DisplaySettings");
- section.SetAttributeValue("Font", s.SelectedFont.Source);
- section.SetAttributeValue("FontSize", s.SelectedFontSize);
- section.SetAttributeValue("ShowLineNumbers", s.ShowLineNumbers);
- section.SetAttributeValue("ShowMetadataTokens", s.ShowMetadataTokens);
- section.SetAttributeValue("ShowMetadataTokensInBase10", s.ShowMetadataTokensInBase10);
- section.SetAttributeValue("ShowDebugInfo", s.ShowDebugInfo);
- section.SetAttributeValue("EnableWordWrap", s.EnableWordWrap);
- section.SetAttributeValue("SortResults", s.SortResults);
- section.SetAttributeValue("FoldBraces", s.FoldBraces);
- section.SetAttributeValue("ExpandMemberDefinitions", s.ExpandMemberDefinitions);
- section.SetAttributeValue("ExpandUsingDeclarations", s.ExpandUsingDeclarations);
- section.SetAttributeValue("IndentationUseTabs", s.IndentationUseTabs);
- section.SetAttributeValue("IndentationSize", s.IndentationSize);
- section.SetAttributeValue("IndentationTabSize", s.IndentationTabSize);
- section.SetAttributeValue("HighlightMatchingBraces", s.HighlightMatchingBraces);
- section.SetAttributeValue("HighlightCurrentLine", s.HighlightCurrentLine);
- section.SetAttributeValue("HideEmptyMetadataTables", s.HideEmptyMetadataTables);
- section.SetAttributeValue("UseNestedNamespaceNodes", s.UseNestedNamespaceNodes);
- section.SetAttributeValue("ShowRawOffsetsAndBytesBeforeInstruction", s.ShowRawOffsetsAndBytesBeforeInstruction);
- section.SetAttributeValue("StyleWindowTitleBar", s.StyleWindowTitleBar);
-
- SettingsService.Instance.SessionSettings.Theme = s.Theme;
- var sessionSettings = SettingsService.Instance.SessionSettings.ToXml();
-
- SettingsService.Instance.DisplaySettings.CopyValues(s);
-
- Update(section);
- Update(sessionSettings);
-
- void Update(XElement element)
- {
- var existingElement = root.Element(element.Name);
- if (existingElement != null)
- existingElement.ReplaceWith(element);
- else
- root.Add(element);
- }
}
private void TextBox_PreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)
@@ -179,44 +55,39 @@ namespace ICSharpCode.ILSpy.Options
e.Handled = true;
}
- private void OnPaste(object sender, DataObjectPastingEventArgs e)
+ private static void OnPaste(object sender, DataObjectPastingEventArgs e)
{
if (!e.SourceDataObject.GetDataPresent(DataFormats.UnicodeText, true))
return;
+
var text = (string)e.SourceDataObject.GetData(DataFormats.UnicodeText, true) ?? string.Empty;
+
if (!text.All(char.IsDigit))
e.CancelCommand();
}
-
- public void LoadDefaults()
- {
- SettingsService.Instance.DisplaySettings.CopyValues(new DisplaySettings());
- this.DataContext = SettingsService.Instance.DisplaySettings;
- }
}
- public class FontSizeConverter : IValueConverter
+ public sealed class FontSizeConverter : ValueConverter
{
- public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ protected override object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value is double d)
{
return Math.Round(d / 4 * 3);
}
- throw new NotImplementedException();
+ return DependencyProperty.UnsetValue;
}
- public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
+ protected override object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
- if (value is string s)
- {
- if (double.TryParse(s, out double d))
- return d * 4 / 3;
- return 11.0 * 4 / 3;
- }
+ if (value is not string s)
+ return DependencyProperty.UnsetValue;
+
+ if (double.TryParse(s, out double d))
+ return d * 4 / 3;
- throw new NotImplementedException();
+ return 11.0 * 4 / 3;
}
}
}
\ No newline at end of file
diff --git a/ILSpy/Options/DisplaySettingsViewModel.cs b/ILSpy/Options/DisplaySettingsViewModel.cs
new file mode 100644
index 000000000..4d7c53f43
--- /dev/null
+++ b/ILSpy/Options/DisplaySettingsViewModel.cs
@@ -0,0 +1,94 @@
+using ICSharpCode.ILSpyX.Settings;
+using System.Windows.Media;
+using System.Xml.Linq;
+using System;
+using System.ComponentModel.Composition;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+using TomsToolbox.Wpf;
+using ICSharpCode.ILSpy.Themes;
+
+namespace ICSharpCode.ILSpy.Options
+{
+ [ExportOptionPage(Order = 20)]
+ [PartCreationPolicy(CreationPolicy.NonShared)]
+ public class DisplaySettingsViewModel : ObservableObject, IOptionPage
+ {
+ private DisplaySettings settings = new();
+ private FontFamily[] fontFamilies;
+ private SessionSettings sessionSettings;
+
+ public DisplaySettingsViewModel()
+ {
+ fontFamilies = [settings.SelectedFont];
+
+ Task.Run(FontLoader).ContinueWith(continuation => {
+ FontFamilies = continuation.Result;
+ if (continuation.Exception == null)
+ return;
+ foreach (var ex in continuation.Exception.InnerExceptions)
+ {
+ MessageBox.Show(ex.ToString());
+ }
+ });
+ }
+
+ public string Title => Properties.Resources.Display;
+
+ public DisplaySettings Settings {
+ get => settings;
+ set => SetProperty(ref settings, value);
+ }
+
+ public SessionSettings SessionSettings {
+ get => sessionSettings;
+ set => SetProperty(ref sessionSettings, value);
+ }
+
+ public FontFamily[] FontFamilies {
+ get => fontFamilies;
+ set => SetProperty(ref fontFamilies, value);
+ }
+
+ public int[] FontSizes { get; } = Enumerable.Range(6, 24 - 6 + 1).ToArray();
+
+ public void Load(SettingsSnapshot snapshot)
+ {
+ Settings = snapshot.GetSettings();
+ SessionSettings = snapshot.GetSettings();
+ }
+
+ static bool IsSymbolFont(FontFamily fontFamily)
+ {
+ foreach (var tf in fontFamily.GetTypefaces())
+ {
+ try
+ {
+ if (tf.TryGetGlyphTypeface(out GlyphTypeface glyph))
+ return glyph.Symbol;
+ }
+ catch (Exception)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ static FontFamily[] FontLoader()
+ {
+ return Fonts.SystemFontFamilies
+ .Where(ff => !IsSymbolFont(ff))
+ .OrderBy(ff => ff.Source)
+ .ToArray();
+ }
+
+ public void LoadDefaults()
+ {
+ Settings.LoadFromXml(new XElement("empty"));
+ SessionSettings.Theme = ThemeManager.Current.DefaultTheme;
+ }
+ }
+}
diff --git a/ICSharpCode.ILSpyX/Settings/MiscSettings.cs b/ILSpy/Options/MiscSettings.cs
similarity index 56%
rename from ICSharpCode.ILSpyX/Settings/MiscSettings.cs
rename to ILSpy/Options/MiscSettings.cs
index d349764d4..75f35e81d 100644
--- a/ICSharpCode.ILSpyX/Settings/MiscSettings.cs
+++ b/ILSpy/Options/MiscSettings.cs
@@ -19,25 +19,42 @@
using System;
using System.Xml.Linq;
+using TomsToolbox.Wpf;
+
namespace ICSharpCode.ILSpyX.Settings
{
- public class MiscSettings : IMiscSettings, ISettingsSection
+ public class MiscSettings : ObservableObject, ISettingsSection
{
- private MiscSettings()
- {
+ private bool allowMultipleInstances;
+ private bool loadPreviousAssemblies = true;
+
+ public bool AllowMultipleInstances {
+ get => allowMultipleInstances;
+ set => SetProperty(ref allowMultipleInstances, value);
+ }
+
+ public bool LoadPreviousAssemblies {
+ get => loadPreviousAssemblies;
+ set => SetProperty(ref loadPreviousAssemblies, value);
}
- public bool AllowMultipleInstances { get; set; }
- public bool LoadPreviousAssemblies { get; set; }
+ public XName SectionName => "MiscSettings";
- public static MiscSettings Load(ISettingsProvider settingsProvider)
+ public void LoadFromXml(XElement e)
{
- XElement e = settingsProvider["MiscSettings"];
- var s = new MiscSettings();
- s.AllowMultipleInstances = (bool?)e.Attribute(nameof(s.AllowMultipleInstances)) ?? false;
- s.LoadPreviousAssemblies = (bool?)e.Attribute(nameof(s.LoadPreviousAssemblies)) ?? true;
+ AllowMultipleInstances = (bool?)e.Attribute(nameof(AllowMultipleInstances)) ?? false;
+ LoadPreviousAssemblies = (bool?)e.Attribute(nameof(LoadPreviousAssemblies)) ?? true;
+ }
+
+ public XElement SaveToXml()
+ {
+ var section = new XElement(SectionName);
- return s;
+ section.SetAttributeValue(nameof(AllowMultipleInstances), AllowMultipleInstances);
+ section.SetAttributeValue(nameof(LoadPreviousAssemblies), LoadPreviousAssemblies);
+
+ return section;
}
}
}
+
diff --git a/ILSpy/Options/MiscSettingsPanel.xaml b/ILSpy/Options/MiscSettingsPanel.xaml
index 502f65fcc..c3a984c9b 100644
--- a/ILSpy/Options/MiscSettingsPanel.xaml
+++ b/ILSpy/Options/MiscSettingsPanel.xaml
@@ -2,16 +2,17 @@
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:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d"
xmlns:properties="clr-namespace:ICSharpCode.ILSpy.Properties"
- mc:Ignorable="d"
+ xmlns:options="clr-namespace:ICSharpCode.ILSpy.Options"
+ d:DataContext="{d:DesignInstance options:MiscSettingsViewModel}"
d:DesignHeight="300" d:DesignWidth="300">
-
-
-
+
+
+
diff --git a/ILSpy/Options/MiscSettingsPanel.xaml.cs b/ILSpy/Options/MiscSettingsPanel.xaml.cs
index ac98981dd..d6c7c672d 100644
--- a/ILSpy/Options/MiscSettingsPanel.xaml.cs
+++ b/ILSpy/Options/MiscSettingsPanel.xaml.cs
@@ -20,53 +20,20 @@ using System.ComponentModel.Composition;
using System.Windows.Controls;
using System.Xml.Linq;
-using ICSharpCode.ILSpyX.Settings;
+using TomsToolbox.Wpf.Composition.Mef;
namespace ICSharpCode.ILSpy.Options
{
///
/// Interaction logic for MiscSettingsPanel.xaml
///
- [ExportOptionPage(Title = nameof(Properties.Resources.Misc), Order = 30)]
+ [DataTemplate(typeof(MiscSettingsViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
- public partial class MiscSettingsPanel : UserControl, IOptionPage
+ public partial class MiscSettingsPanel
{
public MiscSettingsPanel()
{
InitializeComponent();
}
-
- public void Load(ILSpySettings settings)
- {
- this.DataContext = LoadMiscSettings(settings);
- }
-
- static MiscSettingsViewModel currentMiscSettings;
-
- public static MiscSettingsViewModel CurrentMiscSettings {
- get {
- return currentMiscSettings ?? (currentMiscSettings = LoadMiscSettings(ILSpySettings.Load()));
- }
- }
-
- public static MiscSettingsViewModel LoadMiscSettings(ILSpySettings settings)
- {
- var s = MiscSettings.Load(settings);
- return new MiscSettingsViewModel(s);
- }
-
- public void Save(XElement root)
- {
- var s = (MiscSettingsViewModel)this.DataContext;
- IMiscSettings.Save(root, s);
-
- currentMiscSettings = null; // invalidate cached settings
- }
-
- public void LoadDefaults()
- {
- currentMiscSettings = new MiscSettingsViewModel(MiscSettings.Load(ILSpySettings.Load()));
- this.DataContext = currentMiscSettings;
- }
}
}
diff --git a/ILSpy/Options/MiscSettingsViewModel.cs b/ILSpy/Options/MiscSettingsViewModel.cs
index de505c349..2ed4b9868 100644
--- a/ILSpy/Options/MiscSettingsViewModel.cs
+++ b/ILSpy/Options/MiscSettingsViewModel.cs
@@ -16,89 +16,61 @@
// 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.IO;
using System.Reflection;
-using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Input;
+using System.Xml.Linq;
using ICSharpCode.ILSpy.AppEnv;
-using ICSharpCode.ILSpy.Commands;
using ICSharpCode.ILSpyX.Settings;
using Microsoft.Win32;
+using TomsToolbox.Wpf;
+
namespace ICSharpCode.ILSpy.Options
{
- public class MiscSettingsViewModel : IMiscSettings, INotifyPropertyChanged
+ [ExportOptionPage(Order = 30)]
+ [PartCreationPolicy(CreationPolicy.NonShared)]
+ public class MiscSettingsViewModel : ObservableObject, IOptionPage
{
- bool allowMultipleInstances;
- bool loadPreviousAssemblies = true;
-
- public MiscSettingsViewModel(MiscSettings s)
- {
- AllowMultipleInstances = s.AllowMultipleInstances;
- LoadPreviousAssemblies = s.LoadPreviousAssemblies;
-
- if (EnableShellIntegrationCommand)
- {
- AddRemoveShellIntegrationCommand = new DelegateCommand