From 4b475cfa6942ceaf12bbaedf4733be6f77b665a5 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 20 Mar 2022 19:56:56 +0100 Subject: [PATCH] Create ILSpyX project and make the following APIs reusable: - AssemblyList, AssemblyListManager, AssemblyListSnapshot - LoadedAssembly - LoadedPackage and friends - PDB providers --- .../ICSharpCode.Decompiler.Console.csproj | 7 +- .../IlspyCmdProgram.cs | 2 +- ...rpCode.Decompiler.PdbProvider.Cecil.csproj | 19 - .../GetDecompilerCmdlet.cs | 2 +- .../ICSharpCode.Decompiler.PowerShell.csproj | 6 +- .../Helpers/Tester.cs | 3 +- .../ICSharpCode.Decompiler.Tests.csproj | 4 +- {ILSpy => ICSharpCode.ILSpyX}/AssemblyList.cs | 115 ++++--- ICSharpCode.ILSpyX/AssemblyListManager.cs | 324 ++++++++++++++++++ .../AssemblyListSnapshot.cs | 3 +- .../Extensions/CollectionExtensions.cs | 122 +++++++ ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj | 41 +++ .../LoadedAssembly.cs | 69 ++-- .../LoadedAssemblyExtensions.cs | 11 +- .../LoadedPackage.cs | 2 +- .../PdbProvider}/DebugInfoUtils.cs | 4 +- .../MonoCecilDebugInfoProvider.cs | 2 +- .../PdbProvider}/PortableDebugInfoProvider.cs | 6 +- ICSharpCode.ILSpyX/Properties/AssemblyInfo.cs | 29 ++ ILSpy.AddIn.slnf | 2 +- .../BamlResourceNodeFactory.cs | 1 + ILSpy.Installer.slnf | 1 + ILSpy.ReadyToRun/ReadyToRunLanguage.cs | 1 + ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs | 1 - ILSpy.ReadyToRun/ReadyToRunOptions.cs | 2 + .../Analyzers/MethodUsesAnalyzerTests.cs | 5 +- .../Analyzers/TypeUsedByAnalyzerTests.cs | 9 +- ILSpy.Tests/ILSpy.Tests.csproj | 1 - ILSpy.Tests/Stub.cs | 36 -- ILSpy.Wpf.slnf | 1 + ILSpy.XPlat.slnf | 3 +- ILSpy.sln | 12 +- ILSpy/Analyzers/AnalyzerContext.cs | 1 + ILSpy/Analyzers/AnalyzerEntityTreeNode.cs | 1 + ILSpy/Analyzers/AnalyzerScope.cs | 1 + ILSpy/Analyzers/AnalyzerSearchTreeNode.cs | 1 + ILSpy/Analyzers/AnalyzerTreeNode.cs | 1 + ILSpy/Analyzers/AnalyzerTreeView.cs | 1 + ILSpy/AssemblyListManager.cs | 192 ----------- ILSpy/Commands/DecompileAllCommand.cs | 1 + ILSpy/Commands/DisassembleAllCommand.cs | 1 + .../ExtractPackageEntryContextMenuEntry.cs | 1 + ILSpy/Commands/GeneratePdbContextMenuEntry.cs | 1 + ILSpy/Commands/SaveCodeContextMenuEntry.cs | 1 + ILSpy/Commands/SortAssemblyListCommand.cs | 1 + ILSpy/EntityReference.cs | 1 + ILSpy/ExtensionMethods.cs | 131 +------ ILSpy/ILSpy.csproj | 2 +- ILSpy/ILSpySettings.cs | 14 +- .../CSharpHighlightingTokenWriter.cs | 1 + ILSpy/Languages/CSharpILMixedLanguage.cs | 2 + ILSpy/Languages/CSharpLanguage.cs | 4 +- ILSpy/Languages/ILAstLanguage.cs | 1 + ILSpy/Languages/ILLanguage.cs | 1 + ILSpy/Languages/IResourceFileHandler.cs | 2 + ILSpy/Languages/Language.cs | 1 + ILSpy/MainWindow.xaml.cs | 9 +- ILSpy/MainWindowViewModel.cs | 2 +- ILSpy/Metadata/CoffHeaderTreeNode.cs | 1 + ILSpy/Metadata/OptionalHeaderTreeNode.cs | 2 +- ILSpy/Options/DecompilerSettingsPanel.xaml.cs | 89 +---- ILSpy/Options/DecompilerSettingsViewModel.cs | 101 ++++++ ILSpy/Search/SearchPane.cs | 2 + ILSpy/SolutionWriter.cs | 1 + ILSpy/TextView/DecompilerTextView.cs | 1 + ILSpy/TreeNodes/AssemblyListTreeNode.cs | 1 + ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs | 2 +- ILSpy/TreeNodes/AssemblyTreeNode.cs | 4 +- ILSpy/TreeNodes/BaseTypesTreeNode.cs | 1 + ILSpy/TreeNodes/DerivedTypesEntryNode.cs | 3 +- ILSpy/TreeNodes/DerivedTypesTreeNode.cs | 2 +- ILSpy/TreeNodes/EventTreeNode.cs | 2 +- ILSpy/TreeNodes/FieldTreeNode.cs | 2 +- ILSpy/TreeNodes/ILSpyTreeNode.cs | 17 + ILSpy/TreeNodes/MethodTreeNode.cs | 2 +- ILSpy/TreeNodes/ModuleReferenceTreeNode.cs | 2 +- ILSpy/TreeNodes/PackageFolderTreeNode.cs | 1 + ILSpy/TreeNodes/PropertyTreeNode.cs | 2 +- ILSpy/TreeNodes/ThreadingSupport.cs | 1 - ILSpy/TreeNodes/TypeTreeNode.cs | 4 +- .../ManageAssemblyListsViewModel.cs | 115 +------ ILSpy/Views/DebugSteps.xaml.cs | 1 + ILSpy/Views/OpenFromGacDialog.xaml.cs | 1 + 83 files changed, 869 insertions(+), 712 deletions(-) delete mode 100644 ICSharpCode.Decompiler.PdbProvider.Cecil/ICSharpCode.Decompiler.PdbProvider.Cecil.csproj rename {ILSpy => ICSharpCode.ILSpyX}/AssemblyList.cs (82%) create mode 100644 ICSharpCode.ILSpyX/AssemblyListManager.cs rename {ILSpy => ICSharpCode.ILSpyX}/AssemblyListSnapshot.cs (98%) create mode 100644 ICSharpCode.ILSpyX/Extensions/CollectionExtensions.cs create mode 100644 ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj rename {ILSpy => ICSharpCode.ILSpyX}/LoadedAssembly.cs (92%) rename {ILSpy => ICSharpCode.ILSpyX}/LoadedAssemblyExtensions.cs (84%) rename {ILSpy => ICSharpCode.ILSpyX}/LoadedPackage.cs (99%) rename {ILSpy/DebugInfo => ICSharpCode.ILSpyX/PdbProvider}/DebugInfoUtils.cs (98%) rename {ICSharpCode.Decompiler.PdbProvider.Cecil => ICSharpCode.ILSpyX/PdbProvider}/MonoCecilDebugInfoProvider.cs (99%) rename {ILSpy/DebugInfo => ICSharpCode.ILSpyX/PdbProvider}/PortableDebugInfoProvider.cs (95%) create mode 100644 ICSharpCode.ILSpyX/Properties/AssemblyInfo.cs delete mode 100644 ILSpy.Tests/Stub.cs delete mode 100644 ILSpy/AssemblyListManager.cs create mode 100644 ILSpy/Options/DecompilerSettingsViewModel.cs diff --git a/ICSharpCode.Decompiler.Console/ICSharpCode.Decompiler.Console.csproj b/ICSharpCode.Decompiler.Console/ICSharpCode.Decompiler.Console.csproj index 6c4ffe35e..a67b9bcc8 100644 --- a/ICSharpCode.Decompiler.Console/ICSharpCode.Decompiler.Console.csproj +++ b/ICSharpCode.Decompiler.Console/ICSharpCode.Decompiler.Console.csproj @@ -31,17 +31,12 @@ - - - - - - + diff --git a/ICSharpCode.Decompiler.Console/IlspyCmdProgram.cs b/ICSharpCode.Decompiler.Console/IlspyCmdProgram.cs index 3459e8554..1d52dca0b 100644 --- a/ICSharpCode.Decompiler.Console/IlspyCmdProgram.cs +++ b/ICSharpCode.Decompiler.Console/IlspyCmdProgram.cs @@ -14,8 +14,8 @@ using ICSharpCode.Decompiler.CSharp.ProjectDecompiler; using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; -using ICSharpCode.Decompiler.PdbProvider; using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.ILSpyX.PdbProvider; using McMaster.Extensions.CommandLineUtils; // ReSharper disable All diff --git a/ICSharpCode.Decompiler.PdbProvider.Cecil/ICSharpCode.Decompiler.PdbProvider.Cecil.csproj b/ICSharpCode.Decompiler.PdbProvider.Cecil/ICSharpCode.Decompiler.PdbProvider.Cecil.csproj deleted file mode 100644 index 4993983fd..000000000 --- a/ICSharpCode.Decompiler.PdbProvider.Cecil/ICSharpCode.Decompiler.PdbProvider.Cecil.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - netstandard2.0 - 8.0 - true - - - - - - - - - - - - - diff --git a/ICSharpCode.Decompiler.PowerShell/GetDecompilerCmdlet.cs b/ICSharpCode.Decompiler.PowerShell/GetDecompilerCmdlet.cs index 5252ceff7..141305e2a 100644 --- a/ICSharpCode.Decompiler.PowerShell/GetDecompilerCmdlet.cs +++ b/ICSharpCode.Decompiler.PowerShell/GetDecompilerCmdlet.cs @@ -7,7 +7,7 @@ using System.Text; using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.Metadata; -using ICSharpCode.Decompiler.PdbProvider; +using ICSharpCode.ILSpyX.PdbProvider; namespace ICSharpCode.Decompiler.PowerShell { diff --git a/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj b/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj index 1945d651a..d185475b1 100644 --- a/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj +++ b/ICSharpCode.Decompiler.PowerShell/ICSharpCode.Decompiler.PowerShell.csproj @@ -19,9 +19,9 @@ - - - + + + diff --git a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs index a342dbb0b..dc67938d7 100644 --- a/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs +++ b/ICSharpCode.Decompiler.Tests/Helpers/Tester.cs @@ -37,6 +37,7 @@ using ICSharpCode.Decompiler.CSharp.Transforms; using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.ILSpyX.PdbProvider; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; @@ -672,7 +673,7 @@ namespace ICSharpCode.Decompiler.Tests.Helpers decompiler.AstTransforms.Add(new EscapeInvalidIdentifiers()); var pdbFileName = Path.ChangeExtension(assemblyFileName, ".pdb"); if (File.Exists(pdbFileName)) - decompiler.DebugInfoProvider = PdbProvider.DebugInfoUtils.FromFile(module, pdbFileName); + decompiler.DebugInfoProvider = DebugInfoUtils.FromFile(module, pdbFileName); var syntaxTree = decompiler.DecompileWholeModuleAsSingleFile(sortTypes: true); StringWriter output = new StringWriter(); diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj index b8cce13c2..c2a6a708c 100644 --- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj +++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj @@ -62,6 +62,7 @@ + @@ -100,9 +101,6 @@ - - - diff --git a/ILSpy/AssemblyList.cs b/ICSharpCode.ILSpyX/AssemblyList.cs similarity index 82% rename from ILSpy/AssemblyList.cs rename to ICSharpCode.ILSpyX/AssemblyList.cs index 46a9b9561..e24cb737b 100644 --- a/ILSpy/AssemblyList.cs +++ b/ICSharpCode.ILSpyX/AssemblyList.cs @@ -27,21 +27,24 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; -using System.Windows.Threading; using System.Xml.Linq; -namespace ICSharpCode.ILSpy +using ICSharpCode.ILSpyX.Extensions; + +namespace ICSharpCode.ILSpyX { /// /// A list of assemblies. /// public sealed class AssemblyList { + readonly Thread ownerThread; + readonly SynchronizationContext? synchronizationContext; + readonly AssemblyListManager manager; readonly string listName; /// Dirty flag, used to mark modifications so that the list is saved later bool dirty; - readonly object lockObj = new object(); /// @@ -62,17 +65,27 @@ namespace ICSharpCode.ILSpy /// readonly Dictionary byFilename = new Dictionary(StringComparer.OrdinalIgnoreCase); - public AssemblyList(string listName) + /// + /// Exists for testing only. + /// + internal AssemblyList() + { + } + + internal AssemblyList(AssemblyListManager manager, string listName) { + this.manager = manager ?? throw new ArgumentNullException(nameof(manager)); this.listName = listName; + ownerThread = Thread.CurrentThread; + synchronizationContext = SynchronizationContext.Current; assemblies.CollectionChanged += Assemblies_CollectionChanged; } /// /// Loads an assembly list from XML. /// - public AssemblyList(XElement listElement) - : this((string?)listElement.Attribute("name") ?? AssemblyListManager.DefaultListName) + internal AssemblyList(AssemblyListManager manager, XElement listElement) + : this(manager, (string?)listElement.Attribute("name") ?? AssemblyListManager.DefaultListName) { foreach (var asm in listElement.Elements("Assembly")) { @@ -85,7 +98,7 @@ namespace ICSharpCode.ILSpy /// Creates a copy of an assembly list. /// public AssemblyList(AssemblyList list, string newName) - : this(newName) + : this(list.manager, newName) { lock (lockObj) { @@ -99,15 +112,18 @@ namespace ICSharpCode.ILSpy public event NotifyCollectionChangedEventHandler CollectionChanged { add { - App.Current.Dispatcher.VerifyAccess(); + VerifyAccess(); this.assemblies.CollectionChanged += value; } remove { - App.Current.Dispatcher.VerifyAccess(); + VerifyAccess(); this.assemblies.CollectionChanged -= value; } } + public bool ApplyWinRTProjections { get; set; } + public bool UseDebugSymbols { get; set; } + /// /// Gets the loaded assemblies. This method is thread-safe. /// @@ -165,7 +181,7 @@ namespace ICSharpCode.ILSpy internal void Move(LoadedAssembly[] assembliesToMove, int index) { - App.Current.Dispatcher.VerifyAccess(); + VerifyAccess(); lock (lockObj) { foreach (LoadedAssembly asm in assembliesToMove) @@ -214,16 +230,14 @@ namespace ICSharpCode.ILSpy if (!dirty) { dirty = true; - App.Current.Dispatcher.BeginInvoke( - DispatcherPriority.Background, - new Action( - delegate { - if (dirty) - { - dirty = false; - AssemblyListManager.SaveList(this); - } - }) + BeginInvoke( + delegate { + if (dirty) + { + dirty = false; + this.manager.SaveList(this); + } + } ); } } @@ -260,7 +274,7 @@ namespace ICSharpCode.ILSpy { file = Path.GetFullPath(file); return OpenAssembly(file, () => { - var newAsm = new LoadedAssembly(this, file); + var newAsm = new LoadedAssembly(this, file, applyWinRTProjections: ApplyWinRTProjections, useDebugSymbols: UseDebugSymbols); newAsm.IsAutoLoaded = isAutoLoaded; return newAsm; }); @@ -273,7 +287,8 @@ namespace ICSharpCode.ILSpy { file = Path.GetFullPath(file); return OpenAssembly(file, () => { - var newAsm = new LoadedAssembly(this, file, stream: Task.FromResult(stream)); + var newAsm = new LoadedAssembly(this, file, stream: Task.FromResult(stream), + applyWinRTProjections: ApplyWinRTProjections, useDebugSymbols: UseDebugSymbols); newAsm.IsAutoLoaded = isAutoLoaded; return newAsm; }); @@ -281,8 +296,7 @@ namespace ICSharpCode.ILSpy LoadedAssembly OpenAssembly(string file, Func load) { - bool isUIThread = App.Current.Dispatcher.Thread == Thread.CurrentThread; - + bool isUIThread = ownerThread == Thread.CurrentThread; LoadedAssembly? asm; lock (lockObj) { @@ -299,12 +313,12 @@ namespace ICSharpCode.ILSpy } if (!isUIThread) { - App.Current.Dispatcher.BeginInvoke((Action)delegate () { + BeginInvoke(delegate () { lock (lockObj) { assemblies.Add(asm); } - }, DispatcherPriority.Normal); + }); } return asm; } @@ -315,7 +329,7 @@ namespace ICSharpCode.ILSpy /// public LoadedAssembly? HotReplaceAssembly(string file, Stream stream) { - App.Current.Dispatcher.VerifyAccess(); + VerifyAccess(); file = Path.GetFullPath(file); lock (lockObj) { @@ -325,7 +339,8 @@ namespace ICSharpCode.ILSpy if (index < 0) return null; - var newAsm = new LoadedAssembly(this, file, stream: Task.FromResult(stream)); + var newAsm = new LoadedAssembly(this, file, stream: Task.FromResult(stream), + applyWinRTProjections: ApplyWinRTProjections, useDebugSymbols: UseDebugSymbols); newAsm.IsAutoLoaded = target.IsAutoLoaded; Debug.Assert(newAsm.FileName == file); @@ -337,7 +352,7 @@ namespace ICSharpCode.ILSpy public LoadedAssembly? ReloadAssembly(string file) { - App.Current.Dispatcher.VerifyAccess(); + VerifyAccess(); file = Path.GetFullPath(file); var target = this.assemblies.FirstOrDefault(asm => file.Equals(asm.FileName, StringComparison.OrdinalIgnoreCase)); @@ -349,11 +364,12 @@ namespace ICSharpCode.ILSpy public LoadedAssembly? ReloadAssembly(LoadedAssembly target) { - App.Current.Dispatcher.VerifyAccess(); + VerifyAccess(); var index = this.assemblies.IndexOf(target); if (index < 0) return null; - var newAsm = new LoadedAssembly(this, target.FileName, pdbFileName: target.PdbFileName); + var newAsm = new LoadedAssembly(this, target.FileName, pdbFileName: target.PdbFileName, + applyWinRTProjections: ApplyWinRTProjections, useDebugSymbols: UseDebugSymbols); newAsm.IsAutoLoaded = target.IsAutoLoaded; lock (lockObj) { @@ -365,27 +381,12 @@ namespace ICSharpCode.ILSpy public void Unload(LoadedAssembly assembly) { - App.Current.Dispatcher.VerifyAccess(); + VerifyAccess(); lock (lockObj) { assemblies.Remove(assembly); byFilename.Remove(assembly.FileName); } - RequestGC(); - } - - static bool gcRequested; - - static void RequestGC() - { - if (gcRequested) - return; - gcRequested = true; - App.Current.Dispatcher.BeginInvoke(DispatcherPriority.ContextIdle, new Action( - delegate { - gcRequested = false; - GC.Collect(); - })); } public void Sort(IComparer comparer) @@ -395,7 +396,7 @@ namespace ICSharpCode.ILSpy public void Sort(int index, int count, IComparer comparer) { - App.Current.Dispatcher.VerifyAccess(); + VerifyAccess(); lock (lockObj) { List list = new List(assemblies); @@ -404,5 +405,23 @@ namespace ICSharpCode.ILSpy assemblies.AddRange(list); } } + + private void BeginInvoke(Action action) + { + if (synchronizationContext == null) + { + action(); + } + else + { + synchronizationContext.Post(new SendOrPostCallback(_ => action()), null); + } + } + + private void VerifyAccess() + { + if (this.ownerThread != Thread.CurrentThread) + throw new InvalidOperationException("This method must always be called on the thread that owns the assembly list: " + ownerThread.ManagedThreadId + " " + ownerThread.Name); + } } } diff --git a/ICSharpCode.ILSpyX/AssemblyListManager.cs b/ICSharpCode.ILSpyX/AssemblyListManager.cs new file mode 100644 index 000000000..90cd51503 --- /dev/null +++ b/ICSharpCode.ILSpyX/AssemblyListManager.cs @@ -0,0 +1,324 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// 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.ObjectModel; +using System.IO; +using System.Linq; +using System.Xml.Linq; + +using ICSharpCode.Decompiler.Metadata; + +namespace ICSharpCode.ILSpyX +{ + public interface ISettingsProvider + { + XElement this[XName section] { get; } + + void Update(Action action); + ISettingsProvider Load(); + } + + /// + /// Manages the available assembly lists. + /// + /// Contains the list of list names; and provides methods for loading/saving and creating/deleting lists. + /// + public sealed class AssemblyListManager + { + public const string DotNet4List = ".NET 4 (WPF)"; + public const string DotNet35List = ".NET 3.5"; + public const string ASPDotNetMVC3List = "ASP.NET (MVC3)"; + + private ISettingsProvider settingsProvider; + + public AssemblyListManager(ISettingsProvider settingsProvider) + { + this.settingsProvider = settingsProvider; + XElement doc = this.settingsProvider["AssemblyLists"]; + foreach (var list in doc.Elements("List")) + { + AssemblyLists.Add((string)list.Attribute("name")); + } + } + + public bool ApplyWinRTProjections { get; set; } + public bool UseDebugSymbols { get; set; } + + public ObservableCollection AssemblyLists { get; } = new ObservableCollection(); + + /// + /// Loads an assembly list from the ILSpySettings. + /// If no list with the specified name is found, the default list is loaded instead. + /// + 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) + { + XElement doc = this.settingsProvider["AssemblyLists"]; + if (listName != null) + { + foreach (var list in doc.Elements("List")) + { + if ((string)list.Attribute("name") == listName) + { + return new AssemblyList(this, list) { + UseDebugSymbols = UseDebugSymbols, + ApplyWinRTProjections = ApplyWinRTProjections + }; + } + } + } + return new AssemblyList(this, listName ?? DefaultListName) { + UseDebugSymbols = UseDebugSymbols, + ApplyWinRTProjections = ApplyWinRTProjections + }; + } + + public bool CloneList(string selectedAssemblyList, string newListName) + { + var list = DoLoadList(selectedAssemblyList); + var newList = new AssemblyList(list, newListName) { + UseDebugSymbols = UseDebugSymbols, + ApplyWinRTProjections = ApplyWinRTProjections + }; + return AddListIfNotExists(newList); + } + + public bool RenameList(string selectedAssemblyList, string newListName) + { + var list = DoLoadList(selectedAssemblyList); + var newList = new AssemblyList(list, newListName) { + UseDebugSymbols = UseDebugSymbols, + ApplyWinRTProjections = ApplyWinRTProjections + }; + return DeleteList(selectedAssemblyList) && AddListIfNotExists(newList); + } + + public const string DefaultListName = "(Default)"; + + /// + /// Saves the specified assembly list into the config file. + /// + public void SaveList(AssemblyList list) + { + this.settingsProvider.Update( + delegate (XElement root) { + XElement doc = root.Element("AssemblyLists"); + if (doc == null) + { + doc = new XElement("AssemblyLists"); + root.Add(doc); + } + XElement listElement = doc.Elements("List").FirstOrDefault(e => (string)e.Attribute("name") == list.ListName); + if (listElement != null) + listElement.ReplaceWith(list.SaveAsXml()); + else + doc.Add(list.SaveAsXml()); + }); + } + + public bool AddListIfNotExists(AssemblyList list) + { + if (!AssemblyLists.Contains(list.ListName)) + { + AssemblyLists.Add(list.ListName); + SaveList(list); + return true; + } + return false; + } + + public bool DeleteList(string Name) + { + if (AssemblyLists.Remove(Name)) + { + this.settingsProvider.Update( + delegate (XElement root) { + XElement doc = root.Element("AssemblyLists"); + if (doc == null) + { + return; + } + XElement listElement = doc.Elements("List").FirstOrDefault(e => (string)e.Attribute("name") == Name); + if (listElement != null) + listElement.Remove(); + }); + return true; + } + return false; + } + + public void ClearAll() + { + AssemblyLists.Clear(); + this.settingsProvider.Update( + delegate (XElement root) { + XElement doc = root.Element("AssemblyLists"); + if (doc == null) + { + return; + } + doc.Remove(); + }); + } + + public void CreateDefaultAssemblyLists() + { + if (AssemblyLists.Count > 0) + return; + + if (!AssemblyLists.Contains(DotNet4List)) + { + AssemblyList dotnet4 = CreateDefaultList(DotNet4List); + if (dotnet4.Count > 0) + { + AddListIfNotExists(dotnet4); + } + } + + if (!AssemblyLists.Contains(DotNet35List)) + { + AssemblyList dotnet35 = CreateDefaultList(DotNet35List); + if (dotnet35.Count > 0) + { + AddListIfNotExists(dotnet35); + } + } + + if (!AssemblyLists.Contains(ASPDotNetMVC3List)) + { + AssemblyList mvc = CreateDefaultList(ASPDotNetMVC3List); + if (mvc.Count > 0) + { + AddListIfNotExists(mvc); + } + } + } + + public AssemblyList CreateList(string name) + { + return new AssemblyList(this, name); + } + + public AssemblyList CreateDefaultList(string name, string? path = null, string? newName = null) + { + var list = new AssemblyList(this, newName ?? name); + switch (name) + { + case DotNet4List: + AddToListFromGAC("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("System.Data.DataSetExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("System.Xaml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"); + AddToListFromGAC("PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); + AddToListFromGAC("PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); + AddToListFromGAC("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); + break; + case DotNet35List: + AddToListFromGAC("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); + AddToListFromGAC("PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); + AddToListFromGAC("WindowsBase, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); + break; + case ASPDotNetMVC3List: + AddToListFromGAC("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("System.ComponentModel.DataAnnotations, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); + AddToListFromGAC("System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"); + AddToListFromGAC("System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("System.Data.DataSetExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"); + AddToListFromGAC("System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"); + AddToListFromGAC("System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"); + AddToListFromGAC("System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); + AddToListFromGAC("System.Web.ApplicationServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); + AddToListFromGAC("System.Web.DynamicData, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); + AddToListFromGAC("System.Web.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); + AddToListFromGAC("System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); + AddToListFromGAC("System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); + AddToListFromGAC("System.Web.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"); + AddToListFromGAC("System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); + AddToListFromGAC("System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); + AddToListFromGAC("System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); + AddToListFromGAC("Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"); + break; + case object _ when path != null: + foreach (var file in Directory.GetFiles(path, "*.dll")) + { + var dllname = Path.GetFileName(file); + if (DoIncludeFile(dllname)) + AddToListFromDirectory(file); + } + break; + } + return list; + + void AddToListFromGAC(string fullName) + { + AssemblyNameReference reference = AssemblyNameReference.Parse(fullName); + string? file = UniversalAssemblyResolver.GetAssemblyInGac(reference); + if (file != null) + list.OpenAssembly(file); + } + + void AddToListFromDirectory(string file) + { + if (File.Exists(file)) + list.OpenAssembly(file); + } + + bool DoIncludeFile(string fileName) + { + if (fileName == "Microsoft.DiaSymReader.Native.amd64.dll") + return false; + if (fileName.EndsWith("_cor3.dll", StringComparison.OrdinalIgnoreCase)) + return false; + if (char.IsUpper(fileName[0])) + return true; + if (fileName == "netstandard.dll") + return true; + if (fileName == "mscorlib.dll") + return true; + return false; + } + } + } +} diff --git a/ILSpy/AssemblyListSnapshot.cs b/ICSharpCode.ILSpyX/AssemblyListSnapshot.cs similarity index 98% rename from ILSpy/AssemblyListSnapshot.cs rename to ICSharpCode.ILSpyX/AssemblyListSnapshot.cs index 64c98acf5..7f6821eda 100644 --- a/ILSpy/AssemblyListSnapshot.cs +++ b/ICSharpCode.ILSpyX/AssemblyListSnapshot.cs @@ -26,8 +26,9 @@ using System.Threading.Tasks; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Util; +using ICSharpCode.ILSpyX.Extensions; -namespace ICSharpCode.ILSpy +namespace ICSharpCode.ILSpyX { class AssemblyListSnapshot { diff --git a/ICSharpCode.ILSpyX/Extensions/CollectionExtensions.cs b/ICSharpCode.ILSpyX/Extensions/CollectionExtensions.cs new file mode 100644 index 000000000..772c46476 --- /dev/null +++ b/ICSharpCode.ILSpyX/Extensions/CollectionExtensions.cs @@ -0,0 +1,122 @@ +// Copyright (c) 2022 Siegfried Pammer +// +// 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; +using System.Collections.Generic; +using System.Linq; + +using ICSharpCode.Decompiler.Util; + +namespace ICSharpCode.ILSpyX.Extensions +{ + public static class CollectionExtensions + { + public static void AddRange(this ICollection list, IEnumerable items) + { + foreach (T item in items) + if (!list.Contains(item)) + list.Add(item); + } + + public static T? PeekOrDefault(this Stack stack) + { + if (stack.Count == 0) + return default(T); + return stack.Peek(); + } + + public static int BinarySearch(this IList list, T item, int start, int count, IComparer comparer) + { + if (list == null) + throw new ArgumentNullException(nameof(list)); + if (start < 0 || start >= list.Count) + throw new ArgumentOutOfRangeException(nameof(start), start, "Value must be between 0 and " + (list.Count - 1)); + if (count < 0 || count > list.Count - start) + throw new ArgumentOutOfRangeException(nameof(count), count, "Value must be between 0 and " + (list.Count - start)); + int end = start + count - 1; + while (start <= end) + { + int pivot = (start + end) / 2; + int result = comparer.Compare(item, list[pivot]); + if (result == 0) + return pivot; + if (result < 0) + end = pivot - 1; + else + start = pivot + 1; + } + return ~start; + } + + public static int BinarySearch(this IList instance, TKey itemKey, Func keySelector) + where TKey : IComparable, IComparable + { + if (instance == null) + throw new ArgumentNullException(nameof(instance)); + if (keySelector == null) + throw new ArgumentNullException(nameof(keySelector)); + + int start = 0; + int end = instance.Count - 1; + + while (start <= end) + { + int m = (start + end) / 2; + TKey key = keySelector(instance[m]); + int result = key.CompareTo(itemKey); + if (result == 0) + return m; + if (result < 0) + start = m + 1; + else + end = m - 1; + } + return ~start; + } + + public static void InsertSorted(this IList list, T item, IComparer comparer) + { + if (list == null) + throw new ArgumentNullException(nameof(list)); + if (comparer == null) + throw new ArgumentNullException(nameof(comparer)); + + if (list.Count == 0) + { + list.Add(item); + } + else + { + int index = list.BinarySearch(item, 0, list.Count, comparer); + list.Insert(index < 0 ? ~index : index, item); + } + } + + internal static void Deconstruct(this KeyValuePair pair, out TKey key, out TValue value) + { + key = pair.Key; + value = pair.Value; + } + + internal static IEnumerable EmptyIfNull(this IEnumerable? inst) => inst ?? Enumerable.Empty(); + internal static IEnumerable EmptyIfNull(this IEnumerable? inst) => inst ?? Enumerable.Empty(); + internal static IList EmptyIfNull(this IList? inst) => inst ?? EmptyList.Instance; + internal static IList EmptyIfNull(this IList? inst) => inst ?? Array.Empty(); + } +} diff --git a/ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj b/ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj new file mode 100644 index 000000000..05386069a --- /dev/null +++ b/ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj @@ -0,0 +1,41 @@ + + + + net6.0 + enable + true + + en-US + False + False + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ILSpy/LoadedAssembly.cs b/ICSharpCode.ILSpyX/LoadedAssembly.cs similarity index 92% rename from ILSpy/LoadedAssembly.cs rename to ICSharpCode.ILSpyX/LoadedAssembly.cs index 66e9c5b5f..66c992ff0 100644 --- a/ILSpy/LoadedAssembly.cs +++ b/ICSharpCode.ILSpyX/LoadedAssembly.cs @@ -18,10 +18,8 @@ using System; using System.Buffers; -using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.Linq; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; using System.Runtime.CompilerServices; @@ -30,17 +28,16 @@ using System.Threading.Tasks; using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.Decompiler.Metadata; -using ICSharpCode.Decompiler.PdbProvider; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.Util; -using ICSharpCode.ILSpy.Options; +using ICSharpCode.ILSpyX.PdbProvider; using K4os.Compression.LZ4; #nullable enable -namespace ICSharpCode.ILSpy +namespace ICSharpCode.ILSpyX { /// /// Represents a file loaded into ILSpy. @@ -86,23 +83,31 @@ namespace ICSharpCode.ILSpy readonly string fileName; readonly string shortName; readonly IAssemblyResolver? providedAssemblyResolver; + readonly bool applyWinRTProjections; + readonly bool useDebugSymbols; public LoadedAssembly? ParentBundle { get; } public LoadedAssembly(AssemblyList assemblyList, string fileName, - Task? stream = null, IAssemblyResolver? assemblyResolver = null, string? pdbFileName = null) + Task? stream = null, IAssemblyResolver? assemblyResolver = null, string? pdbFileName = null, + bool applyWinRTProjections = false, bool useDebugSymbols = false) { this.assemblyList = assemblyList ?? throw new ArgumentNullException(nameof(assemblyList)); this.fileName = fileName ?? throw new ArgumentNullException(nameof(fileName)); this.PdbFileName = pdbFileName; this.providedAssemblyResolver = assemblyResolver; + this.applyWinRTProjections = applyWinRTProjections; + this.useDebugSymbols = useDebugSymbols; this.loadingTask = Task.Run(() => LoadAsync(stream)); // requires that this.fileName is set this.shortName = Path.GetFileNameWithoutExtension(fileName); } - public LoadedAssembly(LoadedAssembly bundle, string fileName, Task? stream, IAssemblyResolver? assemblyResolver = null) - : this(bundle.assemblyList, fileName, stream, assemblyResolver) + public LoadedAssembly(LoadedAssembly bundle, string fileName, Task? stream, + IAssemblyResolver? assemblyResolver = null, + bool applyWinRTProjections = false, bool useDebugSymbols = false) + : this(bundle.assemblyList, fileName, stream, assemblyResolver, null, + applyWinRTProjections, useDebugSymbols) { this.ParentBundle = bundle; } @@ -326,7 +331,7 @@ namespace ICSharpCode.ILSpy stream = memoryStream; } var streamOptions = stream is MemoryStream ? PEStreamOptions.PrefetchEntireImage : PEStreamOptions.Default; - return LoadAssembly(stream, streamOptions); + return LoadAssembly(stream, streamOptions, applyWinRTProjections); } // Read the module from disk Exception loadAssemblyException; @@ -334,7 +339,7 @@ namespace ICSharpCode.ILSpy { using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { - return LoadAssembly(fileStream, PEStreamOptions.PrefetchEntireImage); + return LoadAssembly(fileStream, PEStreamOptions.PrefetchEntireImage, applyWinRTProjections); } } catch (PEFileNotSupportedException ex) @@ -374,17 +379,11 @@ namespace ICSharpCode.ILSpy } } - LoadResult LoadAssembly(Stream stream, PEStreamOptions streamOptions) + LoadResult LoadAssembly(Stream stream, PEStreamOptions streamOptions, bool applyWinRTProjections) { - MetadataReaderOptions options; - if (DecompilerSettingsPanel.CurrentDecompilerSettings.ApplyWindowsRuntimeProjections) - { - options = MetadataReaderOptions.ApplyWindowsRuntimeProjections; - } - else - { - options = MetadataReaderOptions.None; - } + MetadataReaderOptions options = applyWinRTProjections + ? MetadataReaderOptions.ApplyWindowsRuntimeProjections + : MetadataReaderOptions.None; PEFile module = new PEFile(fileName, stream, streamOptions, metadataOptions: options); @@ -421,7 +420,7 @@ namespace ICSharpCode.ILSpy // Load module from decompressed data buffer using (var uncompressedStream = new MemoryStream(dst, writable: false)) { - return LoadAssembly(uncompressedStream, PEStreamOptions.PrefetchEntireImage); + return LoadAssembly(uncompressedStream, PEStreamOptions.PrefetchEntireImage, applyWinRTProjections); } } finally @@ -434,11 +433,11 @@ namespace ICSharpCode.ILSpy IDebugInfoProvider? LoadDebugInfo(PEFile module) { - if (DecompilerSettingsPanel.CurrentDecompilerSettings.UseDebugSymbols) + if (useDebugSymbols) { try { - return DebugInfoUtils.FromFile(module, PdbFileName) + return (PdbFileName != null ? DebugInfoUtils.FromFile(module, PdbFileName) : null) ?? DebugInfoUtils.LoadSymbols(module); } catch (IOException) @@ -467,6 +466,7 @@ namespace ICSharpCode.ILSpy { readonly LoadedAssembly parent; readonly bool loadOnDemand; + readonly bool applyWinRTProjections; readonly IAssemblyResolver? providedAssemblyResolver; readonly AssemblyList assemblyList; @@ -474,10 +474,12 @@ namespace ICSharpCode.ILSpy readonly Task tfmTask; readonly ReferenceLoadInfo referenceLoadInfo; - public MyAssemblyResolver(LoadedAssembly parent, AssemblyListSnapshot assemblyListSnapshot, bool loadOnDemand) + public MyAssemblyResolver(LoadedAssembly parent, AssemblyListSnapshot assemblyListSnapshot, + bool loadOnDemand, bool applyWinRTProjections) { this.parent = parent; this.loadOnDemand = loadOnDemand; + this.applyWinRTProjections = applyWinRTProjections; this.providedAssemblyResolver = parent.providedAssemblyResolver; this.assemblyList = parent.assemblyList; @@ -529,7 +531,7 @@ namespace ICSharpCode.ILSpy return module; } - string? file = parent.GetUniversalResolver().FindAssemblyFile(reference); + string? file = parent.GetUniversalResolver(applyWinRTProjections).FindAssemblyFile(reference); if (file != null) { @@ -622,23 +624,24 @@ namespace ICSharpCode.ILSpy } } - public IAssemblyResolver GetAssemblyResolver(bool loadOnDemand = true) + public IAssemblyResolver GetAssemblyResolver(bool loadOnDemand = true, bool applyWinRTProjections = false) { - return new MyAssemblyResolver(this, AssemblyList.GetSnapshot(), loadOnDemand); + return new MyAssemblyResolver(this, AssemblyList.GetSnapshot(), loadOnDemand, applyWinRTProjections); } - internal IAssemblyResolver GetAssemblyResolver(AssemblyListSnapshot snapshot, bool loadOnDemand = true) + internal IAssemblyResolver GetAssemblyResolver(AssemblyListSnapshot snapshot, + bool loadOnDemand = true, bool applyWinRTProjections = false) { - return new MyAssemblyResolver(this, snapshot, loadOnDemand); + return new MyAssemblyResolver(this, snapshot, loadOnDemand, applyWinRTProjections); } - private UniversalAssemblyResolver GetUniversalResolver() + private UniversalAssemblyResolver GetUniversalResolver(bool applyWinRTProjections) { return LazyInitializer.EnsureInitialized(ref this.universalResolver, () => { var targetFramework = this.GetTargetFrameworkIdAsync().Result; var runtimePack = this.GetRuntimePackAsync().Result; - var readerOptions = DecompilerSettingsPanel.CurrentDecompilerSettings.ApplyWindowsRuntimeProjections + var readerOptions = applyWinRTProjections ? MetadataReaderOptions.ApplyWindowsRuntimeProjections : MetadataReaderOptions.None; @@ -649,9 +652,9 @@ namespace ICSharpCode.ILSpy })!; } - public AssemblyReferenceClassifier GetAssemblyReferenceClassifier() + public AssemblyReferenceClassifier GetAssemblyReferenceClassifier(bool applyWinRTProjections) { - return GetUniversalResolver(); + return GetUniversalResolver(applyWinRTProjections); } /// diff --git a/ILSpy/LoadedAssemblyExtensions.cs b/ICSharpCode.ILSpyX/LoadedAssemblyExtensions.cs similarity index 84% rename from ILSpy/LoadedAssemblyExtensions.cs rename to ICSharpCode.ILSpyX/LoadedAssemblyExtensions.cs index 05d210145..724310e07 100644 --- a/ILSpy/LoadedAssemblyExtensions.cs +++ b/ICSharpCode.ILSpyX/LoadedAssemblyExtensions.cs @@ -5,7 +5,7 @@ using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; -namespace ICSharpCode.ILSpy +namespace ICSharpCode.ILSpyX { public static class LoadedAssemblyExtensions { @@ -36,21 +36,16 @@ namespace ICSharpCode.ILSpy return GetLoadedAssembly(file).GetAssemblyResolver(snapshot, loadOnDemand); } - public static IDebugInfoProvider GetDebugInfoOrNull(this PEFile file) + public static IDebugInfoProvider? GetDebugInfoOrNull(this PEFile file) { return GetLoadedAssembly(file).GetDebugInfoOrNull(); } - public static ICompilation GetTypeSystemOrNull(this PEFile file) + public static ICompilation? GetTypeSystemOrNull(this PEFile file) { return GetLoadedAssembly(file).GetTypeSystemOrNull(); } - public static ICompilation GetTypeSystemWithCurrentOptionsOrNull(this PEFile file) - { - return GetLoadedAssembly(file).GetTypeSystemOrNull(DecompilerTypeSystem.GetOptions(new DecompilationOptions().DecompilerSettings)); - } - public static LoadedAssembly GetLoadedAssembly(this PEFile file) { if (file == null) diff --git a/ILSpy/LoadedPackage.cs b/ICSharpCode.ILSpyX/LoadedPackage.cs similarity index 99% rename from ILSpy/LoadedPackage.cs rename to ICSharpCode.ILSpyX/LoadedPackage.cs index 2acf98e62..ffe789cdb 100644 --- a/ILSpy/LoadedPackage.cs +++ b/ICSharpCode.ILSpyX/LoadedPackage.cs @@ -31,7 +31,7 @@ using System.Threading.Tasks; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; -namespace ICSharpCode.ILSpy +namespace ICSharpCode.ILSpyX { /// /// NuGet package or .NET bundle: diff --git a/ILSpy/DebugInfo/DebugInfoUtils.cs b/ICSharpCode.ILSpyX/PdbProvider/DebugInfoUtils.cs similarity index 98% rename from ILSpy/DebugInfo/DebugInfoUtils.cs rename to ICSharpCode.ILSpyX/PdbProvider/DebugInfoUtils.cs index cd3f9b596..16cbe284d 100644 --- a/ILSpy/DebugInfo/DebugInfoUtils.cs +++ b/ICSharpCode.ILSpyX/PdbProvider/DebugInfoUtils.cs @@ -26,9 +26,9 @@ using System.Runtime.InteropServices; using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.Decompiler.Metadata; -namespace ICSharpCode.Decompiler.PdbProvider +namespace ICSharpCode.ILSpyX.PdbProvider { - static class DebugInfoUtils + public static class DebugInfoUtils { public static IDebugInfoProvider LoadSymbols(PEFile module) { diff --git a/ICSharpCode.Decompiler.PdbProvider.Cecil/MonoCecilDebugInfoProvider.cs b/ICSharpCode.ILSpyX/PdbProvider/MonoCecilDebugInfoProvider.cs similarity index 99% rename from ICSharpCode.Decompiler.PdbProvider.Cecil/MonoCecilDebugInfoProvider.cs rename to ICSharpCode.ILSpyX/PdbProvider/MonoCecilDebugInfoProvider.cs index 0ca165e06..8d2f9e272 100644 --- a/ICSharpCode.Decompiler.PdbProvider.Cecil/MonoCecilDebugInfoProvider.cs +++ b/ICSharpCode.ILSpyX/PdbProvider/MonoCecilDebugInfoProvider.cs @@ -31,7 +31,7 @@ using Mono.Cecil.Pdb; using SRM = System.Reflection.Metadata; -namespace ICSharpCode.Decompiler.PdbProvider +namespace ICSharpCode.ILSpyX.PdbProvider { public class MonoCecilDebugInfoProvider : IDebugInfoProvider { diff --git a/ILSpy/DebugInfo/PortableDebugInfoProvider.cs b/ICSharpCode.ILSpyX/PdbProvider/PortableDebugInfoProvider.cs similarity index 95% rename from ILSpy/DebugInfo/PortableDebugInfoProvider.cs rename to ICSharpCode.ILSpyX/PdbProvider/PortableDebugInfoProvider.cs index f4c04cd3b..b04198c80 100644 --- a/ILSpy/DebugInfo/PortableDebugInfoProvider.cs +++ b/ICSharpCode.ILSpyX/PdbProvider/PortableDebugInfoProvider.cs @@ -23,7 +23,7 @@ using System.Reflection.Metadata; using ICSharpCode.Decompiler.DebugInfo; -namespace ICSharpCode.Decompiler.PdbProvider +namespace ICSharpCode.ILSpyX.PdbProvider { class PortableDebugInfoProvider : IDebugInfoProvider { @@ -80,11 +80,11 @@ namespace ICSharpCode.Decompiler.PdbProvider public string SourceFileName => pdbFileName ?? moduleFileName; - public IList GetSequencePoints(MethodDefinitionHandle method) + public IList GetSequencePoints(MethodDefinitionHandle method) { var metadata = GetMetadataReader(); var debugInfo = metadata.GetMethodDebugInformation(method); - var sequencePoints = new List(); + var sequencePoints = new List(); if (metadata == null) return sequencePoints; diff --git a/ICSharpCode.ILSpyX/Properties/AssemblyInfo.cs b/ICSharpCode.ILSpyX/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..25750d5ce --- /dev/null +++ b/ICSharpCode.ILSpyX/Properties/AssemblyInfo.cs @@ -0,0 +1,29 @@ +#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 + +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible(false)] + +[assembly: AssemblyVersion(DecompilerVersionInfo.Major + "." + DecompilerVersionInfo.Minor + "." + DecompilerVersionInfo.Build + "." + DecompilerVersionInfo.Revision)] +[assembly: AssemblyInformationalVersion(DecompilerVersionInfo.FullVersionWithShortCommitHash)] + +[assembly: SupportedOSPlatform("Windows7.0")] +[assembly: TargetPlatform("Windows10.0")] + +[assembly: SuppressMessage("Microsoft.Usage", "CA2243:AttributeStringLiteralsShouldParseCorrectly", + Justification = "AssemblyInformationalVersion does not need to be a parsable version")] + +[assembly: InternalsVisibleTo("ILSpy, PublicKey=00240000048000009400000006020000002400005253413100040000010001004dcf3979c4e902efa4dd2163a039701ed5822e6f1134d77737296abbb97bf0803083cfb2117b4f5446a217782f5c7c634f9fe1fc60b4c11d62c5b3d33545036706296d31903ddcf750875db38a8ac379512f51620bb948c94d0831125fbc5fe63707cbb93f48c1459c4d1749eb7ac5e681a2f0d6d7c60fa527a3c0b8f92b02bf")] +[assembly: InternalsVisibleTo("ILSpy.Tests")] + + diff --git a/ILSpy.AddIn.slnf b/ILSpy.AddIn.slnf index 21f14e948..8dbeea0a1 100644 --- a/ILSpy.AddIn.slnf +++ b/ILSpy.AddIn.slnf @@ -2,9 +2,9 @@ "solution": { "path": "ILSpy.sln", "projects": [ - "ICSharpCode.Decompiler.PdbProvider.Cecil\\ICSharpCode.Decompiler.PdbProvider.Cecil.csproj", "ICSharpCode.Decompiler.Tests\\ICSharpCode.Decompiler.Tests.csproj", "ICSharpCode.Decompiler\\ICSharpCode.Decompiler.csproj", + "ICSharpCode.ILSpyX\\ICSharpCode.ILSpyX.csproj", "ILSpy.AddIn.Shared\\ILSpy.AddIn.Shared.shproj", "ILSpy.AddIn.VS2022\\ILSpy.AddIn.VS2022.csproj", "ILSpy.AddIn\\ILSpy.AddIn.csproj", diff --git a/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs b/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs index f2c0b375c..c5f086342 100644 --- a/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs +++ b/ILSpy.BamlDecompiler/BamlResourceNodeFactory.cs @@ -23,6 +23,7 @@ using System.IO; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy; using ICSharpCode.ILSpy.TreeNodes; +using ICSharpCode.ILSpyX; namespace ILSpy.BamlDecompiler { diff --git a/ILSpy.Installer.slnf b/ILSpy.Installer.slnf index a45d85373..bff5364a2 100644 --- a/ILSpy.Installer.slnf +++ b/ILSpy.Installer.slnf @@ -5,6 +5,7 @@ "ICSharpCode.Decompiler.PdbProvider.Cecil\\ICSharpCode.Decompiler.PdbProvider.Cecil.csproj", "ICSharpCode.Decompiler.Tests\\ICSharpCode.Decompiler.Tests.csproj", "ICSharpCode.Decompiler\\ICSharpCode.Decompiler.csproj", + "ICSharpCode.ILSpyX\\ICSharpCode.ILSpyX.csproj", "ILSpy.BamlDecompiler.Tests\\ILSpy.BamlDecompiler.Tests.csproj", "ILSpy.BamlDecompiler\\ILSpy.BamlDecompiler.csproj", "ILSpy.ReadyToRun\\ILSpy.ReadyToRun.csproj", diff --git a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs index 037cb7903..d8db74e98 100644 --- a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs +++ b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs @@ -33,6 +33,7 @@ using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Solution; using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.ILSpyX; using ILCompiler.Reflection.ReadyToRun; diff --git a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs index 415d3f729..fed74fb2c 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs +++ b/ILSpy.ReadyToRun/ReadyToRunOptionPage.xaml.cs @@ -22,7 +22,6 @@ using System.Xml.Linq; using ICSharpCode.ILSpy.Options; -using ILSpy.ReadyToRun; namespace ICSharpCode.ILSpy.ReadyToRun { [ExportOptionPage(Title = nameof(global::ILSpy.ReadyToRun.Properties.Resources.ReadyToRun), Order = 40)] diff --git a/ILSpy.ReadyToRun/ReadyToRunOptions.cs b/ILSpy.ReadyToRun/ReadyToRunOptions.cs index 3fbd6df6c..8f8d5d75e 100644 --- a/ILSpy.ReadyToRun/ReadyToRunOptions.cs +++ b/ILSpy.ReadyToRun/ReadyToRunOptions.cs @@ -18,6 +18,8 @@ using System.Xml.Linq; +using ICSharpCode.ILSpyX; + namespace ICSharpCode.ILSpy.ReadyToRun { internal class ReadyToRunOptions diff --git a/ILSpy.Tests/Analyzers/MethodUsesAnalyzerTests.cs b/ILSpy.Tests/Analyzers/MethodUsesAnalyzerTests.cs index e502891ac..0f9f46cbb 100644 --- a/ILSpy.Tests/Analyzers/MethodUsesAnalyzerTests.cs +++ b/ILSpy.Tests/Analyzers/MethodUsesAnalyzerTests.cs @@ -8,6 +8,7 @@ using System.Windows; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.Analyzers; using ICSharpCode.ILSpy.Analyzers.Builtin; +using ICSharpCode.ILSpyX; using NUnit.Framework; @@ -25,9 +26,7 @@ namespace ICSharpCode.ILSpy.Tests.Analyzers [OneTimeSetUp] public void Setup() { - Stub.SetupApplication(); - Options.DecompilerSettingsPanel.TestSetup(new Decompiler.DecompilerSettings()); - assemblyList = new AssemblyList("Test"); + assemblyList = new AssemblyList(); testAssembly = assemblyList.OpenAssembly(typeof(MethodUsesAnalyzerTests).Assembly.Location); assemblyList.OpenAssembly(typeof(void).Assembly.Location); testAssemblyTypeSystem = testAssembly.GetTypeSystemOrNull(); diff --git a/ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs b/ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs index 6a57daa8c..76af5ca9c 100644 --- a/ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs +++ b/ILSpy.Tests/Analyzers/TypeUsedByAnalyzerTests.cs @@ -23,17 +23,18 @@ using System.Text; using System.Threading.Tasks; using System.Windows; +using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.ILSpy.Analyzers; using ICSharpCode.ILSpy.Analyzers.Builtin; +using ICSharpCode.ILSpyX; using NUnit.Framework; namespace ICSharpCode.ILSpy.Tests.Analyzers { [TestFixture, Parallelizable(ParallelScope.All)] - [Ignore("Only one test case can be executed, the test setup is really hacky and the whole ILSpy UI should be refactored and made mockable/testable, remove singletons, dependencies on Application.Current.Dispatcher, etc.")] public class TypeUsedByAnalyzerTests { AssemblyList assemblyList; @@ -44,11 +45,9 @@ namespace ICSharpCode.ILSpy.Tests.Analyzers [OneTimeSetUp] public void Setup() { - Stub.SetupApplication(); - Options.DecompilerSettingsPanel.TestSetup(new Decompiler.DecompilerSettings()); - assemblyList = new AssemblyList("Test"); + assemblyList = new AssemblyList(); testAssembly = assemblyList.OpenAssembly(typeof(MethodUsesAnalyzerTests).Assembly.Location); - testAssemblyTypeSystem = new SimpleCompilation(testAssembly.GetPEFileOrNull(), assemblyList.OpenAssembly(typeof(void).Assembly.Location).GetPEFileOrNull()); + testAssemblyTypeSystem = new DecompilerTypeSystem(testAssembly.GetPEFileOrNull(), testAssembly.GetAssemblyResolver()); language = new CSharpLanguage(); } diff --git a/ILSpy.Tests/ILSpy.Tests.csproj b/ILSpy.Tests/ILSpy.Tests.csproj index 3e136338b..345189f44 100644 --- a/ILSpy.Tests/ILSpy.Tests.csproj +++ b/ILSpy.Tests/ILSpy.Tests.csproj @@ -38,7 +38,6 @@ - diff --git a/ILSpy.Tests/Stub.cs b/ILSpy.Tests/Stub.cs deleted file mode 100644 index 6763528d4..000000000 --- a/ILSpy.Tests/Stub.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2020 Siegfried Pammer -// -// 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.Windows; - -namespace ICSharpCode.ILSpy.Tests -{ - public static class Stub - { - static readonly object sync = new object(); - - internal static void SetupApplication() - { - lock (sync) - { - if (Application.Current == null) - new Application(); - } - } - } -} diff --git a/ILSpy.Wpf.slnf b/ILSpy.Wpf.slnf index 259436d4c..e27dd18c4 100644 --- a/ILSpy.Wpf.slnf +++ b/ILSpy.Wpf.slnf @@ -5,6 +5,7 @@ "ICSharpCode.Decompiler.PdbProvider.Cecil\\ICSharpCode.Decompiler.PdbProvider.Cecil.csproj", "ICSharpCode.Decompiler.Tests\\ICSharpCode.Decompiler.Tests.csproj", "ICSharpCode.Decompiler\\ICSharpCode.Decompiler.csproj", + "ICSharpCode.ILSpyX\\ICSharpCode.ILSpyX.csproj", "ILSpy.BamlDecompiler.Tests\\ILSpy.BamlDecompiler.Tests.csproj", "ILSpy.BamlDecompiler\\ILSpy.BamlDecompiler.csproj", "ILSpy.ReadyToRun\\ILSpy.ReadyToRun.csproj", diff --git a/ILSpy.XPlat.slnf b/ILSpy.XPlat.slnf index 02445a148..c7272c267 100644 --- a/ILSpy.XPlat.slnf +++ b/ILSpy.XPlat.slnf @@ -5,7 +5,8 @@ "ICSharpCode.Decompiler.Console\\ICSharpCode.Decompiler.Console.csproj", "ICSharpCode.Decompiler.PowerShell\\ICSharpCode.Decompiler.PowerShell.csproj", "ICSharpCode.Decompiler.Tests\\ICSharpCode.Decompiler.Tests.csproj", - "ICSharpCode.Decompiler\\ICSharpCode.Decompiler.csproj" + "ICSharpCode.Decompiler\\ICSharpCode.Decompiler.csproj", + "ICSharpCode.ILSpyX\\ICSharpCode.ILSpyX.csproj" ] } } \ No newline at end of file diff --git a/ILSpy.sln b/ILSpy.sln index bbb51a9b5..ff994e7b8 100644 --- a/ILSpy.sln +++ b/ILSpy.sln @@ -37,8 +37,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.AddIn", "ILSpy.AddIn\ {1E85EFF9-E370-4683-83E4-8A3D063FF791} = {1E85EFF9-E370-4683-83E4-8A3D063FF791} EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.Decompiler.PdbProvider.Cecil", "ICSharpCode.Decompiler.PdbProvider.Cecil\ICSharpCode.Decompiler.PdbProvider.Cecil.csproj", "{B85A155A-9DD6-43BC-A624-2D8EC773D71F}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.Tests", "ILSpy.Tests\ILSpy.Tests.csproj", "{B51C6636-B8D1-4200-9869-08F2689DE6C2}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.ReadyToRun", "ILSpy.ReadyToRun\ILSpy.ReadyToRun.csproj", "{0313F581-C63B-43BB-AA9B-07615DABD8A3}" @@ -65,6 +63,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILSpy.Installer", "ILSpy.In EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.Decompiler.TestRunner", "ICSharpCode.Decompiler.TestRunner\ICSharpCode.Decompiler.TestRunner.csproj", "{4FBB470F-69EB-4C8B-8961-8B4DF4EBB999}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ICSharpCode.ILSpyX", "ICSharpCode.ILSpyX\ICSharpCode.ILSpyX.csproj", "{F8EFCF9D-B9A3-4BA0-A1B2-B026A71DAC22}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution ILSpy.AddIn.Shared\ILSpy.AddIn.Shared.projitems*{09a03980-d14a-4705-a38c-741ad7166dee}*SharedItemsImports = 5 @@ -108,10 +108,6 @@ Global {9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Debug|Any CPU.Build.0 = Debug|Any CPU {9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Release|Any CPU.ActiveCfg = Release|Any CPU {9D7BE6C0-B7B3-4A50-A54E-18A2D84A3384}.Release|Any CPU.Build.0 = Release|Any CPU - {B85A155A-9DD6-43BC-A624-2D8EC773D71F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B85A155A-9DD6-43BC-A624-2D8EC773D71F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B85A155A-9DD6-43BC-A624-2D8EC773D71F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B85A155A-9DD6-43BC-A624-2D8EC773D71F}.Release|Any CPU.Build.0 = Release|Any CPU {B51C6636-B8D1-4200-9869-08F2689DE6C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B51C6636-B8D1-4200-9869-08F2689DE6C2}.Debug|Any CPU.Build.0 = Debug|Any CPU {B51C6636-B8D1-4200-9869-08F2689DE6C2}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -140,6 +136,10 @@ Global {4FBB470F-69EB-4C8B-8961-8B4DF4EBB999}.Debug|Any CPU.Build.0 = Debug|Any CPU {4FBB470F-69EB-4C8B-8961-8B4DF4EBB999}.Release|Any CPU.ActiveCfg = Release|Any CPU {4FBB470F-69EB-4C8B-8961-8B4DF4EBB999}.Release|Any CPU.Build.0 = Release|Any CPU + {F8EFCF9D-B9A3-4BA0-A1B2-B026A71DAC22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F8EFCF9D-B9A3-4BA0-A1B2-B026A71DAC22}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F8EFCF9D-B9A3-4BA0-A1B2-B026A71DAC22}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F8EFCF9D-B9A3-4BA0-A1B2-B026A71DAC22}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ILSpy/Analyzers/AnalyzerContext.cs b/ILSpy/Analyzers/AnalyzerContext.cs index 47a7b517b..2e3657103 100644 --- a/ILSpy/Analyzers/AnalyzerContext.cs +++ b/ILSpy/Analyzers/AnalyzerContext.cs @@ -23,6 +23,7 @@ using System.Threading; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.ILSpyX; namespace ICSharpCode.ILSpy.Analyzers { diff --git a/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs b/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs index ee1fc4ee9..782821c47 100644 --- a/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs +++ b/ILSpy/Analyzers/AnalyzerEntityTreeNode.cs @@ -21,6 +21,7 @@ using System.Windows; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.TreeNodes; +using ICSharpCode.ILSpyX; using ICSharpCode.TreeView; namespace ICSharpCode.ILSpy.Analyzers diff --git a/ILSpy/Analyzers/AnalyzerScope.cs b/ILSpy/Analyzers/AnalyzerScope.cs index 6b5735be8..6377549b2 100644 --- a/ILSpy/Analyzers/AnalyzerScope.cs +++ b/ILSpy/Analyzers/AnalyzerScope.cs @@ -24,6 +24,7 @@ using System.Threading; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Util; +using ICSharpCode.ILSpyX; namespace ICSharpCode.ILSpy.Analyzers { diff --git a/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs b/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs index f0965c3bf..6b908d1ff 100644 --- a/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs +++ b/ILSpy/Analyzers/AnalyzerSearchTreeNode.cs @@ -24,6 +24,7 @@ using System.Threading; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.Analyzers.TreeNodes; using ICSharpCode.ILSpy.TreeNodes; +using ICSharpCode.ILSpyX; namespace ICSharpCode.ILSpy.Analyzers { diff --git a/ILSpy/Analyzers/AnalyzerTreeNode.cs b/ILSpy/Analyzers/AnalyzerTreeNode.cs index 96a1a1a5e..5f9b39650 100644 --- a/ILSpy/Analyzers/AnalyzerTreeNode.cs +++ b/ILSpy/Analyzers/AnalyzerTreeNode.cs @@ -20,6 +20,7 @@ using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; +using ICSharpCode.ILSpyX; using ICSharpCode.TreeView; namespace ICSharpCode.ILSpy.Analyzers diff --git a/ILSpy/Analyzers/AnalyzerTreeView.cs b/ILSpy/Analyzers/AnalyzerTreeView.cs index 261e52b18..500f40f79 100644 --- a/ILSpy/Analyzers/AnalyzerTreeView.cs +++ b/ILSpy/Analyzers/AnalyzerTreeView.cs @@ -26,6 +26,7 @@ using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.Analyzers.TreeNodes; using ICSharpCode.ILSpy.Docking; using ICSharpCode.ILSpy.ViewModels; +using ICSharpCode.ILSpyX; using ICSharpCode.TreeView; namespace ICSharpCode.ILSpy.Analyzers diff --git a/ILSpy/AssemblyListManager.cs b/ILSpy/AssemblyListManager.cs deleted file mode 100644 index 8000f3b51..000000000 --- a/ILSpy/AssemblyListManager.cs +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of this -// software and associated documentation files (the "Software"), to deal in the Software -// without restriction, including without limitation the rights to use, copy, modify, merge, -// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons -// to whom the Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all copies or -// substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE -// 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.ObjectModel; -using System.Linq; -using System.Xml.Linq; - -using ICSharpCode.ILSpy.ViewModels; - -namespace ICSharpCode.ILSpy -{ - /// - /// Manages the available assembly lists. - /// - /// Contains the list of list names; and provides methods for loading/saving and creating/deleting lists. - /// - sealed class AssemblyListManager - { - ILSpySettings spySettings; - - public AssemblyListManager(ILSpySettings spySettings) - { - this.spySettings = spySettings; - XElement doc = spySettings["AssemblyLists"]; - foreach (var list in doc.Elements("List")) - { - AssemblyLists.Add((string)list.Attribute("name")); - } - } - - public ObservableCollection AssemblyLists { get; } = new ObservableCollection(); - - /// - /// Loads an assembly list from the ILSpySettings. - /// If no list with the specified name is found, the default list is loaded instead. - /// - public AssemblyList LoadList(ILSpySettings settings, string listName) - { - this.spySettings = settings; - AssemblyList list = DoLoadList(spySettings, listName); - if (!AssemblyLists.Contains(list.ListName)) - AssemblyLists.Add(list.ListName); - return list; - } - - AssemblyList DoLoadList(ILSpySettings spySettings, string listName) - { - XElement doc = spySettings["AssemblyLists"]; - if (listName != null) - { - foreach (var list in doc.Elements("List")) - { - if ((string)list.Attribute("name") == listName) - { - return new AssemblyList(list); - } - } - } - return new AssemblyList(listName ?? DefaultListName); - } - - public bool CloneList(string selectedAssemblyList, string newListName) - { - var list = DoLoadList(spySettings, selectedAssemblyList); - var newList = new AssemblyList(list, newListName); - return CreateList(newList); - } - - public bool RenameList(string selectedAssemblyList, string newListName) - { - var list = DoLoadList(spySettings, selectedAssemblyList); - var newList = new AssemblyList(list, newListName); - return DeleteList(selectedAssemblyList) && CreateList(newList); - } - - public const string DefaultListName = "(Default)"; - - /// - /// Saves the specifies assembly list into the config file. - /// - public static void SaveList(AssemblyList list) - { - ILSpySettings.Update( - delegate (XElement root) { - XElement doc = root.Element("AssemblyLists"); - if (doc == null) - { - doc = new XElement("AssemblyLists"); - root.Add(doc); - } - XElement listElement = doc.Elements("List").FirstOrDefault(e => (string)e.Attribute("name") == list.ListName); - if (listElement != null) - listElement.ReplaceWith(list.SaveAsXml()); - else - doc.Add(list.SaveAsXml()); - }); - } - - public bool CreateList(AssemblyList list) - { - if (!AssemblyLists.Contains(list.ListName)) - { - AssemblyLists.Add(list.ListName); - SaveList(list); - return true; - } - return false; - } - - public bool DeleteList(string Name) - { - if (AssemblyLists.Remove(Name)) - { - ILSpySettings.Update( - delegate (XElement root) { - XElement doc = root.Element("AssemblyLists"); - if (doc == null) - { - return; - } - XElement listElement = doc.Elements("List").FirstOrDefault(e => (string)e.Attribute("name") == Name); - if (listElement != null) - listElement.Remove(); - }); - return true; - } - return false; - } - - public void ClearAll() - { - AssemblyLists.Clear(); - ILSpySettings.Update( - delegate (XElement root) { - XElement doc = root.Element("AssemblyLists"); - if (doc == null) - { - return; - } - doc.Remove(); - }); - } - - public void CreateDefaultAssemblyLists() - { - if (AssemblyLists.Count > 0) - return; - - if (!AssemblyLists.Contains(ManageAssemblyListsViewModel.DotNet4List)) - { - AssemblyList dotnet4 = ManageAssemblyListsViewModel.CreateDefaultList(ManageAssemblyListsViewModel.DotNet4List); - if (dotnet4.Count > 0) - { - CreateList(dotnet4); - } - } - - if (!AssemblyLists.Contains(ManageAssemblyListsViewModel.DotNet35List)) - { - AssemblyList dotnet35 = ManageAssemblyListsViewModel.CreateDefaultList(ManageAssemblyListsViewModel.DotNet35List); - if (dotnet35.Count > 0) - { - CreateList(dotnet35); - } - } - - if (!AssemblyLists.Contains(ManageAssemblyListsViewModel.ASPDotNetMVC3List)) - { - AssemblyList mvc = ManageAssemblyListsViewModel.CreateDefaultList(ManageAssemblyListsViewModel.ASPDotNetMVC3List); - if (mvc.Count > 0) - { - CreateList(mvc); - } - } - } - } -} diff --git a/ILSpy/Commands/DecompileAllCommand.cs b/ILSpy/Commands/DecompileAllCommand.cs index ca6f926c5..bda0d7a93 100644 --- a/ILSpy/Commands/DecompileAllCommand.cs +++ b/ILSpy/Commands/DecompileAllCommand.cs @@ -27,6 +27,7 @@ using System.Threading.Tasks; using ICSharpCode.Decompiler; using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.TextView; +using ICSharpCode.ILSpyX; namespace ICSharpCode.ILSpy { diff --git a/ILSpy/Commands/DisassembleAllCommand.cs b/ILSpy/Commands/DisassembleAllCommand.cs index 849dd15d7..a127c5203 100644 --- a/ILSpy/Commands/DisassembleAllCommand.cs +++ b/ILSpy/Commands/DisassembleAllCommand.cs @@ -25,6 +25,7 @@ using System.Threading.Tasks; using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.TextView; +using ICSharpCode.ILSpyX; namespace ICSharpCode.ILSpy { diff --git a/ILSpy/Commands/ExtractPackageEntryContextMenuEntry.cs b/ILSpy/Commands/ExtractPackageEntryContextMenuEntry.cs index 79974c89b..57076e517 100644 --- a/ILSpy/Commands/ExtractPackageEntryContextMenuEntry.cs +++ b/ILSpy/Commands/ExtractPackageEntryContextMenuEntry.cs @@ -27,6 +27,7 @@ using ICSharpCode.Decompiler.CSharp.ProjectDecompiler; using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TreeNodes; +using ICSharpCode.ILSpyX; using Microsoft.Win32; diff --git a/ILSpy/Commands/GeneratePdbContextMenuEntry.cs b/ILSpy/Commands/GeneratePdbContextMenuEntry.cs index 473360ff5..351e96e10 100644 --- a/ILSpy/Commands/GeneratePdbContextMenuEntry.cs +++ b/ILSpy/Commands/GeneratePdbContextMenuEntry.cs @@ -30,6 +30,7 @@ using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TreeNodes; +using ICSharpCode.ILSpyX; using Microsoft.Win32; diff --git a/ILSpy/Commands/SaveCodeContextMenuEntry.cs b/ILSpy/Commands/SaveCodeContextMenuEntry.cs index 0a849f134..a16316fac 100644 --- a/ILSpy/Commands/SaveCodeContextMenuEntry.cs +++ b/ILSpy/Commands/SaveCodeContextMenuEntry.cs @@ -22,6 +22,7 @@ using System.IO; using System.Linq; using System.Windows; +using ICSharpCode.ILSpy.Options; using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.ViewModels; diff --git a/ILSpy/Commands/SortAssemblyListCommand.cs b/ILSpy/Commands/SortAssemblyListCommand.cs index a57999a71..29cd8ae05 100644 --- a/ILSpy/Commands/SortAssemblyListCommand.cs +++ b/ILSpy/Commands/SortAssemblyListCommand.cs @@ -20,6 +20,7 @@ using System; using System.Collections.Generic; using ICSharpCode.ILSpy.Properties; +using ICSharpCode.ILSpyX; using ICSharpCode.TreeView; namespace ICSharpCode.ILSpy diff --git a/ILSpy/EntityReference.cs b/ILSpy/EntityReference.cs index 1ff1ce7e7..86ebd55a2 100644 --- a/ILSpy/EntityReference.cs +++ b/ILSpy/EntityReference.cs @@ -21,6 +21,7 @@ using System.Diagnostics; using System.Reflection.Metadata; using ICSharpCode.Decompiler.Metadata; +using ICSharpCode.ILSpyX; namespace ICSharpCode.ILSpy { diff --git a/ILSpy/ExtensionMethods.cs b/ILSpy/ExtensionMethods.cs index de2bd4189..732dc7b4e 100644 --- a/ILSpy/ExtensionMethods.cs +++ b/ILSpy/ExtensionMethods.cs @@ -26,8 +26,11 @@ using System.Windows; using System.Windows.Controls; using System.Windows.Media; +using ICSharpCode.Decompiler.Metadata; +using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; using ICSharpCode.ILSpy.Options; +using ICSharpCode.ILSpyX; namespace ICSharpCode.ILSpy { @@ -36,134 +39,17 @@ namespace ICSharpCode.ILSpy /// public static class ExtensionMethods { - public static void AddRange(this ICollection list, IEnumerable items) + public static string ToSuffixString(this System.Reflection.Metadata.EntityHandle handle, bool showMetadataTokens, bool useBase10) { - foreach (T item in items) - if (!list.Contains(item)) - list.Add(item); - } - - public static T? PeekOrDefault(this Stack stack) - { - if (stack.Count == 0) - return default(T); - return stack.Peek(); - } - - public static int BinarySearch(this IList list, T item, int start, int count, IComparer comparer) - { - if (list == null) - throw new ArgumentNullException(nameof(list)); - if (start < 0 || start >= list.Count) - throw new ArgumentOutOfRangeException(nameof(start), start, "Value must be between 0 and " + (list.Count - 1)); - if (count < 0 || count > list.Count - start) - throw new ArgumentOutOfRangeException(nameof(count), count, "Value must be between 0 and " + (list.Count - start)); - int end = start + count - 1; - while (start <= end) - { - int pivot = (start + end) / 2; - int result = comparer.Compare(item, list[pivot]); - if (result == 0) - return pivot; - if (result < 0) - end = pivot - 1; - else - start = pivot + 1; - } - return ~start; - } - - public static int BinarySearch(this IList instance, TKey itemKey, Func keySelector) - where TKey : IComparable, IComparable - { - if (instance == null) - throw new ArgumentNullException(nameof(instance)); - if (keySelector == null) - throw new ArgumentNullException(nameof(keySelector)); - - int start = 0; - int end = instance.Count - 1; - - while (start <= end) - { - int m = (start + end) / 2; - TKey key = keySelector(instance[m]); - int result = key.CompareTo(itemKey); - if (result == 0) - return m; - if (result < 0) - start = m + 1; - else - end = m - 1; - } - return ~start; - } - - public static void InsertSorted(this IList list, T item, IComparer comparer) - { - if (list == null) - throw new ArgumentNullException(nameof(list)); - if (comparer == null) - throw new ArgumentNullException(nameof(comparer)); - - if (list.Count == 0) - { - list.Add(item); - } - else - { - int index = list.BinarySearch(item, 0, list.Count, comparer); - list.Insert(index < 0 ? ~index : index, item); - } - } - - internal static void Deconstruct(this KeyValuePair pair, out TKey key, out TValue value) - { - key = pair.Key; - value = pair.Value; - } - - internal static IEnumerable EmptyIfNull(this IEnumerable? inst) => inst ?? Enumerable.Empty(); - internal static IEnumerable EmptyIfNull(this IEnumerable? inst) => inst ?? Enumerable.Empty(); - internal static IList EmptyIfNull(this IList? inst) => inst ?? EmptyList.Instance; - internal static IList EmptyIfNull(this IList? inst) => inst ?? Array.Empty(); - - public static string ToSuffixString(this System.Reflection.Metadata.EntityHandle handle) - { - if (!DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokens) + if (!showMetadataTokens) return string.Empty; int token = System.Reflection.Metadata.Ecma335.MetadataTokens.GetToken(handle); - if (DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokensInBase10) + if (useBase10) return " @" + token; return " @" + token.ToString("x8"); } - public static string ToSuffixString(this System.Reflection.Metadata.MethodDefinitionHandle handle) - { - return ToSuffixString((System.Reflection.Metadata.EntityHandle)handle); - } - - public static string ToSuffixString(this System.Reflection.Metadata.PropertyDefinitionHandle handle) - { - return ToSuffixString((System.Reflection.Metadata.EntityHandle)handle); - } - - public static string ToSuffixString(this System.Reflection.Metadata.EventDefinitionHandle handle) - { - return ToSuffixString((System.Reflection.Metadata.EntityHandle)handle); - } - - public static string ToSuffixString(this System.Reflection.Metadata.FieldDefinitionHandle handle) - { - return ToSuffixString((System.Reflection.Metadata.EntityHandle)handle); - } - - public static string ToSuffixString(this System.Reflection.Metadata.TypeDefinitionHandle handle) - { - return ToSuffixString((System.Reflection.Metadata.EntityHandle)handle); - } - /// /// Takes at most first characters from string, and appends '...' if string is longer. /// String can be null. @@ -190,6 +76,11 @@ namespace ICSharpCode.ILSpy return result; } + public static ICompilation? GetTypeSystemWithCurrentOptionsOrNull(this PEFile file) + { + return LoadedAssemblyExtensions.GetLoadedAssembly(file).GetTypeSystemOrNull(DecompilerTypeSystem.GetOptions(new DecompilationOptions().DecompilerSettings)); + } + #region DPI independence public static Rect TransformToDevice(this Rect rect, Visual visual) { diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 9f2cd7532..87224fc0e 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -56,7 +56,6 @@ - @@ -94,6 +93,7 @@ + diff --git a/ILSpy/ILSpySettings.cs b/ILSpy/ILSpySettings.cs index 4da939c4b..77eb58bc9 100644 --- a/ILSpy/ILSpySettings.cs +++ b/ILSpy/ILSpySettings.cs @@ -22,12 +22,14 @@ using System.Threading; using System.Xml; using System.Xml.Linq; +using ICSharpCode.ILSpyX; + namespace ICSharpCode.ILSpy { /// /// Manages IL Spy settings. /// - public class ILSpySettings + public class ILSpySettings : ISettingsProvider { readonly XElement root; @@ -124,6 +126,11 @@ namespace ICSharpCode.ILSpy } } + void ISettingsProvider.Update(Action action) + { + Update(action); + } + static string GetConfigFile() { if (App.CommandLineArguments.ConfigFile != null) @@ -134,6 +141,11 @@ namespace ICSharpCode.ILSpy return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "ICSharpCode\\ILSpy.xml"); } + ISettingsProvider ISettingsProvider.Load() + { + return Load(); + } + const string ConfigFileMutex = "01A91708-49D1-410D-B8EB-4DE2662B3971"; /// diff --git a/ILSpy/Languages/CSharpHighlightingTokenWriter.cs b/ILSpy/Languages/CSharpHighlightingTokenWriter.cs index 475cac06a..ab437bfa4 100644 --- a/ILSpy/Languages/CSharpHighlightingTokenWriter.cs +++ b/ILSpy/Languages/CSharpHighlightingTokenWriter.cs @@ -24,6 +24,7 @@ using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp.OutputVisitor; using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.ILSpyX.Extensions; namespace ICSharpCode.ILSpy { diff --git a/ILSpy/Languages/CSharpILMixedLanguage.cs b/ILSpy/Languages/CSharpILMixedLanguage.cs index 2fa6a32f8..2de42e3aa 100644 --- a/ILSpy/Languages/CSharpILMixedLanguage.cs +++ b/ILSpy/Languages/CSharpILMixedLanguage.cs @@ -36,6 +36,8 @@ using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; +using ICSharpCode.ILSpyX; +using ICSharpCode.ILSpyX.Extensions; namespace ICSharpCode.ILSpy { diff --git a/ILSpy/Languages/CSharpLanguage.cs b/ILSpy/Languages/CSharpLanguage.cs index 6d0e2d378..5bb903410 100644 --- a/ILSpy/Languages/CSharpLanguage.cs +++ b/ILSpy/Languages/CSharpLanguage.cs @@ -42,8 +42,10 @@ using ICSharpCode.Decompiler.Output; using ICSharpCode.Decompiler.Solution; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; +using ICSharpCode.ILSpy.Options; using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TreeNodes; +using ICSharpCode.ILSpyX; namespace ICSharpCode.ILSpy { @@ -496,7 +498,7 @@ namespace ICSharpCode.ILSpy readonly DecompilationOptions options; public ILSpyWholeProjectDecompiler(LoadedAssembly assembly, DecompilationOptions options) - : base(options.DecompilerSettings, assembly.GetAssemblyResolver(), assembly.GetAssemblyReferenceClassifier(), assembly.GetDebugInfoOrNull()) + : base(options.DecompilerSettings, assembly.GetAssemblyResolver(), assembly.GetAssemblyReferenceClassifier(options.DecompilerSettings.ApplyWindowsRuntimeProjections), assembly.GetDebugInfoOrNull()) { this.assembly = assembly; this.options = options; diff --git a/ILSpy/Languages/ILAstLanguage.cs b/ILSpy/Languages/ILAstLanguage.cs index 7d4156168..918558451 100644 --- a/ILSpy/Languages/ILAstLanguage.cs +++ b/ILSpy/Languages/ILAstLanguage.cs @@ -29,6 +29,7 @@ using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.ViewModels; +using ICSharpCode.ILSpyX; using static System.Reflection.Metadata.PEReaderExtensions; diff --git a/ILSpy/Languages/ILLanguage.cs b/ILSpy/Languages/ILLanguage.cs index d31068de4..a57e0266e 100644 --- a/ILSpy/Languages/ILLanguage.cs +++ b/ILSpy/Languages/ILLanguage.cs @@ -30,6 +30,7 @@ using ICSharpCode.Decompiler.Solution; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; using ICSharpCode.ILSpy.TextView; +using ICSharpCode.ILSpyX; namespace ICSharpCode.ILSpy { diff --git a/ILSpy/Languages/IResourceFileHandler.cs b/ILSpy/Languages/IResourceFileHandler.cs index 3ea4fb6bc..43270bec4 100644 --- a/ILSpy/Languages/IResourceFileHandler.cs +++ b/ILSpy/Languages/IResourceFileHandler.cs @@ -18,6 +18,8 @@ using System.IO; +using ICSharpCode.ILSpyX; + namespace ICSharpCode.ILSpy { public interface IResourceFileHandler diff --git a/ILSpy/Languages/Language.cs b/ILSpy/Languages/Language.cs index d9fa79827..0b7cc48e8 100644 --- a/ILSpy/Languages/Language.cs +++ b/ILSpy/Languages/Language.cs @@ -29,6 +29,7 @@ using ICSharpCode.Decompiler.Solution; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.Util; +using ICSharpCode.ILSpyX; using SRM = System.Reflection.Metadata; diff --git a/ILSpy/MainWindow.xaml.cs b/ILSpy/MainWindow.xaml.cs index 1fb4a38c7..725464427 100644 --- a/ILSpy/MainWindow.xaml.cs +++ b/ILSpy/MainWindow.xaml.cs @@ -49,6 +49,7 @@ using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.Themes; using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.ViewModels; +using ICSharpCode.ILSpyX; using ICSharpCode.TreeView; using Microsoft.Win32; @@ -850,12 +851,12 @@ namespace ICSharpCode.ILSpy { // 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 = AssemblyListManager.LoadList(spySettings, sessionSettings.ActiveAssemblyList); + this.assemblyList = AssemblyListManager.LoadList(sessionSettings.ActiveAssemblyList); } else { - this.assemblyList = new AssemblyList(AssemblyListManager.DefaultListName); AssemblyListManager.ClearAll(); + this.assemblyList = AssemblyListManager.CreateList(AssemblyListManager.DefaultListName); } HandleCommandLineArguments(App.CommandLineArguments); @@ -983,7 +984,7 @@ namespace ICSharpCode.ILSpy public void ShowAssemblyList(string name) { - AssemblyList list = this.AssemblyListManager.LoadList(ILSpySettings.Load(), name); + AssemblyList list = this.AssemblyListManager.LoadList(name); //Only load a new list when it is a different one if (list.ListName != CurrentAssemblyList.ListName) { @@ -1409,7 +1410,7 @@ namespace ICSharpCode.ILSpy { refreshInProgress = true; var path = GetPathForNode(AssemblyTreeView.SelectedItem as SharpTreeNode); - ShowAssemblyList(AssemblyListManager.LoadList(ILSpySettings.Load(), assemblyList.ListName)); + ShowAssemblyList(AssemblyListManager.LoadList(assemblyList.ListName)); SelectNode(FindNodeByPath(path, true), false, false); } finally diff --git a/ILSpy/MainWindowViewModel.cs b/ILSpy/MainWindowViewModel.cs index 6568e18db..16b2cc0fd 100644 --- a/ILSpy/MainWindowViewModel.cs +++ b/ILSpy/MainWindowViewModel.cs @@ -17,7 +17,7 @@ // DEALINGS IN THE SOFTWARE. using ICSharpCode.ILSpy.Docking; -using ICSharpCode.ILSpy.ViewModels; +using ICSharpCode.ILSpyX; namespace ICSharpCode.ILSpy { diff --git a/ILSpy/Metadata/CoffHeaderTreeNode.cs b/ILSpy/Metadata/CoffHeaderTreeNode.cs index 7764ce903..8e7c3fe57 100644 --- a/ILSpy/Metadata/CoffHeaderTreeNode.cs +++ b/ILSpy/Metadata/CoffHeaderTreeNode.cs @@ -26,6 +26,7 @@ using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.ViewModels; +using ICSharpCode.ILSpyX.Extensions; namespace ICSharpCode.ILSpy.Metadata { diff --git a/ILSpy/Metadata/OptionalHeaderTreeNode.cs b/ILSpy/Metadata/OptionalHeaderTreeNode.cs index 76a46bcbf..cbd67a292 100644 --- a/ILSpy/Metadata/OptionalHeaderTreeNode.cs +++ b/ILSpy/Metadata/OptionalHeaderTreeNode.cs @@ -24,8 +24,8 @@ using System.Windows.Data; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; -using ICSharpCode.ILSpy.TextView; using ICSharpCode.ILSpy.TreeNodes; +using ICSharpCode.ILSpyX.Extensions; namespace ICSharpCode.ILSpy.Metadata { diff --git a/ILSpy/Options/DecompilerSettingsPanel.xaml.cs b/ILSpy/Options/DecompilerSettingsPanel.xaml.cs index d2d9402dc..41bfb1b5f 100644 --- a/ILSpy/Options/DecompilerSettingsPanel.xaml.cs +++ b/ILSpy/Options/DecompilerSettingsPanel.xaml.cs @@ -19,15 +19,11 @@ using System.ComponentModel; using System.Linq; using System.Reflection; -using System.Runtime.CompilerServices; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Xml.Linq; -using ICSharpCode.ILSpy.Properties; -using ICSharpCode.ILSpy.TreeNodes; - namespace ICSharpCode.ILSpy.Options { /// @@ -43,11 +39,6 @@ namespace ICSharpCode.ILSpy.Options static Decompiler.DecompilerSettings currentDecompilerSettings; - internal static void TestSetup(Decompiler.DecompilerSettings settings) - { - currentDecompilerSettings = settings; - } - public static Decompiler.DecompilerSettings CurrentDecompilerSettings { get { return currentDecompilerSettings ?? (currentDecompilerSettings = LoadDecompilerSettings(ILSpySettings.Load())); @@ -71,13 +62,13 @@ namespace ICSharpCode.ILSpy.Options public void Load(ILSpySettings settings) { - this.DataContext = new DecompilerSettings(LoadDecompilerSettings(settings)); + this.DataContext = new DecompilerSettingsViewModel(LoadDecompilerSettings(settings)); } public void Save(XElement root) { XElement section = new XElement("DecompilerSettings"); - var newSettings = ((DecompilerSettings)this.DataContext).ToDecompilerSettings(); + var newSettings = ((DecompilerSettingsViewModel)this.DataContext).ToDecompilerSettings(); var properties = typeof(Decompiler.DecompilerSettings).GetProperties() .Where(p => p.GetCustomAttribute()?.Browsable != false); foreach (var p in properties) @@ -145,81 +136,7 @@ namespace ICSharpCode.ILSpy.Options public void LoadDefaults() { currentDecompilerSettings = new Decompiler.DecompilerSettings(); - this.DataContext = new DecompilerSettings(currentDecompilerSettings); - } - } - - public class DecompilerSettings : INotifyPropertyChanged - { - public CSharpDecompilerSetting[] Settings { get; set; } - - public DecompilerSettings(Decompiler.DecompilerSettings settings) - { - Settings = typeof(Decompiler.DecompilerSettings).GetProperties() - .Where(p => p.GetCustomAttribute()?.Browsable != false) - .Select(p => new CSharpDecompilerSetting(p) { IsEnabled = (bool)p.GetValue(settings) }) - .OrderBy(item => item.Category, NaturalStringComparer.Instance) - .ThenBy(item => item.Description) - .ToArray(); - } - - public event PropertyChangedEventHandler PropertyChanged; - - protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - - public Decompiler.DecompilerSettings ToDecompilerSettings() - { - var settings = new Decompiler.DecompilerSettings(); - foreach (var item in Settings) - { - item.Property.SetValue(settings, item.IsEnabled); - } - return settings; - } - } - - public class CSharpDecompilerSetting : INotifyPropertyChanged - { - bool isEnabled; - - public CSharpDecompilerSetting(PropertyInfo p) - { - this.Property = p; - this.Category = GetResourceString(p.GetCustomAttribute()?.Category ?? Resources.Other); - this.Description = GetResourceString(p.GetCustomAttribute()?.Description ?? p.Name); - } - - public PropertyInfo Property { get; } - - public bool IsEnabled { - get => isEnabled; - set { - if (value != isEnabled) - { - isEnabled = value; - OnPropertyChanged(); - } - } - } - - public string Description { get; set; } - - public string Category { get; set; } - - public event PropertyChangedEventHandler PropertyChanged; - - protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - - static string GetResourceString(string key) - { - var str = !string.IsNullOrEmpty(key) ? Resources.ResourceManager.GetString(key) : null; - return string.IsNullOrEmpty(key) || string.IsNullOrEmpty(str) ? key : str; + this.DataContext = new DecompilerSettingsViewModel(currentDecompilerSettings); } } } diff --git a/ILSpy/Options/DecompilerSettingsViewModel.cs b/ILSpy/Options/DecompilerSettingsViewModel.cs new file mode 100644 index 000000000..b7ce36fbe --- /dev/null +++ b/ILSpy/Options/DecompilerSettingsViewModel.cs @@ -0,0 +1,101 @@ +// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System.ComponentModel; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; + +using ICSharpCode.ILSpy.Properties; +using ICSharpCode.ILSpy.TreeNodes; + +namespace ICSharpCode.ILSpy.Options +{ + public class DecompilerSettingsViewModel : INotifyPropertyChanged + { + public CSharpDecompilerSetting[] Settings { get; set; } + + public DecompilerSettingsViewModel(Decompiler.DecompilerSettings settings) + { + Settings = typeof(Decompiler.DecompilerSettings).GetProperties() + .Where(p => p.GetCustomAttribute()?.Browsable != false) + .Select(p => new CSharpDecompilerSetting(p) { IsEnabled = (bool)p.GetValue(settings) }) + .OrderBy(item => item.Category, NaturalStringComparer.Instance) + .ThenBy(item => item.Description) + .ToArray(); + } + + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + public Decompiler.DecompilerSettings ToDecompilerSettings() + { + var settings = new Decompiler.DecompilerSettings(); + foreach (var item in Settings) + { + item.Property.SetValue(settings, item.IsEnabled); + } + return settings; + } + } + public class CSharpDecompilerSetting : INotifyPropertyChanged + { + bool isEnabled; + + public CSharpDecompilerSetting(PropertyInfo p) + { + this.Property = p; + this.Category = GetResourceString(p.GetCustomAttribute()?.Category ?? Resources.Other); + this.Description = GetResourceString(p.GetCustomAttribute()?.Description ?? p.Name); + } + + public PropertyInfo Property { get; } + + public bool IsEnabled { + get => isEnabled; + set { + if (value != isEnabled) + { + isEnabled = value; + OnPropertyChanged(); + } + } + } + + public string Description { get; set; } + + public string Category { get; set; } + + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + static string GetResourceString(string key) + { + var str = !string.IsNullOrEmpty(key) ? Resources.ResourceManager.GetString(key) : null; + return string.IsNullOrEmpty(key) || string.IsNullOrEmpty(str) ? key : str; + } + } +} diff --git a/ILSpy/Search/SearchPane.cs b/ILSpy/Search/SearchPane.cs index 3fb677d35..7f81b1972 100644 --- a/ILSpy/Search/SearchPane.cs +++ b/ILSpy/Search/SearchPane.cs @@ -37,6 +37,8 @@ using ICSharpCode.ILSpy.Docking; using ICSharpCode.ILSpy.Options; using ICSharpCode.ILSpy.Search; using ICSharpCode.ILSpy.ViewModels; +using ICSharpCode.ILSpyX; +using ICSharpCode.ILSpyX.Extensions; namespace ICSharpCode.ILSpy { diff --git a/ILSpy/SolutionWriter.cs b/ILSpy/SolutionWriter.cs index a02cfe87b..b8a2700ef 100644 --- a/ILSpy/SolutionWriter.cs +++ b/ILSpy/SolutionWriter.cs @@ -29,6 +29,7 @@ using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Solution; using ICSharpCode.Decompiler.Util; using ICSharpCode.ILSpy.TextView; +using ICSharpCode.ILSpyX; namespace ICSharpCode.ILSpy { diff --git a/ILSpy/TextView/DecompilerTextView.cs b/ILSpy/TextView/DecompilerTextView.cs index 2c17dd3df..0ebaf6219 100644 --- a/ILSpy/TextView/DecompilerTextView.cs +++ b/ILSpy/TextView/DecompilerTextView.cs @@ -56,6 +56,7 @@ using ICSharpCode.ILSpy.Options; using ICSharpCode.ILSpy.Themes; using ICSharpCode.ILSpy.TreeNodes; using ICSharpCode.ILSpy.ViewModels; +using ICSharpCode.ILSpyX; using Microsoft.Win32; diff --git a/ILSpy/TreeNodes/AssemblyListTreeNode.cs b/ILSpy/TreeNodes/AssemblyListTreeNode.cs index 2341e15bc..4d29f8fe8 100644 --- a/ILSpy/TreeNodes/AssemblyListTreeNode.cs +++ b/ILSpy/TreeNodes/AssemblyListTreeNode.cs @@ -25,6 +25,7 @@ using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.Util; +using ICSharpCode.ILSpyX; using ICSharpCode.TreeView; namespace ICSharpCode.ILSpy.TreeNodes diff --git a/ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs b/ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs index 01a0961d6..815983efb 100644 --- a/ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs +++ b/ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs @@ -42,7 +42,7 @@ namespace ICSharpCode.ILSpy.TreeNodes public IAssemblyReference AssemblyNameReference => r; public override object Text { - get { return r.Name + ((System.Reflection.Metadata.EntityHandle)r.Handle).ToSuffixString(); } + get { return r.Name + GetSuffixString(r.Handle); } } public override object Icon => Images.Assembly; diff --git a/ILSpy/TreeNodes/AssemblyTreeNode.cs b/ILSpy/TreeNodes/AssemblyTreeNode.cs index 59ea8b066..6efe0b143 100644 --- a/ILSpy/TreeNodes/AssemblyTreeNode.cs +++ b/ILSpy/TreeNodes/AssemblyTreeNode.cs @@ -31,6 +31,8 @@ using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.Properties; using ICSharpCode.ILSpy.ViewModels; +using ICSharpCode.ILSpyX; +using ICSharpCode.ILSpyX.PdbProvider; using ICSharpCode.TreeView; using Microsoft.Win32; @@ -204,7 +206,7 @@ namespace ICSharpCode.ILSpy.TreeNodes var assembly = (MetadataModule)typeSystem.MainModule; this.Children.Add(new Metadata.MetadataTreeNode(module, this)); Decompiler.DebugInfo.IDebugInfoProvider debugInfo = LoadedAssembly.GetDebugInfoOrNull(); - if (debugInfo is Decompiler.PdbProvider.PortableDebugInfoProvider ppdb + if (debugInfo is PortableDebugInfoProvider ppdb && ppdb.GetMetadataReader() is System.Reflection.Metadata.MetadataReader reader) { this.Children.Add(new Metadata.DebugMetadataTreeNode(module, ppdb.IsEmbedded, reader, this)); diff --git a/ILSpy/TreeNodes/BaseTypesTreeNode.cs b/ILSpy/TreeNodes/BaseTypesTreeNode.cs index f90147935..d2d79650c 100644 --- a/ILSpy/TreeNodes/BaseTypesTreeNode.cs +++ b/ILSpy/TreeNodes/BaseTypesTreeNode.cs @@ -24,6 +24,7 @@ using System.Windows.Threading; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.ILSpyX; using ICSharpCode.TreeView; namespace ICSharpCode.ILSpy.TreeNodes diff --git a/ILSpy/TreeNodes/DerivedTypesEntryNode.cs b/ILSpy/TreeNodes/DerivedTypesEntryNode.cs index 48199ecd0..fa4fa0c9a 100644 --- a/ILSpy/TreeNodes/DerivedTypesEntryNode.cs +++ b/ILSpy/TreeNodes/DerivedTypesEntryNode.cs @@ -21,6 +21,7 @@ using System.Linq; using System.Threading; using ICSharpCode.Decompiler; +using ICSharpCode.ILSpyX; namespace ICSharpCode.ILSpy.TreeNodes { @@ -43,7 +44,7 @@ namespace ICSharpCode.ILSpy.TreeNodes public override bool ShowExpander => !type.IsSealed && base.ShowExpander; public override object Text { - get { return Language.TypeToString(type, includeNamespace: true) + type.MetadataToken.ToSuffixString(); } + get { return Language.TypeToString(type, includeNamespace: true) + GetSuffixString(type.MetadataToken); } } public override object Icon => TypeTreeNode.GetIcon(type); diff --git a/ILSpy/TreeNodes/DerivedTypesTreeNode.cs b/ILSpy/TreeNodes/DerivedTypesTreeNode.cs index 3221af947..46dcbf6d7 100644 --- a/ILSpy/TreeNodes/DerivedTypesTreeNode.cs +++ b/ILSpy/TreeNodes/DerivedTypesTreeNode.cs @@ -21,9 +21,9 @@ using System.Linq; using System.Threading; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.ILSpy.Properties; +using ICSharpCode.ILSpyX; using SRM = System.Reflection.Metadata; diff --git a/ILSpy/TreeNodes/EventTreeNode.cs b/ILSpy/TreeNodes/EventTreeNode.cs index b9cce0968..9362fac6e 100644 --- a/ILSpy/TreeNodes/EventTreeNode.cs +++ b/ILSpy/TreeNodes/EventTreeNode.cs @@ -46,7 +46,7 @@ namespace ICSharpCode.ILSpy.TreeNodes public IEvent EventDefinition { get; } - public override object Text => GetText(GetEventDefinition(), this.Language) + EventDefinition.MetadataToken.ToSuffixString(); + public override object Text => GetText(GetEventDefinition(), this.Language) + GetSuffixString(EventDefinition); private IEvent GetEventDefinition() { diff --git a/ILSpy/TreeNodes/FieldTreeNode.cs b/ILSpy/TreeNodes/FieldTreeNode.cs index fab2c6ae4..3a11cbefb 100644 --- a/ILSpy/TreeNodes/FieldTreeNode.cs +++ b/ILSpy/TreeNodes/FieldTreeNode.cs @@ -38,7 +38,7 @@ namespace ICSharpCode.ILSpy.TreeNodes this.FieldDefinition = field ?? throw new ArgumentNullException(nameof(field)); } - public override object Text => GetText(GetFieldDefinition(), Language) + FieldDefinition.MetadataToken.ToSuffixString(); + public override object Text => GetText(GetFieldDefinition(), Language) + GetSuffixString(FieldDefinition); private IField GetFieldDefinition() { diff --git a/ILSpy/TreeNodes/ILSpyTreeNode.cs b/ILSpy/TreeNodes/ILSpyTreeNode.cs index 6796e48a3..d4672fd6b 100644 --- a/ILSpy/TreeNodes/ILSpyTreeNode.cs +++ b/ILSpy/TreeNodes/ILSpyTreeNode.cs @@ -20,10 +20,14 @@ using System; using System.Collections.Specialized; using System.ComponentModel; using System.Linq; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; using System.Windows; using System.Windows.Threading; using ICSharpCode.Decompiler; +using ICSharpCode.Decompiler.TypeSystem; +using ICSharpCode.ILSpy.Options; using ICSharpCode.TreeView; namespace ICSharpCode.ILSpy.TreeNodes @@ -178,6 +182,19 @@ namespace ICSharpCode.ILSpy.TreeNodes } } + protected string GetSuffixString(IMember member) => GetSuffixString(member.MetadataToken); + + protected string GetSuffixString(EntityHandle handle) + { + if (!DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokens) + return string.Empty; + + int token = MetadataTokens.GetToken(handle); + if (DisplaySettingsPanel.CurrentDisplaySettings.ShowMetadataTokensInBase10) + return " @" + token; + return " @" + token.ToString("x8"); + } + public virtual bool IsPublicAPI { get { return true; } } diff --git a/ILSpy/TreeNodes/MethodTreeNode.cs b/ILSpy/TreeNodes/MethodTreeNode.cs index 408e5a36e..28e4cfa30 100644 --- a/ILSpy/TreeNodes/MethodTreeNode.cs +++ b/ILSpy/TreeNodes/MethodTreeNode.cs @@ -38,7 +38,7 @@ namespace ICSharpCode.ILSpy.TreeNodes this.MethodDefinition = method ?? throw new ArgumentNullException(nameof(method)); } - public override object Text => GetText(GetMethodDefinition(), Language) + MethodDefinition.MetadataToken.ToSuffixString(); + public override object Text => GetText(GetMethodDefinition(), Language) + GetSuffixString(MethodDefinition); private IMethod GetMethodDefinition() { diff --git a/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs b/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs index 6216a3704..1161d2e56 100644 --- a/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs +++ b/ILSpy/TreeNodes/ModuleReferenceTreeNode.cs @@ -61,7 +61,7 @@ namespace ICSharpCode.ILSpy.TreeNodes } public override object Text { - get { return moduleName + ((EntityHandle)handle).ToSuffixString(); } + get { return moduleName + GetSuffixString(handle); } } public override object Icon => Images.Library; diff --git a/ILSpy/TreeNodes/PackageFolderTreeNode.cs b/ILSpy/TreeNodes/PackageFolderTreeNode.cs index 58f4f3801..6a631966d 100644 --- a/ILSpy/TreeNodes/PackageFolderTreeNode.cs +++ b/ILSpy/TreeNodes/PackageFolderTreeNode.cs @@ -21,6 +21,7 @@ using System.Collections.Generic; using System.Linq; using ICSharpCode.Decompiler; +using ICSharpCode.ILSpyX; using ICSharpCode.TreeView; namespace ICSharpCode.ILSpy.TreeNodes diff --git a/ILSpy/TreeNodes/PropertyTreeNode.cs b/ILSpy/TreeNodes/PropertyTreeNode.cs index e8e2e149d..694a31c4c 100644 --- a/ILSpy/TreeNodes/PropertyTreeNode.cs +++ b/ILSpy/TreeNodes/PropertyTreeNode.cs @@ -48,7 +48,7 @@ namespace ICSharpCode.ILSpy.TreeNodes public IProperty PropertyDefinition { get; } - public override object Text => GetText(GetPropertyDefinition(), Language) + PropertyDefinition.MetadataToken.ToSuffixString(); + public override object Text => GetText(GetPropertyDefinition(), Language) + GetSuffixString(PropertyDefinition); private IProperty GetPropertyDefinition() { diff --git a/ILSpy/TreeNodes/ThreadingSupport.cs b/ILSpy/TreeNodes/ThreadingSupport.cs index 0e5fbf4e0..4e8861c21 100644 --- a/ILSpy/TreeNodes/ThreadingSupport.cs +++ b/ILSpy/TreeNodes/ThreadingSupport.cs @@ -27,7 +27,6 @@ using System.Windows; using System.Windows.Threading; using ICSharpCode.Decompiler; -using ICSharpCode.ILSpy.Analyzers; using ICSharpCode.ILSpy.Properties; using ICSharpCode.TreeView; diff --git a/ILSpy/TreeNodes/TypeTreeNode.cs b/ILSpy/TreeNodes/TypeTreeNode.cs index 3cb5ca3a4..c0edd649e 100644 --- a/ILSpy/TreeNodes/TypeTreeNode.cs +++ b/ILSpy/TreeNodes/TypeTreeNode.cs @@ -18,7 +18,6 @@ using System; using System.Linq; -using System.Reflection; using System.Windows.Media; using ICSharpCode.Decompiler; @@ -28,6 +27,7 @@ using SRM = System.Reflection.Metadata; namespace ICSharpCode.ILSpy.TreeNodes { using ICSharpCode.Decompiler.TypeSystem; + public sealed class TypeTreeNode : ILSpyTreeNode, IMemberTreeNode { public TypeTreeNode(ITypeDefinition typeDefinition, AssemblyTreeNode parentAssemblyNode) @@ -42,7 +42,7 @@ namespace ICSharpCode.ILSpy.TreeNodes public AssemblyTreeNode ParentAssemblyNode { get; } public override object Text => this.Language.TypeToString(GetTypeDefinition(), includeNamespace: false) - + TypeDefinition.MetadataToken.ToSuffixString(); + + GetSuffixString(TypeDefinition.MetadataToken); private ITypeDefinition GetTypeDefinition() { diff --git a/ILSpy/ViewModels/ManageAssemblyListsViewModel.cs b/ILSpy/ViewModels/ManageAssemblyListsViewModel.cs index e1db19ac1..5327afc0b 100644 --- a/ILSpy/ViewModels/ManageAssemblyListsViewModel.cs +++ b/ILSpy/ViewModels/ManageAssemblyListsViewModel.cs @@ -27,15 +27,12 @@ using System.Windows.Input; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.Commands; using ICSharpCode.ILSpy.Properties; +using ICSharpCode.ILSpyX; namespace ICSharpCode.ILSpy.ViewModels { public class ManageAssemblyListsViewModel : ViewModelBase { - public const string DotNet4List = ".NET 4 (WPF)"; - public const string DotNet35List = ".NET 3.5"; - public const string ASPDotNetMVC3List = "ASP.NET (MVC3)"; - private readonly AssemblyListManager manager; private readonly Window parent; @@ -57,9 +54,9 @@ namespace ICSharpCode.ILSpy.ViewModels IEnumerable ResolvePreconfiguredAssemblyLists() { - yield return new PreconfiguredAssemblyList(DotNet4List); - yield return new PreconfiguredAssemblyList(DotNet35List); - yield return new PreconfiguredAssemblyList(ASPDotNetMVC3List); + yield return new PreconfiguredAssemblyList(AssemblyListManager.DotNet4List); + yield return new PreconfiguredAssemblyList(AssemblyListManager.DotNet35List); + yield return new PreconfiguredAssemblyList(AssemblyListManager.ASPDotNetMVC3List); var basePath = DotNetCorePathFinder.FindDotNetExeDirectory(); if (basePath == null) @@ -140,7 +137,7 @@ namespace ICSharpCode.ILSpy.ViewModels }; if (dlg.ShowDialog() == true) { - manager.CreateList(new AssemblyList(dlg.ListName)); + manager.CreateList(dlg.ListName); } } @@ -241,104 +238,6 @@ namespace ICSharpCode.ILSpy.ViewModels } } - internal static AssemblyList CreateDefaultList(string name, string path = null, string newName = null) - { - var list = new AssemblyList(newName ?? name); - switch (name) - { - case DotNet4List: - AddToListFromGAC("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("System.Data.DataSetExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("System.Xaml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"); - AddToListFromGAC("PresentationCore, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); - AddToListFromGAC("PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); - AddToListFromGAC("WindowsBase, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); - break; - case DotNet35List: - AddToListFromGAC("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); - AddToListFromGAC("PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); - AddToListFromGAC("WindowsBase, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); - break; - case ASPDotNetMVC3List: - AddToListFromGAC("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("System.ComponentModel.DataAnnotations, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); - AddToListFromGAC("System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"); - AddToListFromGAC("System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("System.Data.DataSetExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"); - AddToListFromGAC("System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"); - AddToListFromGAC("System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"); - AddToListFromGAC("System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); - AddToListFromGAC("System.Web.ApplicationServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); - AddToListFromGAC("System.Web.DynamicData, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); - AddToListFromGAC("System.Web.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); - AddToListFromGAC("System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); - AddToListFromGAC("System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); - AddToListFromGAC("System.Web.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"); - AddToListFromGAC("System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); - AddToListFromGAC("System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"); - AddToListFromGAC("System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); - AddToListFromGAC("Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"); - break; - case object _ when path != null: - foreach (var file in Directory.GetFiles(path, "*.dll")) - { - var dllname = Path.GetFileName(file); - if (DoIncludeFile(dllname)) - AddToListFromDirectory(file); - } - break; - } - return list; - - void AddToListFromGAC(string fullName) - { - AssemblyNameReference reference = AssemblyNameReference.Parse(fullName); - string file = UniversalAssemblyResolver.GetAssemblyInGac(reference); - if (file != null) - list.OpenAssembly(file); - } - - void AddToListFromDirectory(string file) - { - if (File.Exists(file)) - list.OpenAssembly(file); - } - - bool DoIncludeFile(string fileName) - { - if (fileName == "Microsoft.DiaSymReader.Native.amd64.dll") - return false; - if (fileName.EndsWith("_cor3.dll", StringComparison.OrdinalIgnoreCase)) - return false; - if (char.IsUpper(fileName[0])) - return true; - if (fileName == "netstandard.dll") - return true; - if (fileName == "mscorlib.dll") - return true; - return false; - } - } - private void ExecuteCreatePreconfiguredAssemblyList(PreconfiguredAssemblyList config) { CreateListDialog dlg = new CreateListDialog(Resources.AddPreconfiguredList); @@ -357,10 +256,10 @@ namespace ICSharpCode.ILSpy.ViewModels }; if (dlg.ShowDialog() == true) { - var list = CreateDefaultList(config.Name, config.Path, dlg.ListName); + var list = manager.CreateDefaultList(config.Name, config.Path, dlg.ListName); if (list.Count > 0) { - manager.CreateList(list); + manager.AddListIfNotExists(list); } } } diff --git a/ILSpy/Views/DebugSteps.xaml.cs b/ILSpy/Views/DebugSteps.xaml.cs index 46eb588ca..dce20bafb 100644 --- a/ILSpy/Views/DebugSteps.xaml.cs +++ b/ILSpy/Views/DebugSteps.xaml.cs @@ -7,6 +7,7 @@ using System.Windows.Input; using ICSharpCode.Decompiler.IL; using ICSharpCode.Decompiler.IL.Transforms; using ICSharpCode.ILSpy.Docking; +using ICSharpCode.ILSpy.Options; using ICSharpCode.ILSpy.ViewModels; namespace ICSharpCode.ILSpy diff --git a/ILSpy/Views/OpenFromGacDialog.xaml.cs b/ILSpy/Views/OpenFromGacDialog.xaml.cs index 22a1a00aa..5189be034 100644 --- a/ILSpy/Views/OpenFromGacDialog.xaml.cs +++ b/ILSpy/Views/OpenFromGacDialog.xaml.cs @@ -29,6 +29,7 @@ using System.Windows.Threading; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.ILSpy.Controls; +using ICSharpCode.ILSpyX.Extensions; namespace ICSharpCode.ILSpy {