From b4df781da1cd61076e0d8e85db44c2af8fe137f4 Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Sun, 17 Nov 2024 08:35:51 +0100 Subject: [PATCH 01/26] Microsoft.NETCore.ILAsm, Microsoft.NETCore.ILDAsm, System.Resources.Extensions to 9.0, SRM/S.C.Immutable to 9.0 outside ICSD --- Directory.Packages.props | 36 ++++++++++++++++++++---------------- ILSpy/ILSpy.csproj | 5 +++++ 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 054032035..e2133d770 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,11 +5,11 @@ - + - + @@ -26,31 +26,35 @@ - - + + - + - + - - - - - - - + + + + + + + - - + + + + + + - + \ No newline at end of file diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index 6bd46530f..e85c97a1e 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -93,6 +93,11 @@ + + + + + From 5ba75bfd51645fee4c76e00a1e1d1c2f2bc4eae6 Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Sun, 17 Nov 2024 15:04:25 +0100 Subject: [PATCH 02/26] Fix for "Unable to locate dotnet CLI. Ensure that it is on the PATH." https://github.com/microsoft/azure-pipelines-tasks/issues/19162 (then see https://github.com/dotnet/format/pull/2000) --- .github/workflows/build-ilspy.yml | 2 +- BuildTools/pre-commit | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build-ilspy.yml b/.github/workflows/build-ilspy.yml index 10e5d8e9d..f3abfb018 100644 --- a/.github/workflows/build-ilspy.yml +++ b/.github/workflows/build-ilspy.yml @@ -35,7 +35,7 @@ jobs: uses: microsoft/setup-msbuild@v2 - name: Install dotnet-format - run: dotnet tool install -g dotnet-format --version "8.0.453106" --add-source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet8/nuget/v3/index.json + run: dotnet tool install -g dotnet-format --version "8.3.546805" --add-source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet8/nuget/v3/index.json - name: Get Version id: version diff --git a/BuildTools/pre-commit b/BuildTools/pre-commit index eee675c87..1067d5581 100644 --- a/BuildTools/pre-commit +++ b/BuildTools/pre-commit @@ -5,7 +5,7 @@ set -eu -DOTNET_FORMAT_VERSION=8.0.453106 +DOTNET_FORMAT_VERSION=8.3.546805 DOTNET_PATH="$LOCALAPPDATA/ICSharpCode/ILSpy/dotnet-format-$DOTNET_FORMAT_VERSION" if [ ! -d "$DOTNET_PATH" ]; then echo "Downloading dotnet-format $DOTNET_FORMAT_VERSION..." From 25a9693457819db5c029f284bfcad9ed2e64abf8 Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Wed, 4 Dec 2024 07:36:45 +0100 Subject: [PATCH 03/26] Roslyn 4.12 --- Directory.Packages.props | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index e2133d770..016f5fcf6 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -16,8 +16,8 @@ - - + + From 762a7713d8e229824d5a83d704d256dd1813387a Mon Sep 17 00:00:00 2001 From: CreateAndInject Date: Mon, 9 Dec 2024 03:43:13 +0800 Subject: [PATCH 04/26] Fix high Dpi --- ILSpy/Controls/CustomDialog.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ILSpy/Controls/CustomDialog.cs b/ILSpy/Controls/CustomDialog.cs index 994bedffc..b3f33dd51 100644 --- a/ILSpy/Controls/CustomDialog.cs +++ b/ILSpy/Controls/CustomDialog.cs @@ -53,7 +53,7 @@ namespace ICSharpCode.ILSpy.Controls { Rectangle screen = Screen.PrimaryScreen.WorkingArea; SizeF size = g.MeasureString(message, label.Font, screen.Width - 20); - Size clientSize = size.ToSize(); + Size clientSize = new Size((int)(size.Width * 96 / g.DpiX), (int)(size.Height * 96 / g.DpiY)); Button[] buttons = new Button[buttonLabels.Length]; int[] positions = new int[buttonLabels.Length]; int pos = 0; @@ -66,7 +66,7 @@ namespace ICSharpCode.ILSpy.Controls newButton.Text = buttonLabel; newButton.Click += new EventHandler(ButtonClick); SizeF buttonSize = g.MeasureString(buttonLabel, newButton.Font); - newButton.Width = Math.Max(newButton.Width, ((int)Math.Ceiling(buttonSize.Width / 8.0) + 1) * 8); + newButton.Width = Math.Max(newButton.Width, ((int)Math.Ceiling(buttonSize.Width * 96 / g.DpiX / 8.0) + 1) * 8); positions[i] = pos; buttons[i] = newButton; pos += newButton.Width + 4; From bff20985fc91575e91e0bef5a7d20e745f3082a1 Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Mon, 9 Dec 2024 08:50:16 +0100 Subject: [PATCH 05/26] Add DOTNET_ROOT --- .github/workflows/build-ilspy.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-ilspy.yml b/.github/workflows/build-ilspy.yml index f3abfb018..51c2b595c 100644 --- a/.github/workflows/build-ilspy.yml +++ b/.github/workflows/build-ilspy.yml @@ -30,7 +30,10 @@ jobs: with: dotnet-version: '8.0.x' dotnet-quality: 'ga' - + env: + DOTNET_INSTALL_DIR: ${{ runner.temp }}/.dotnet + DOTNET_ROOT: ${{ runner.temp }}/.dotnet + - name: Add msbuild to PATH uses: microsoft/setup-msbuild@v2 From 6293cd17628f368b64d89d7087c78aa2b0ae1b2a Mon Sep 17 00:00:00 2001 From: Andrew Au Date: Mon, 9 Dec 2024 06:09:27 -0800 Subject: [PATCH 06/26] Update ReadyToRun to use 9.0 package (#3340) --- Directory.Packages.props | 2 +- ILSpy.ReadyToRun/ReadyToRunLanguage.cs | 5 +++++ NuGet.config | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 016f5fcf6..72b5cb578 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -10,7 +10,7 @@ - + diff --git a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs index 26a3dc0df..de2620bd7 100644 --- a/ILSpy.ReadyToRun/ReadyToRunLanguage.cs +++ b/ILSpy.ReadyToRun/ReadyToRunLanguage.cs @@ -30,6 +30,7 @@ using System.Runtime.CompilerServices; using ICSharpCode.AvalonEdit.Highlighting; using ICSharpCode.Decompiler; +using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Metadata; using ICSharpCode.Decompiler.Solution; using ICSharpCode.Decompiler.TypeSystem; @@ -96,6 +97,10 @@ namespace ICSharpCode.ILSpy.ReadyToRun public void WriteReference(IMember member, string text, bool isDefinition = false) { } + + public void WriteReference(MetadataFile metadata, Handle handle, string text, string protocol = "decompile", bool isDefinition = false) + { + } } #endif diff --git a/NuGet.config b/NuGet.config index 5209a02bf..ccdac39a4 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,7 +4,7 @@ - + @@ -12,7 +12,7 @@ - + From e652490cce4a3f5ec54b9c858807418f02e39ae0 Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Mon, 9 Dec 2024 15:42:06 +0100 Subject: [PATCH 07/26] Implement 3330: Generate diagram from UI without advanced options (#3336) --- .../Commands/CreateDiagramContextMenuEntry.cs | 124 ++++++++++++++++++ ILSpy/Docking/DockWorkspace.cs | 5 + ILSpy/Properties/Resources.Designer.cs | 18 +++ ILSpy/Properties/Resources.resx | 6 + ILSpy/TextView/DecompilerTextView.cs | 4 +- 5 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 ILSpy/Commands/CreateDiagramContextMenuEntry.cs diff --git a/ILSpy/Commands/CreateDiagramContextMenuEntry.cs b/ILSpy/Commands/CreateDiagramContextMenuEntry.cs new file mode 100644 index 000000000..edbbe14a3 --- /dev/null +++ b/ILSpy/Commands/CreateDiagramContextMenuEntry.cs @@ -0,0 +1,124 @@ +// Copyright (c) 2024 Christoph Wille 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.Composition; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + +using ICSharpCode.Decompiler; +using ICSharpCode.ILSpy.Docking; +using ICSharpCode.ILSpy.Properties; +using ICSharpCode.ILSpy.TreeNodes; +using ICSharpCode.ILSpyX.MermaidDiagrammer; + +using Microsoft.Win32; + +namespace ICSharpCode.ILSpy.TextView +{ + [ExportContextMenuEntry(Header = nameof(Resources._CreateDiagram), Category = nameof(Resources.Save), Icon = "Images/Save")] + [Shared] + sealed class CreateDiagramContextMenuEntry(DockWorkspace dockWorkspace) : IContextMenuEntry + { + public void Execute(TextViewContext context) + { + var assembly = (context.SelectedTreeNodes?.FirstOrDefault() as AssemblyTreeNode)?.LoadedAssembly; + if (assembly == null) + return; + + var selectedPath = SelectDestinationFolder(); + if (string.IsNullOrEmpty(selectedPath)) + return; + + dockWorkspace.RunWithCancellation(ct => Task.Factory.StartNew(() => { + AvalonEditTextOutput output = new() { + EnableHyperlinks = true + }; + Stopwatch stopwatch = Stopwatch.StartNew(); + try + { + var command = new GenerateHtmlDiagrammer { + Assembly = assembly.FileName, + OutputFolder = selectedPath + }; + + command.Run(); + } + catch (OperationCanceledException) + { + output.WriteLine(); + output.WriteLine(Resources.GenerationWasCancelled); + throw; + } + stopwatch.Stop(); + output.WriteLine(Resources.GenerationCompleteInSeconds, stopwatch.Elapsed.TotalSeconds.ToString("F1")); + output.WriteLine(); + output.WriteLine("Learn more: " + "https://github.com/icsharpcode/ILSpy/wiki/Diagramming#tips-for-using-the-html-diagrammer"); + output.WriteLine(); + + var diagramHtml = Path.Combine(selectedPath, "index.html"); + output.AddButton(null, Resources.OpenExplorer, delegate { Process.Start("explorer", "/select,\"" + diagramHtml + "\""); }); + output.WriteLine(); + return output; + }, ct), Properties.Resources.CreatingDiagram).Then(dockWorkspace.ShowText).HandleExceptions(); + + return; + } + + public bool IsEnabled(TextViewContext context) => true; + + public bool IsVisible(TextViewContext context) + { + return context.SelectedTreeNodes?.Length == 1 + && context.SelectedTreeNodes?.FirstOrDefault() is AssemblyTreeNode tn + && tn.LoadedAssembly.IsLoadedAsValidAssembly; + } + + static string SelectDestinationFolder() + { + OpenFolderDialog dialog = new(); + dialog.Multiselect = false; + dialog.Title = "Select target folder"; + + if (dialog.ShowDialog() != true) + { + return null; + } + + string selectedPath = Path.GetDirectoryName(dialog.FolderName); + bool directoryNotEmpty; + try + { + directoryNotEmpty = Directory.EnumerateFileSystemEntries(selectedPath).Any(); + } + catch (Exception e) when (e is IOException || e is UnauthorizedAccessException || e is System.Security.SecurityException) + { + MessageBox.Show( + "The directory cannot be accessed. Please ensure it exists and you have sufficient rights to access it.", + "Target directory not accessible", + MessageBoxButton.OK, MessageBoxImage.Error); + return null; + } + + return dialog.FolderName; + } + } +} diff --git a/ILSpy/Docking/DockWorkspace.cs b/ILSpy/Docking/DockWorkspace.cs index d92b92847..cc69c7bda 100644 --- a/ILSpy/Docking/DockWorkspace.cs +++ b/ILSpy/Docking/DockWorkspace.cs @@ -226,6 +226,11 @@ namespace ICSharpCode.ILSpy.Docking return ActiveTabPage.ShowTextViewAsync(textView => textView.RunWithCancellation(taskCreation)); } + public Task RunWithCancellation(Func> taskCreation, string progressTitle) + { + return ActiveTabPage.ShowTextViewAsync(textView => textView.RunWithCancellation(taskCreation, progressTitle)); + } + internal void ShowNodes(AvalonEditTextOutput output, TreeNodes.ILSpyTreeNode[] nodes, IHighlightingDefinition highlighting) { ActiveTabPage.ShowTextView(textView => textView.ShowNodes(output, nodes, highlighting)); diff --git a/ILSpy/Properties/Resources.Designer.cs b/ILSpy/Properties/Resources.Designer.cs index ca8b55151..01628056b 100644 --- a/ILSpy/Properties/Resources.Designer.cs +++ b/ILSpy/Properties/Resources.Designer.cs @@ -114,6 +114,15 @@ namespace ICSharpCode.ILSpy.Properties { } } + /// + /// Looks up a localized string similar to Create _Diagram.... + /// + public static string _CreateDiagram { + get { + return ResourceManager.GetString("_CreateDiagram", resourceCulture); + } + } + /// /// Looks up a localized string similar to _File. /// @@ -567,6 +576,15 @@ namespace ICSharpCode.ILSpy.Properties { } } + /// + /// Looks up a localized string similar to Creating diagram.... + /// + public static string CreatingDiagram { + get { + return ResourceManager.GetString("CreatingDiagram", resourceCulture); + } + } + /// /// Looks up a localized string similar to Culture. /// diff --git a/ILSpy/Properties/Resources.resx b/ILSpy/Properties/Resources.resx index b853b0641..bcb79fae7 100644 --- a/ILSpy/Properties/Resources.resx +++ b/ILSpy/Properties/Resources.resx @@ -210,6 +210,9 @@ Are you sure you want to continue? Create + + Creating diagram... + Culture @@ -1036,6 +1039,9 @@ Do you want to continue? _Collapse all tree nodes + + Create _Diagram... + _File diff --git a/ILSpy/TextView/DecompilerTextView.cs b/ILSpy/TextView/DecompilerTextView.cs index 2e65074d1..4e748fd2a 100644 --- a/ILSpy/TextView/DecompilerTextView.cs +++ b/ILSpy/TextView/DecompilerTextView.cs @@ -595,14 +595,14 @@ namespace ICSharpCode.ILSpy.TextView /// the task. /// If another task is started before the previous task finishes running, the previous task is cancelled. /// - public Task RunWithCancellation(Func> taskCreation) + public Task RunWithCancellation(Func> taskCreation, string? progressTitle = null) { if (waitAdorner.Visibility != Visibility.Visible) { waitAdorner.Visibility = Visibility.Visible; // Work around a WPF bug by setting IsIndeterminate only while the progress bar is visible. // https://github.com/icsharpcode/ILSpy/issues/593 - progressTitle.Text = Properties.Resources.Decompiling; + this.progressTitle.Text = progressTitle == null ? Properties.Resources.Decompiling : progressTitle; progressBar.IsIndeterminate = true; progressText.Text = null; progressText.Visibility = Visibility.Collapsed; From 62cdf38e9b96f87add9adb9281fdee439e74b6ee Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 13 Dec 2024 02:18:44 +0100 Subject: [PATCH 08/26] Fix #3349: Get rid of version string manipulation in UniversalAssemblyResolver.ParseTargetFramework. --- .../ProjectDecompiler/TargetFrameworkTests.cs | 10 ++++++++++ .../Metadata/UniversalAssemblyResolver.cs | 15 ++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/ProjectDecompiler/TargetFrameworkTests.cs b/ICSharpCode.Decompiler.Tests/ProjectDecompiler/TargetFrameworkTests.cs index df78e9bc1..1a9557c77 100644 --- a/ICSharpCode.Decompiler.Tests/ProjectDecompiler/TargetFrameworkTests.cs +++ b/ICSharpCode.Decompiler.Tests/ProjectDecompiler/TargetFrameworkTests.cs @@ -19,6 +19,7 @@ using System; using ICSharpCode.Decompiler.CSharp.ProjectDecompiler; +using ICSharpCode.Decompiler.Metadata; using NUnit.Framework; @@ -119,5 +120,14 @@ namespace ICSharpCode.Decompiler.Tests // Assert Assert.That(targetFramework.Moniker, Is.EqualTo(expectedMoniker)); } + + [TestCase(".NETCoreApp, Version=v5.0", TargetFrameworkIdentifier.NET, "5.0.0")] + [TestCase(".NETCoreApp, Version=v10.0", TargetFrameworkIdentifier.NET, "10.0.0")] + public void VerifyUniversalAssemblyResolverParseTargetFramework(string targetFramework, TargetFrameworkIdentifier identifier, string version) + { + var (id, v) = UniversalAssemblyResolver.ParseTargetFramework(targetFramework); + Assert.That(id, Is.EqualTo(identifier)); + Assert.That(v.ToString(3), Is.EqualTo(version)); + } } } diff --git a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs index 90ba8724a..ffd6d700d 100644 --- a/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs +++ b/ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs @@ -189,15 +189,16 @@ namespace ICSharpCode.Decompiler.Metadata switch (pair[0].Trim().ToUpperInvariant()) { case "VERSION": - var versionString = pair[1].TrimStart('v', ' ', '\t'); - if (identifier == TargetFrameworkIdentifier.NETCoreApp || - identifier == TargetFrameworkIdentifier.NETStandard) - { - if (versionString.Length == 3) - versionString += ".0"; - } + var versionString = pair[1].TrimStart('v', 'V', ' ', '\t'); + if (!Version.TryParse(versionString, out version)) + { version = null; + } + else + { + version = new Version(version.Major, version.Minor, version.Build < 0 ? 0 : version.Build); + } // .NET 5 or greater still use ".NETCOREAPP" as TargetFrameworkAttribute value... if (version?.Major >= 5 && identifier == TargetFrameworkIdentifier.NETCoreApp) identifier = TargetFrameworkIdentifier.NET; From 663dea45bf74ec8f3df3bf2cf410e2be3c0266a9 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 14 Dec 2024 19:40:59 +0100 Subject: [PATCH 09/26] Performance: Initialize ToolPanes in DockWorkspace.InitializeLayout() instead of the property getter to avoid WPF seeing them in InitializeComponent() and rendering all panes docked at the right before the layout is properly initialized. This also appears to make startup around 500ms/25% faster, keeping total time from App::.cctor to "decompilation finished" (for a "standard" assembly node with just attributes in the output) at under two seconds. --- ILSpy/Docking/DockWorkspace.cs | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/ILSpy/Docking/DockWorkspace.cs b/ILSpy/Docking/DockWorkspace.cs index cc69c7bda..3ad6aaf83 100644 --- a/ILSpy/Docking/DockWorkspace.cs +++ b/ILSpy/Docking/DockWorkspace.cs @@ -123,11 +123,9 @@ namespace ICSharpCode.ILSpy.Docking public ReadOnlyObservableCollection TabPages { get; } - public ReadOnlyCollection ToolPanes => exportProvider - .GetExportedValues("ToolPane") - .OrderBy(item => item.Title) - .ToArray() - .AsReadOnly(); + private ToolPaneModel[] toolPanes = []; + + public ReadOnlyCollection ToolPanes => toolPanes.AsReadOnly(); public bool ShowToolPane(string contentId) { @@ -183,6 +181,12 @@ namespace ICSharpCode.ILSpy.Docking AddTabPage(); } + toolPanes = exportProvider + .GetExportedValues("ToolPane") + .OrderBy(item => item.Title) + .ToArray(); + OnPropertyChanged(nameof(ToolPanes)); + DockingManager.LayoutUpdateStrategy = this; XmlLayoutSerializer serializer = new XmlLayoutSerializer(DockingManager); serializer.LayoutSerializationCallback += LayoutSerializationCallback; From 19d4f0136563c6a53205b9b47b6435a3447ff1a4 Mon Sep 17 00:00:00 2001 From: CreateAndInject Date: Sun, 15 Dec 2024 08:28:22 +0800 Subject: [PATCH 10/26] Use TextRenderer.MeasureText instead of Graphics.MeasureString to get exact result --- ILSpy/Controls/CustomDialog.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/ILSpy/Controls/CustomDialog.cs b/ILSpy/Controls/CustomDialog.cs index b3f33dd51..d51f69c0f 100644 --- a/ILSpy/Controls/CustomDialog.cs +++ b/ILSpy/Controls/CustomDialog.cs @@ -51,9 +51,8 @@ namespace ICSharpCode.ILSpy.Controls using (Graphics g = this.CreateGraphics()) { - Rectangle screen = Screen.PrimaryScreen.WorkingArea; - SizeF size = g.MeasureString(message, label.Font, screen.Width - 20); - Size clientSize = new Size((int)(size.Width * 96 / g.DpiX), (int)(size.Height * 96 / g.DpiY)); + SizeF size = TextRenderer.MeasureText(message, label.Font); + Size clientSize = new Size((int)(size.Width * 96 / g.DpiX) + DockPadding.Left + DockPadding.Right, (int)(size.Height * 96 / g.DpiY) + DockPadding.Top + DockPadding.Bottom); Button[] buttons = new Button[buttonLabels.Length]; int[] positions = new int[buttonLabels.Length]; int pos = 0; @@ -65,7 +64,7 @@ namespace ICSharpCode.ILSpy.Controls string buttonLabel = buttonLabels[i]; newButton.Text = buttonLabel; newButton.Click += new EventHandler(ButtonClick); - SizeF buttonSize = g.MeasureString(buttonLabel, newButton.Font); + SizeF buttonSize = TextRenderer.MeasureText(buttonLabel, newButton.Font); newButton.Width = Math.Max(newButton.Width, ((int)Math.Ceiling(buttonSize.Width * 96 / g.DpiX / 8.0) + 1) * 8); positions[i] = pos; buttons[i] = newButton; From b32f026d348e7b2378c5a65c2872fd95435db28c Mon Sep 17 00:00:00 2001 From: CreateAndInject Date: Tue, 17 Dec 2024 20:06:53 +0800 Subject: [PATCH 11/26] Fix Mnemonic --- ILSpy/Controls/CustomDialog.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ILSpy/Controls/CustomDialog.cs b/ILSpy/Controls/CustomDialog.cs index d51f69c0f..63ca6bef9 100644 --- a/ILSpy/Controls/CustomDialog.cs +++ b/ILSpy/Controls/CustomDialog.cs @@ -51,8 +51,8 @@ namespace ICSharpCode.ILSpy.Controls using (Graphics g = this.CreateGraphics()) { - SizeF size = TextRenderer.MeasureText(message, label.Font); - Size clientSize = new Size((int)(size.Width * 96 / g.DpiX) + DockPadding.Left + DockPadding.Right, (int)(size.Height * 96 / g.DpiY) + DockPadding.Top + DockPadding.Bottom); + SizeF size = TextRenderer.MeasureText(message, label.Font, default, TextFormatFlags.NoPrefix); + Size clientSize = new Size((int)Math.Ceiling(size.Width * 96 / g.DpiX) + DockPadding.Left + DockPadding.Right, (int)Math.Ceiling(size.Height * 96 / g.DpiY) + DockPadding.Top + DockPadding.Bottom); Button[] buttons = new Button[buttonLabels.Length]; int[] positions = new int[buttonLabels.Length]; int pos = 0; @@ -86,7 +86,7 @@ namespace ICSharpCode.ILSpy.Controls { clientSize.Width = pos; } - clientSize.Height += panel.Height + 6; + clientSize.Height += panel.Height; this.ClientSize = clientSize; int start = (clientSize.Width - pos) / 2; for (int i = 0; i < buttons.Length; i++) From 44da7ce0235741b19e1cba02198baa7793f0b008 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Wed, 18 Dec 2024 21:46:11 +0100 Subject: [PATCH 12/26] Fix broken Window menu and ResetLayout --- ILSpy/Docking/DockWorkspace.cs | 19 ++++++++++--------- ILSpy/MainWindow.xaml | 2 -- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/ILSpy/Docking/DockWorkspace.cs b/ILSpy/Docking/DockWorkspace.cs index 3ad6aaf83..2fe0d0fc2 100644 --- a/ILSpy/Docking/DockWorkspace.cs +++ b/ILSpy/Docking/DockWorkspace.cs @@ -25,6 +25,7 @@ using System.Linq; using System.Reflection; using System.Threading; using System.Threading.Tasks; +using System.Windows.Data; using System.Windows.Threading; using AvalonDock; @@ -50,6 +51,7 @@ namespace ICSharpCode.ILSpy.Docking private readonly IExportProvider exportProvider; private readonly ObservableCollection tabPages = []; + private ReadOnlyCollection toolPanes; readonly SessionSettings sessionSettings; @@ -123,9 +125,11 @@ namespace ICSharpCode.ILSpy.Docking public ReadOnlyObservableCollection TabPages { get; } - private ToolPaneModel[] toolPanes = []; - - public ReadOnlyCollection ToolPanes => toolPanes.AsReadOnly(); + public ReadOnlyCollection ToolPanes => toolPanes ??= exportProvider + .GetExportedValues("ToolPane") + .OrderBy(item => item.Title) + .ToArray() + .AsReadOnly(); public bool ShowToolPane(string contentId) { @@ -181,12 +185,6 @@ namespace ICSharpCode.ILSpy.Docking AddTabPage(); } - toolPanes = exportProvider - .GetExportedValues("ToolPane") - .OrderBy(item => item.Title) - .ToArray(); - OnPropertyChanged(nameof(ToolPanes)); - DockingManager.LayoutUpdateStrategy = this; XmlLayoutSerializer serializer = new XmlLayoutSerializer(DockingManager); serializer.LayoutSerializationCallback += LayoutSerializationCallback; @@ -198,6 +196,9 @@ namespace ICSharpCode.ILSpy.Docking { serializer.LayoutSerializationCallback -= LayoutSerializationCallback; } + + DockingManager.SetBinding(DockingManager.AnchorablesSourceProperty, new Binding(nameof(ToolPanes))); + DockingManager.SetBinding(DockingManager.DocumentsSourceProperty, new Binding(nameof(TabPages))); } void LayoutSerializationCallback(object sender, LayoutSerializationCallbackEventArgs e) diff --git a/ILSpy/MainWindow.xaml b/ILSpy/MainWindow.xaml index 99c5ee08f..a60f6c990 100644 --- a/ILSpy/MainWindow.xaml +++ b/ILSpy/MainWindow.xaml @@ -67,8 +67,6 @@ From 2f53f69799f970881c39993e5a65113db9d35ae2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=84=B1=EC=9B=90?= Date: Wed, 1 Jan 2025 07:43:51 +0000 Subject: [PATCH 13/26] Fix #3355 : Insert missing DecompilerSettings --- ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index 520619787..7147785de 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -521,7 +521,7 @@ namespace ICSharpCode.Decompiler.CSharp file.DetectTargetFrameworkId(), file.DetectRuntimePack(), settings.LoadInMemory ? PEStreamOptions.PrefetchMetadata : PEStreamOptions.Default, settings.ApplyWindowsRuntimeProjections ? MetadataReaderOptions.ApplyWindowsRuntimeProjections : MetadataReaderOptions.None); - return new DecompilerTypeSystem(file, resolver); + return new DecompilerTypeSystem(file, resolver, settings); } static TypeSystemAstBuilder CreateAstBuilder(DecompilerSettings settings) From 8373ac752e26df0046751ed7f789a788416f83b6 Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Wed, 1 Jan 2025 09:57:11 +0100 Subject: [PATCH 14/26] v9.0 RC Designation (#3357) * v9.0 RC designation * Ambiguous reference errors fixed --- Directory.Packages.props | 13 ++++++------- .../CorrectnessTestRunner.cs | 6 +++--- ICSharpCode.Decompiler.Tests/UglyTestRunner.cs | 2 +- .../Properties/DecompilerVersionInfo.template.cs | 2 +- doc/copyright.txt | 2 +- doc/license.txt | 2 +- 6 files changed, 13 insertions(+), 14 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 72b5cb578..5c5711fea 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -5,14 +5,14 @@ - + - + - + @@ -25,7 +25,7 @@ - + @@ -34,7 +34,7 @@ - + @@ -48,8 +48,7 @@ - - + diff --git a/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs b/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs index 2b877d110..a0901f255 100644 --- a/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/CorrectnessTestRunner.cs @@ -409,7 +409,7 @@ namespace ICSharpCode.Decompiler.Tests options |= CompilerOptions.UseTestRunner; string testFileName = testName + ".cs"; string testOutputFileName = TestsAssemblyOutput.GetFilePath(TestCasePath, testName, Tester.GetSuffix(options) + ".exe"); - CompilerResults outputFile = null, decompiledOutputFile = null; + Helpers.CompilerResults outputFile = null, decompiledOutputFile = null; try { @@ -453,7 +453,7 @@ namespace ICSharpCode.Decompiler.Tests options |= CompilerOptions.UseTestRunner; string testFileName = testName + ".vb"; string testOutputFileName = TestsAssemblyOutput.GetFilePath(TestCasePath, testName, Tester.GetSuffix(options) + ".exe"); - CompilerResults outputFile = null, decompiledOutputFile = null; + Helpers.CompilerResults outputFile = null, decompiledOutputFile = null; try { @@ -477,7 +477,7 @@ namespace ICSharpCode.Decompiler.Tests async Task RunIL(string testFileName, CompilerOptions options = CompilerOptions.UseDebug, AssemblerOptions asmOptions = AssemblerOptions.None) { string outputFile = null; - CompilerResults decompiledOutputFile = null; + Helpers.CompilerResults decompiledOutputFile = null; bool optionsForce32Bit = options.HasFlag(CompilerOptions.Force32Bit); bool asmOptionsForce32Bit = asmOptions.HasFlag(AssemblerOptions.Force32Bit); diff --git a/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs b/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs index 620424ca8..bc60f38c9 100644 --- a/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs +++ b/ICSharpCode.Decompiler.Tests/UglyTestRunner.cs @@ -146,7 +146,7 @@ namespace ICSharpCode.Decompiler.Tests if (!File.Exists(ilFile)) { // re-create .il file if necessary - CompilerResults output = null; + Helpers.CompilerResults output = null; try { output = await Tester.CompileCSharp(csFile, cscOptions).ConfigureAwait(false); diff --git a/ICSharpCode.Decompiler/Properties/DecompilerVersionInfo.template.cs b/ICSharpCode.Decompiler/Properties/DecompilerVersionInfo.template.cs index 947188ef1..8810b7e16 100644 --- a/ICSharpCode.Decompiler/Properties/DecompilerVersionInfo.template.cs +++ b/ICSharpCode.Decompiler/Properties/DecompilerVersionInfo.template.cs @@ -4,7 +4,7 @@ public const string Minor = "0"; public const string Build = "0"; public const string Revision = "$INSERTREVISION$"; - public const string VersionName = "preview3"; + public const string VersionName = "RC"; public const string FullVersion = Major + "." + Minor + "." + Build + ".$INSERTREVISION$$INSERTBRANCHPOSTFIX$$INSERTVERSIONNAMEPOSTFIX$"; public const string FullVersionWithShortCommitHash = FullVersion + "+$INSERTSHORTCOMMITHASH$"; diff --git a/doc/copyright.txt b/doc/copyright.txt index de4935037..979e262b9 100644 --- a/doc/copyright.txt +++ b/doc/copyright.txt @@ -1,4 +1,4 @@ -Copyright 2011-2023 for the ILSpy team +Copyright 2011-2025 for the ILSpy team by AlphaSierraPapa, Christoph Wille diff --git a/doc/license.txt b/doc/license.txt index 52c20debd..22e1b4257 100644 --- a/doc/license.txt +++ b/doc/license.txt @@ -1,6 +1,6 @@ MIT license -Copyright (c) 2011-2023 AlphaSierraPapa for the ILSpy team +Copyright (c) 2011-2025 AlphaSierraPapa for the ILSpy 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 From 4bad0c7a4b11ad586f133c47ea56501cd2035a50 Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Fri, 3 Jan 2025 10:12:45 +0100 Subject: [PATCH 15/26] Move license.txt to root folder LICENSE file --- ILSpy.AddIn.VS2022/ILSpy.AddIn.VS2022.csproj | 2 +- ILSpy.AddIn/ILSpy.AddIn.csproj | 2 +- ILSpy/ILSpy.csproj | 2 +- doc/license.txt => LICENSE | 0 doc/ILSpyAboutPage.txt | 2 +- doc/ILSpyAboutPage_zh_Hans.txt | 2 +- 6 files changed, 5 insertions(+), 5 deletions(-) rename doc/license.txt => LICENSE (100%) diff --git a/ILSpy.AddIn.VS2022/ILSpy.AddIn.VS2022.csproj b/ILSpy.AddIn.VS2022/ILSpy.AddIn.VS2022.csproj index 83404ae2f..c5d27caea 100644 --- a/ILSpy.AddIn.VS2022/ILSpy.AddIn.VS2022.csproj +++ b/ILSpy.AddIn.VS2022/ILSpy.AddIn.VS2022.csproj @@ -149,7 +149,7 @@ - + Always true diff --git a/ILSpy.AddIn/ILSpy.AddIn.csproj b/ILSpy.AddIn/ILSpy.AddIn.csproj index 9b41766fd..bdcf4d021 100644 --- a/ILSpy.AddIn/ILSpy.AddIn.csproj +++ b/ILSpy.AddIn/ILSpy.AddIn.csproj @@ -148,7 +148,7 @@ - + Always true diff --git a/ILSpy/ILSpy.csproj b/ILSpy/ILSpy.csproj index e85c97a1e..ba2e33f5b 100644 --- a/ILSpy/ILSpy.csproj +++ b/ILSpy/ILSpy.csproj @@ -58,7 +58,7 @@ - + license.txt diff --git a/doc/license.txt b/LICENSE similarity index 100% rename from doc/license.txt rename to LICENSE diff --git a/doc/ILSpyAboutPage.txt b/doc/ILSpyAboutPage.txt index 0b5610aea..cf181a904 100644 --- a/doc/ILSpyAboutPage.txt +++ b/doc/ILSpyAboutPage.txt @@ -3,7 +3,7 @@ ILSpy is the open-source .NET assembly browser and decompiler. Website: https://ilspy.net/ Found a bug? https://github.com/icsharpcode/ILSpy/issues/new/choose -Copyright 2011-2023 AlphaSierraPapa for the ILSpy team +Copyright 2011-2025 AlphaSierraPapa for the ILSpy team Current and past contributors: https://github.com/icsharpcode/ILSpy/graphs/contributors ILSpy is distributed under the MIT License. diff --git a/doc/ILSpyAboutPage_zh_Hans.txt b/doc/ILSpyAboutPage_zh_Hans.txt index ebaf5676d..3723702f8 100644 --- a/doc/ILSpyAboutPage_zh_Hans.txt +++ b/doc/ILSpyAboutPage_zh_Hans.txt @@ -4,7 +4,7 @@ ILSpy 是开源的 .NET 程序集浏览器和反编译器。 反馈BUG: https://github.com/icsharpcode/ILSpy/issues/new/choose 中文翻译反馈:https://github.com/maikebing/ILSpy/issues -Copyright 2011-2023 AlphaSierraPapa for the ILSpy team +Copyright 2011-2025 AlphaSierraPapa for the ILSpy team 当前和过去的贡献者: https://github.com/icsharpcode/ILSpy/graphs/contributors ILSpy 基于 MIT 许可证发行。 From a0e22b1757ca2759b9b3724b499ff8d1d39bc71b Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Fri, 3 Jan 2025 10:53:31 +0100 Subject: [PATCH 16/26] IncludeInVSIX passes original name unchanged (ignores Linked) --- ILSpy.AddIn.VS2022/source.extension.vsixmanifest.template | 2 +- ILSpy.AddIn/source.extension.vsixmanifest.template | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ILSpy.AddIn.VS2022/source.extension.vsixmanifest.template b/ILSpy.AddIn.VS2022/source.extension.vsixmanifest.template index be1488335..55e6649e6 100644 --- a/ILSpy.AddIn.VS2022/source.extension.vsixmanifest.template +++ b/ILSpy.AddIn.VS2022/source.extension.vsixmanifest.template @@ -5,7 +5,7 @@ ILSpy 2022 Integrates the ILSpy decompiler into Visual Studio. https://ilspy.net - license.txt + LICENSE ILSpy-Large.ico ILSpy;IL;decompile;decompiler;decompilation;C#;CSharp;.NET;Productivity;Open Source;Free diff --git a/ILSpy.AddIn/source.extension.vsixmanifest.template b/ILSpy.AddIn/source.extension.vsixmanifest.template index b87e1d1dc..c3d0d0d60 100644 --- a/ILSpy.AddIn/source.extension.vsixmanifest.template +++ b/ILSpy.AddIn/source.extension.vsixmanifest.template @@ -5,7 +5,7 @@ ILSpy Integrates the ILSpy decompiler into Visual Studio. https://ilspy.net - license.txt + LICENSE ILSpy-Large.ico From 1048cd9557fd27986ec68785bce2da84c2d57d5c Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Fri, 3 Jan 2025 14:30:08 +0100 Subject: [PATCH 17/26] Enable repeatable package restores (#3359) Locking restricted to projects that create NuGet packages ICSharpCode.Decompiler ICSharpCode.ILSpyX ILSpyCmd ICSharpCode.BamlDecompiler --- .../ICSharpCode.BamlDecompiler.csproj | 6 + ICSharpCode.BamlDecompiler/packages.lock.json | 44 ++ .../ICSharpCode.Decompiler.csproj | 6 + ICSharpCode.Decompiler/packages.lock.json | 91 ++++ .../ICSharpCode.ILSpyCmd.csproj | 6 + ICSharpCode.ILSpyCmd/packages.lock.json | 453 ++++++++++++++++++ ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj | 6 + ICSharpCode.ILSpyX/packages.lock.json | 79 +++ ILSpy.Installer/ILSpy.Installer.csproj | 2 +- 9 files changed, 692 insertions(+), 1 deletion(-) create mode 100644 ICSharpCode.BamlDecompiler/packages.lock.json create mode 100644 ICSharpCode.Decompiler/packages.lock.json create mode 100644 ICSharpCode.ILSpyCmd/packages.lock.json create mode 100644 ICSharpCode.ILSpyX/packages.lock.json diff --git a/ICSharpCode.BamlDecompiler/ICSharpCode.BamlDecompiler.csproj b/ICSharpCode.BamlDecompiler/ICSharpCode.BamlDecompiler.csproj index cd022af4b..d054a6512 100644 --- a/ICSharpCode.BamlDecompiler/ICSharpCode.BamlDecompiler.csproj +++ b/ICSharpCode.BamlDecompiler/ICSharpCode.BamlDecompiler.csproj @@ -41,6 +41,12 @@ + + + true + true + + diff --git a/ICSharpCode.BamlDecompiler/packages.lock.json b/ICSharpCode.BamlDecompiler/packages.lock.json new file mode 100644 index 000000000..2fe6f64a0 --- /dev/null +++ b/ICSharpCode.BamlDecompiler/packages.lock.json @@ -0,0 +1,44 @@ +{ + "version": 2, + "dependencies": { + "net8.0": { + "TomsToolbox.Composition.Analyzer": { + "type": "Direct", + "requested": "[2.21.0, )", + "resolved": "2.21.0", + "contentHash": "vJx9hxAzjni34slGz78ewqYP9Ylk8dJszfEUK1TF5cflVKMBO3ORSFd0FtICTwJtE8munvZrMrcLWwXt5bIcEA==" + }, + "icsharpcode.decompiler": { + "type": "Project", + "dependencies": { + "System.Collections.Immutable": "[6.0.0, )", + "System.Reflection.Metadata": "[6.0.0, )" + } + }, + "System.Collections.Immutable": { + "type": "CentralTransitive", + "requested": "[9.0.0, )", + "resolved": "6.0.0", + "contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Reflection.Metadata": { + "type": "CentralTransitive", + "requested": "[9.0.0, )", + "resolved": "6.0.0", + "contentHash": "sffDOcex1C3HO5kDolOYcWXTwRpZY/LvJujM6SMjn63fWMJWchYAAmkoAJXlbpZ5yf4d+KMgxd+LeETa4gD9sQ==", + "dependencies": { + "System.Collections.Immutable": "6.0.0" + } + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "CentralTransitive", + "requested": "[6.1.0, )", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + } + } + } +} \ No newline at end of file diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index 583adedeb..5314bd4f7 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -47,6 +47,12 @@ + + + + true + true + True diff --git a/ICSharpCode.Decompiler/packages.lock.json b/ICSharpCode.Decompiler/packages.lock.json new file mode 100644 index 000000000..c6e34ae99 --- /dev/null +++ b/ICSharpCode.Decompiler/packages.lock.json @@ -0,0 +1,91 @@ +{ + "version": 1, + "dependencies": { + ".NETStandard,Version=v2.0": { + "Microsoft.SourceLink.GitHub": { + "type": "Direct", + "requested": "[8.0.0, )", + "resolved": "8.0.0", + "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==", + "dependencies": { + "Microsoft.Build.Tasks.Git": "8.0.0", + "Microsoft.SourceLink.Common": "8.0.0" + } + }, + "NETStandard.Library": { + "type": "Direct", + "requested": "[2.0.3, )", + "resolved": "2.0.3", + "contentHash": "st47PosZSHrjECdjeIzZQbzivYBJFv6P2nv4cj2ypdI204DO+vZ7l5raGMiX4eXMJ53RfOIg+/s4DHVZ54Nu2A==", + "dependencies": { + "Microsoft.NETCore.Platforms": "1.1.0" + } + }, + "System.Collections.Immutable": { + "type": "Direct", + "requested": "[6.0.0, )", + "resolved": "6.0.0", + "contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==", + "dependencies": { + "System.Memory": "4.5.4", + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } + }, + "System.Reflection.Metadata": { + "type": "Direct", + "requested": "[6.0.0, )", + "resolved": "6.0.0", + "contentHash": "sffDOcex1C3HO5kDolOYcWXTwRpZY/LvJujM6SMjn63fWMJWchYAAmkoAJXlbpZ5yf4d+KMgxd+LeETa4gD9sQ==", + "dependencies": { + "System.Collections.Immutable": "6.0.0" + } + }, + "TunnelVisionLabs.ReferenceAssemblyAnnotator": { + "type": "Direct", + "requested": "[1.0.0-alpha.160, )", + "resolved": "1.0.0-alpha.160", + "contentHash": "ktxB8PGoPpIaYKjLk/+P94Fi2Qw2E1Dw7atBQRrKnHA57sk8WwmkI4RJmg6s5ph4k1RIaaAZMus05ah/AikEkA==" + }, + "Microsoft.Build.Tasks.Git": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ==" + }, + "Microsoft.NETCore.Platforms": { + "type": "Transitive", + "resolved": "1.1.0", + "contentHash": "kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==" + }, + "Microsoft.SourceLink.Common": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" + }, + "System.Buffers": { + "type": "Transitive", + "resolved": "4.5.1", + "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" + }, + "System.Memory": { + "type": "Transitive", + "resolved": "4.5.4", + "contentHash": "1MbJTHS1lZ4bS4FmsJjnuGJOu88ZzTT2rLvrhW7Ygic+pC0NWA+3hgAen0HRdsocuQXCkUTdFn9yHJJhsijDXw==", + "dependencies": { + "System.Buffers": "4.5.1", + "System.Numerics.Vectors": "4.4.0", + "System.Runtime.CompilerServices.Unsafe": "4.5.3" + } + }, + "System.Numerics.Vectors": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "UiLzLW+Lw6HLed1Hcg+8jSRttrbuXv7DANVj0DkL9g6EnnzbL75EB7EWsw5uRbhxd/4YdG8li5XizGWepmG3PQ==" + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Transitive", + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" + } + } + } +} \ No newline at end of file diff --git a/ICSharpCode.ILSpyCmd/ICSharpCode.ILSpyCmd.csproj b/ICSharpCode.ILSpyCmd/ICSharpCode.ILSpyCmd.csproj index ca25d2eef..aba229ad0 100644 --- a/ICSharpCode.ILSpyCmd/ICSharpCode.ILSpyCmd.csproj +++ b/ICSharpCode.ILSpyCmd/ICSharpCode.ILSpyCmd.csproj @@ -31,6 +31,12 @@ + + + + true + true + false diff --git a/ICSharpCode.ILSpyCmd/packages.lock.json b/ICSharpCode.ILSpyCmd/packages.lock.json new file mode 100644 index 000000000..0ffdf6bd2 --- /dev/null +++ b/ICSharpCode.ILSpyCmd/packages.lock.json @@ -0,0 +1,453 @@ +{ + "version": 2, + "dependencies": { + "net8.0": { + "McMaster.Extensions.Hosting.CommandLine": { + "type": "Direct", + "requested": "[4.1.1, )", + "resolved": "4.1.1", + "contentHash": "+a37L3hHZC2KG1sbwdzTGlUWIJWYQv/9I4dLnrC0OVusR/665hkewjlz1jiAKa8jYbve4GTSZsRCoVXcSFFrdA==", + "dependencies": { + "McMaster.Extensions.CommandLineUtils": "4.1.1", + "Microsoft.Extensions.Hosting.Abstractions": "6.0.0", + "Microsoft.Extensions.Logging.Abstractions": "6.0.0" + } + }, + "Microsoft.Extensions.Hosting": { + "type": "Direct", + "requested": "[8.0.1, )", + "resolved": "8.0.1", + "contentHash": "bP9EEkHBEfjgYiG8nUaXqMk/ujwJrffOkNPP7onpRMO8R+OUSESSP4xHkCAXgYZ1COP2Q9lXlU5gkMFh20gRuw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Configuration.Binder": "8.0.2", + "Microsoft.Extensions.Configuration.CommandLine": "8.0.0", + "Microsoft.Extensions.Configuration.EnvironmentVariables": "8.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "8.0.1", + "Microsoft.Extensions.Configuration.Json": "8.0.1", + "Microsoft.Extensions.Configuration.UserSecrets": "8.0.1", + "Microsoft.Extensions.DependencyInjection": "8.0.1", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Diagnostics": "8.0.1", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Physical": "8.0.0", + "Microsoft.Extensions.Hosting.Abstractions": "8.0.1", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Logging.Configuration": "8.0.1", + "Microsoft.Extensions.Logging.Console": "8.0.1", + "Microsoft.Extensions.Logging.Debug": "8.0.1", + "Microsoft.Extensions.Logging.EventLog": "8.0.1", + "Microsoft.Extensions.Logging.EventSource": "8.0.1", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "NuGet.Protocol": { + "type": "Direct", + "requested": "[6.12.1, )", + "resolved": "6.12.1", + "contentHash": "VBN7OtG/Y9Rnj1WT3G8X88ZHu5Pq+yzca5Z6OI/FWXcENVAQkUl0ml6Cv8ghOqYyiuvnObGDV9oWLD/bIuVtDw==", + "dependencies": { + "NuGet.Packaging": "6.12.1" + } + }, + "TomsToolbox.Composition.Analyzer": { + "type": "Direct", + "requested": "[2.21.0, )", + "resolved": "2.21.0", + "contentHash": "vJx9hxAzjni34slGz78ewqYP9Ylk8dJszfEUK1TF5cflVKMBO3ORSFd0FtICTwJtE8munvZrMrcLWwXt5bIcEA==" + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "3lE/iLSutpgX1CC0NOW70FJoGARRHbyKmG7dc0klnUZ9Dd9hS6N/POPWhKhMLCEuNN5nXEY5agmlFtH562vqhQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "7IQhGK+wjyGrNsPBjJcZwWAr+Wf6D4+TwOptUt77bWtgNkiV8tDEbhFS+dDamtQFZ2X7kWG9m71iZQRj2x3zgQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.CommandLine": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "NZuZMz3Q8Z780nKX3ifV1fE7lS+6pynDHK71OfU4OZ1ItgvDOhyOC7E6z+JMZrAj63zRpwbdldYFk499t3+1dQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.EnvironmentVariables": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "plvZ0ZIpq+97gdPNNvhwvrEZ92kNml9hd1pe3idMA7svR0PztdzVLkoWLcRFgySYXUJc3kSM3Xw3mNFMo/bxRA==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.FileExtensions": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "EJzSNO9oaAXnTdtdNO6npPRsIIeZCBSNmdQ091VDO7fBiOtJAAeEq6dtrVXIi3ZyjC5XRSAtVvF8SzcneRHqKQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Physical": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.UserSecrets": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "7tYqdPPpAK+3jO9d5LTuCK2VxrEdf85Ol4trUr6ds4jclBecadWZ/RyPCbNjfbN5iGTfUnD/h65TOQuqQv2c+A==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Configuration.Json": "8.0.1", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileProviders.Physical": "8.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "BmANAnR5Xd4Oqw7yQ75xOAYODybZQRzdeNucg7kS5wWKd2PNnMdYtJ2Vciy0QLylRmv42DGl5+AFL9izA6F1Rw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" + } + }, + "Microsoft.Extensions.Diagnostics": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "doVPCUUCY7c6LhBsEfiy3W1bvS7Mi6LkfQMS8nlC22jZWNxBv8VO8bdfeyvpYFst6Kxqk7HBC6lytmEoBssvSQ==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Diagnostics.Abstractions": "8.0.1", + "Microsoft.Extensions.Options.ConfigurationExtensions": "8.0.0" + } + }, + "Microsoft.Extensions.Diagnostics.Abstractions": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "elH2vmwNmsXuKmUeMQ4YW9ldXiF+gSGDgg1vORksob5POnpaI6caj1Hu8zaYbEuibhqCoWg0YRWDazBY3zjBfg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.Extensions.FileProviders.Abstractions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "ZbaMlhJlpisjuWbvXr4LdAst/1XxH3vZ6A0BsgTphZ2L4PGuxRLz7Jr/S7mkAAnOn78Vu0fKhEgNF5JO3zfjqQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.FileProviders.Physical": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "UboiXxpPUpwulHvIAVE36Knq0VSHaAmfrFkegLyBZeaADuKezJ/AIXYAW8F5GBlGk/VaibN2k/Zn1ca8YAfVdA==", + "dependencies": { + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.FileSystemGlobbing": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.FileSystemGlobbing": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "OK+670i7esqlQrPjdIKRbsyMCe9g5kSLpRRQGSr4Q58AOYEe/hCnfLZprh7viNisSUUQZmMrbbuDaIrP+V1ebQ==" + }, + "Microsoft.Extensions.Hosting.Abstractions": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "nHwq9aPBdBPYXPti6wYEEfgXddfBrYC+CQLn+qISiwQq5tpfaqDZSKOJNxoe9rfQxGf1c+2wC/qWFe1QYJPYqw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Diagnostics.Abstractions": "8.0.1", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "4x+pzsQEbqxhNf1QYRr5TDkLP9UsLT3A6MdRKDDEgrW7h1ljiEPgTNhKYUhNCCAaVpQECVQ+onA91PTPnIp6Lw==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.Extensions.Logging.Abstractions": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "nroMDjS7hNBPtkZqVBbSiQaQjWRDxITI8Y7XnDs97rqG3EbzVTNLZQf7bIeUJcaHOV8bca47s1Uxq94+2oGdxA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2" + } + }, + "Microsoft.Extensions.Logging.Configuration": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "QWwTrsgOnJMmn+XUslm8D2H1n3PkP/u/v52FODtyBc/k4W9r3i2vcXXeeX/upnzllJYRRbrzVzT0OclfNJtBJA==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Configuration.Binder": "8.0.2", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2", + "Microsoft.Extensions.Options.ConfigurationExtensions": "8.0.0" + } + }, + "Microsoft.Extensions.Logging.Console": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "uzcg/5U2eLyn5LIKlERkdSxw6VPC1yydnOSQiRRWGBGN3kphq3iL4emORzrojScDmxRhv49gp5BI8U3Dz7y4iA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Logging.Configuration": "8.0.1", + "Microsoft.Extensions.Options": "8.0.2" + } + }, + "Microsoft.Extensions.Logging.Debug": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "B8hqNuYudC2RB+L/DI33uO4rf5by41fZVdcVL2oZj0UyoAZqnwTwYHp1KafoH4nkl1/23piNeybFFASaV2HkFg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2" + } + }, + "Microsoft.Extensions.Logging.EventLog": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "ZD1m4GXoxcZeDJIq8qePKj+QAWeQNO/OG8skvrOG8RQfxLp9MAKRoliTc27xanoNUzeqvX5HhS/I7c0BvwAYUg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2", + "System.Diagnostics.EventLog": "8.0.1" + } + }, + "Microsoft.Extensions.Logging.EventSource": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "YMXMAla6B6sEf/SnfZYTty633Ool3AH7KOw2LOaaEqwSo2piK4f7HMtzyc3CNiipDnq1fsUSuG5Oc7ZzpVy8WQ==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.2", + "Microsoft.Extensions.Logging": "8.0.1", + "Microsoft.Extensions.Logging.Abstractions": "8.0.2", + "Microsoft.Extensions.Options": "8.0.2", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "8.0.2", + "contentHash": "dWGKvhFybsaZpGmzkGCbNNwBD1rVlWzrZKANLW/CcbFJpCEceMCGzT7zZwHOGBCbwM0SzBuceMj5HN1LKV1QqA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "0f4DMRqEd50zQh+UyJc+/HiBsZ3vhAQALgdkcQEalSH1L2isdC7Yj54M3cyo5e+BeO5fcBQ7Dxly8XiBBcvRgw==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Configuration.Binder": "8.0.0", + "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0", + "Microsoft.Extensions.Options": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "bXJEZrW9ny8vjMF1JV253WeLhpEVzFo1lyaZu1vQ4ZxWUlVvknZ/+ftFgVheLubb4eZPSwwxBeqS1JkCOjxd8g==" + }, + "Newtonsoft.Json": { + "type": "Transitive", + "resolved": "13.0.3", + "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ==" + }, + "NuGet.Common": { + "type": "Transitive", + "resolved": "6.12.1", + "contentHash": "nk8nTdhQl4x2VaAQUvefI7DDYAuBDlE+OZZRffm50Qx5dUAEq8wkc5JIqrN2lTEohObHPI/SXyG2UFdMQkrdyg==", + "dependencies": { + "NuGet.Frameworks": "6.12.1" + } + }, + "NuGet.Configuration": { + "type": "Transitive", + "resolved": "6.12.1", + "contentHash": "IRwlY1379ZgJ0oEJvjD+lDuOhJ5S1fsU5n/bEC5/i0+N9bo2WIMDAdaQ/qIdyK/gMJ/YWS+++GSX6rN7luqEvg==", + "dependencies": { + "NuGet.Common": "6.12.1", + "System.Security.Cryptography.ProtectedData": "4.4.0" + } + }, + "NuGet.Frameworks": { + "type": "Transitive", + "resolved": "6.12.1", + "contentHash": "kPaRD5RJC0ByUg+yGX6bDz5XHMI7OYmQwP8kbtef+vZ+csj/VDb5Bwas4ChxwhoAbI8lEvwP5/3aViQPpgNBow==" + }, + "NuGet.Packaging": { + "type": "Transitive", + "resolved": "6.12.1", + "contentHash": "6s5NO3VNX6fIx6GwuWZtIsal9W1xkelYd3Vg2KUAg1zGqnKC3wB5IZlombvVGVGcwyl/A+iDvpUwSvgeDoB3wA==", + "dependencies": { + "Newtonsoft.Json": "13.0.3", + "NuGet.Configuration": "6.12.1", + "NuGet.Versioning": "6.12.1", + "System.Formats.Asn1": "8.0.1", + "System.Security.Cryptography.Pkcs": "6.0.4" + } + }, + "NuGet.Versioning": { + "type": "Transitive", + "resolved": "6.12.1", + "contentHash": "fJ6rFYANDnohFsdpaY79FvrJxI6murmoOxXz6nZlf819F48+IBKMnAIg3oIBRtZq5y498ObMtKnro5IitvizUg==" + }, + "System.ComponentModel.Annotations": { + "type": "Transitive", + "resolved": "5.0.0", + "contentHash": "dMkqfy2el8A8/I76n2Hi1oBFEbG1SfxD2l5nhwXV3XjlnOmwxJlQbYpJH4W51odnU9sARCSAgv7S3CyAFMkpYg==" + }, + "System.Diagnostics.EventLog": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "n1ZP7NM2Gkn/MgD8+eOT5MulMj6wfeQMNS2Pizvq5GHCZfjlFMXV2irQlQmJhwA2VABC57M0auudO89Iu2uRLg==" + }, + "System.Formats.Asn1": { + "type": "Transitive", + "resolved": "8.0.1", + "contentHash": "XqKba7Mm/koKSjKMfW82olQdmfbI5yqeoLV/tidRp7fbh5rmHAQ5raDI/7SU0swTzv+jgqtUGkzmFxuUg0it1A==" + }, + "System.Security.Cryptography.Pkcs": { + "type": "Transitive", + "resolved": "6.0.4", + "contentHash": "LGbXi1oUJ9QgCNGXRO9ndzBL/GZgANcsURpMhNR8uO+rca47SZmciS3RSQUvlQRwK3QHZSHNOXzoMUASKA+Anw==", + "dependencies": { + "System.Formats.Asn1": "6.0.0" + } + }, + "System.Security.Cryptography.ProtectedData": { + "type": "Transitive", + "resolved": "4.4.0", + "contentHash": "cJV7ScGW7EhatRsjehfvvYVBvtiSMKgN8bOVI0bQhnF5bU7vnHVIsH49Kva7i7GWaWYvmEzkYVk1TC+gZYBEog==" + }, + "icsharpcode.decompiler": { + "type": "Project", + "dependencies": { + "System.Collections.Immutable": "[6.0.0, )", + "System.Reflection.Metadata": "[6.0.0, )" + } + }, + "icsharpcode.ilspyx": { + "type": "Project", + "dependencies": { + "ICSharpCode.Decompiler": "[8.0.0-noversion, )", + "K4os.Compression.LZ4": "[1.3.8, )", + "Mono.Cecil": "[0.11.6, )", + "System.Composition.AttributedModel": "[9.0.0, )", + "System.Reflection.Metadata": "[9.0.0, )", + "System.Runtime.CompilerServices.Unsafe": "[6.1.0, )" + } + }, + "K4os.Compression.LZ4": { + "type": "CentralTransitive", + "requested": "[1.3.8, )", + "resolved": "1.3.8", + "contentHash": "LhwlPa7c1zs1OV2XadMtAWdImjLIsqFJPoRcIWAadSRn0Ri1DepK65UbWLPmt4riLqx2d40xjXRk0ogpqNtK7g==" + }, + "McMaster.Extensions.CommandLineUtils": { + "type": "CentralTransitive", + "requested": "[4.1.1, )", + "resolved": "4.1.1", + "contentHash": "zxgDY+G5yVq2q8sVB3Z275Qkxed1jC95nwAfnlSyoG4l5Nicvd4+ke1jXusEZEfyuErlAgXCKS937c13FmZWBg==", + "dependencies": { + "System.ComponentModel.Annotations": "5.0.0" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "CentralTransitive", + "requested": "[8.0.0, )", + "resolved": "8.0.0", + "contentHash": "0J/9YNXTMWSZP2p2+nvl8p71zpSwokZXZuJW+VjdErkegAnFdO1XlqtA62SJtgVYHdKu3uPxJHcMR/r35HwFBA==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Primitives": "8.0.0" + } + }, + "Microsoft.Extensions.Configuration.Json": { + "type": "CentralTransitive", + "requested": "[8.0.1, )", + "resolved": "8.0.1", + "contentHash": "L89DLNuimOghjV3tLx0ArFDwVEJD6+uGB3BMCMX01kaLzXkaXHb2021xOMl2QOxUxbdePKUZsUY7n2UUkycjRg==", + "dependencies": { + "Microsoft.Extensions.Configuration": "8.0.0", + "Microsoft.Extensions.Configuration.Abstractions": "8.0.0", + "Microsoft.Extensions.Configuration.FileExtensions": "8.0.1", + "Microsoft.Extensions.FileProviders.Abstractions": "8.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "CentralTransitive", + "requested": "[8.0.2, )", + "resolved": "8.0.2", + "contentHash": "3iE7UF7MQkCv1cxzCahz+Y/guQbTqieyxyaWKhrRO91itI9cOKO76OHeQDahqG4MmW5umr3CcCvGmK92lWNlbg==" + }, + "Mono.Cecil": { + "type": "CentralTransitive", + "requested": "[0.11.6, )", + "resolved": "0.11.6", + "contentHash": "f33RkDtZO8VlGXCtmQIviOtxgnUdym9xx/b1p9h91CRGOsJFxCFOFK1FDbVt1OCf1aWwYejUFa2MOQyFWTFjbA==" + }, + "System.Collections.Immutable": { + "type": "CentralTransitive", + "requested": "[9.0.0, )", + "resolved": "9.0.0", + "contentHash": "QhkXUl2gNrQtvPmtBTQHb0YsUrDiDQ2QS09YbtTTiSjGcf7NBqtYbrG/BE06zcBPCKEwQGzIv13IVdXNOSub2w==" + }, + "System.Composition.AttributedModel": { + "type": "CentralTransitive", + "requested": "[9.0.0, )", + "resolved": "9.0.0", + "contentHash": "iri00l/zIX9g4lHMY+Nz0qV1n40+jFYAmgsaiNn16xvt2RDwlqByNG4wgblagnDYxm3YSQQ0jLlC/7Xlk9CzyA==" + }, + "System.Reflection.Metadata": { + "type": "CentralTransitive", + "requested": "[9.0.0, )", + "resolved": "9.0.0", + "contentHash": "ANiqLu3DxW9kol/hMmTWbt3414t9ftdIuiIU7j80okq2YzAueo120M442xk1kDJWtmZTqWQn7wHDvMRipVOEOQ==", + "dependencies": { + "System.Collections.Immutable": "9.0.0" + } + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "CentralTransitive", + "requested": "[6.1.0, )", + "resolved": "6.1.0", + "contentHash": "5o/HZxx6RVqYlhKSq8/zronDkALJZUT2Vz0hx43f0gwe8mwlM0y2nYlqdBwLMzr262Bwvpikeb/yEwkAa5PADg==" + } + } + } +} \ No newline at end of file diff --git a/ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj b/ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj index 76a7b3504..4272c40aa 100644 --- a/ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj +++ b/ICSharpCode.ILSpyX/ICSharpCode.ILSpyX.csproj @@ -48,6 +48,12 @@ + + + true + true + + diff --git a/ICSharpCode.ILSpyX/packages.lock.json b/ICSharpCode.ILSpyX/packages.lock.json new file mode 100644 index 000000000..37a460ef0 --- /dev/null +++ b/ICSharpCode.ILSpyX/packages.lock.json @@ -0,0 +1,79 @@ +{ + "version": 2, + "dependencies": { + "net8.0": { + "K4os.Compression.LZ4": { + "type": "Direct", + "requested": "[1.3.8, )", + "resolved": "1.3.8", + "contentHash": "LhwlPa7c1zs1OV2XadMtAWdImjLIsqFJPoRcIWAadSRn0Ri1DepK65UbWLPmt4riLqx2d40xjXRk0ogpqNtK7g==" + }, + "Microsoft.SourceLink.GitHub": { + "type": "Direct", + "requested": "[8.0.0, )", + "resolved": "8.0.0", + "contentHash": "G5q7OqtwIyGTkeIOAc3u2ZuV/kicQaec5EaRnc0pIeSnh9LUjj+PYQrJYBURvDt7twGl2PKA7nSN0kz1Zw5bnQ==", + "dependencies": { + "Microsoft.Build.Tasks.Git": "8.0.0", + "Microsoft.SourceLink.Common": "8.0.0" + } + }, + "Mono.Cecil": { + "type": "Direct", + "requested": "[0.11.6, )", + "resolved": "0.11.6", + "contentHash": "f33RkDtZO8VlGXCtmQIviOtxgnUdym9xx/b1p9h91CRGOsJFxCFOFK1FDbVt1OCf1aWwYejUFa2MOQyFWTFjbA==" + }, + "System.Composition.AttributedModel": { + "type": "Direct", + "requested": "[9.0.0, )", + "resolved": "9.0.0", + "contentHash": "iri00l/zIX9g4lHMY+Nz0qV1n40+jFYAmgsaiNn16xvt2RDwlqByNG4wgblagnDYxm3YSQQ0jLlC/7Xlk9CzyA==" + }, + "System.Reflection.Metadata": { + "type": "Direct", + "requested": "[9.0.0, )", + "resolved": "9.0.0", + "contentHash": "ANiqLu3DxW9kol/hMmTWbt3414t9ftdIuiIU7j80okq2YzAueo120M442xk1kDJWtmZTqWQn7wHDvMRipVOEOQ==", + "dependencies": { + "System.Collections.Immutable": "9.0.0" + } + }, + "System.Runtime.CompilerServices.Unsafe": { + "type": "Direct", + "requested": "[6.1.0, )", + "resolved": "6.1.0", + "contentHash": "5o/HZxx6RVqYlhKSq8/zronDkALJZUT2Vz0hx43f0gwe8mwlM0y2nYlqdBwLMzr262Bwvpikeb/yEwkAa5PADg==" + }, + "TomsToolbox.Composition.Analyzer": { + "type": "Direct", + "requested": "[2.21.0, )", + "resolved": "2.21.0", + "contentHash": "vJx9hxAzjni34slGz78ewqYP9Ylk8dJszfEUK1TF5cflVKMBO3ORSFd0FtICTwJtE8munvZrMrcLWwXt5bIcEA==" + }, + "Microsoft.Build.Tasks.Git": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "bZKfSIKJRXLTuSzLudMFte/8CempWjVamNUR5eHJizsy+iuOuO/k2gnh7W0dHJmYY0tBf+gUErfluCv5mySAOQ==" + }, + "Microsoft.SourceLink.Common": { + "type": "Transitive", + "resolved": "8.0.0", + "contentHash": "dk9JPxTCIevS75HyEQ0E4OVAFhB2N+V9ShCXf8Q6FkUQZDkgLI12y679Nym1YqsiSysuQskT7Z+6nUf3yab6Vw==" + }, + "icsharpcode.decompiler": { + "type": "Project", + "dependencies": { + "System.Collections.Immutable": "[6.0.0, )", + "System.Reflection.Metadata": "[6.0.0, )" + } + }, + "System.Collections.Immutable": { + "type": "CentralTransitive", + "requested": "[9.0.0, )", + "resolved": "9.0.0", + "contentHash": "QhkXUl2gNrQtvPmtBTQHb0YsUrDiDQ2QS09YbtTTiSjGcf7NBqtYbrG/BE06zcBPCKEwQGzIv13IVdXNOSub2w==" + } + } + } +} \ No newline at end of file diff --git a/ILSpy.Installer/ILSpy.Installer.csproj b/ILSpy.Installer/ILSpy.Installer.csproj index 6edfaab49..266020a76 100644 --- a/ILSpy.Installer/ILSpy.Installer.csproj +++ b/ILSpy.Installer/ILSpy.Installer.csproj @@ -15,7 +15,7 @@ - + From 045b08f9460092008b8b2c1e69df6d5dc3b48523 Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Fri, 3 Jan 2025 14:40:27 +0100 Subject: [PATCH 18/26] Create SECURITY.md --- SECURITY.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..1ba498f29 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,15 @@ +# Security Policy + +## Supported Versions + +Supported are the latest released version as well as the latest preview/rc version. + +## Reporting a Vulnerability + +Security issues and bugs should be reported privately to christoph.wille AT gmail.com. Please note that +we cannot guarantee a response time (*) although we will strive to get back to you within one business day. If you +do not hear back from Chris within a week, alternatively try to contact siegfriedpammer AT gmail.com. + +Please do not open issues for anything you think might have a security implication. + +(*) We are an OSS project entirely run by volunteers and sometimes lifetm will mean longer response times. From 6215747563c3a7d21adfd7336f114f41e56d2b8b Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Fri, 3 Jan 2025 16:23:03 +0100 Subject: [PATCH 19/26] Principle of least privilege for workflow tokens (#3360) --- .github/workflows/build-frontends.yml | 3 +++ .github/workflows/build-ilspy.yml | 5 +++++ .github/workflows/codeql-analysis.yml | 7 +++++++ .github/workflows/generate-bom.yml | 3 +++ .github/workflows/lock.yml | 5 +++++ 5 files changed, 23 insertions(+) diff --git a/.github/workflows/build-frontends.yml b/.github/workflows/build-frontends.yml index 2ebe5fd40..d9abeabe5 100644 --- a/.github/workflows/build-frontends.yml +++ b/.github/workflows/build-frontends.yml @@ -6,6 +6,9 @@ on: pull_request: branches: [ master, release/** ] +permissions: + contents: read + jobs: build: runs-on: ubuntu-latest diff --git a/.github/workflows/build-ilspy.yml b/.github/workflows/build-ilspy.yml index 51c2b595c..f5edfdc97 100644 --- a/.github/workflows/build-ilspy.yml +++ b/.github/workflows/build-ilspy.yml @@ -6,8 +6,13 @@ on: pull_request: branches: [ master, release/** ] +permissions: + contents: read + jobs: Build: + permissions: + packages: write # for dotnet nuget push runs-on: windows-2022 strategy: fail-fast: false diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 1886a05af..f7cd2250c 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -6,8 +6,15 @@ on: pull_request: branches: [ master, release/** ] +permissions: + contents: read + jobs: analyze: + permissions: + actions: read # for github/codeql-action/init to get workflow details + security-events: write # for github/codeql-action/analyze to upload SARIF results + name: Analyze runs-on: ubuntu-latest diff --git a/.github/workflows/generate-bom.yml b/.github/workflows/generate-bom.yml index 5cfafea63..44cf80453 100644 --- a/.github/workflows/generate-bom.yml +++ b/.github/workflows/generate-bom.yml @@ -3,6 +3,9 @@ name: Generate BOM on: workflow_dispatch: +permissions: + contents: read + jobs: build: diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index 3bc404b70..4ef571260 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -4,8 +4,13 @@ on: schedule: - cron: '0 0 * * *' +permissions: + contents: read + jobs: lock: + permissions: + issues: write # for dessant/lock-threads to lock issues runs-on: ubuntu-latest steps: - uses: dessant/lock-threads@v5.0.1 From efbefd0d3b19b61299c3a22dce5b4446a9d7f37c Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 4 Jan 2025 12:28:30 +0100 Subject: [PATCH 20/26] Fix #3361: switch-value conversion was losing its target type. --- .../TestCases/Pretty/Switch.cs | 86 +++++++++++++++++++ .../CSharp/ExpressionBuilder.cs | 19 +++- .../CSharp/StatementBuilder.cs | 25 +----- 3 files changed, 102 insertions(+), 28 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs index 856c02028..e6e7e7ae4 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs @@ -67,6 +67,36 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } } + public class ImplicitInt + { + private readonly int s; + + public ImplicitInt(int s) + { + this.s = s; + } + + public static implicit operator int(ImplicitInt v) + { + return v.s; + } + } + + public class ExplicitInt + { + private readonly int s; + + public ExplicitInt(int s) + { + this.s = s; + } + + public static explicit operator int(ExplicitInt v) + { + return v.s; + } + } + public enum State { False, @@ -310,6 +340,62 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } } + public static void SwitchOverExplicitInt(ExplicitInt i) + { + switch ((int)i) + { + case 0: + Console.WriteLine("zero"); + break; + case 5: + Console.WriteLine("five"); + break; + case 10: + Console.WriteLine("ten"); + break; + case 15: + Console.WriteLine("fifteen"); + break; + case 20: + Console.WriteLine("twenty"); + break; + case 25: + Console.WriteLine("twenty-five"); + break; + case 30: + Console.WriteLine("thirty"); + break; + } + } + + public static void SwitchOverImplicitInt(ImplicitInt i) + { + switch (i) + { + case 0: + Console.WriteLine("zero"); + break; + case 5: + Console.WriteLine("five"); + break; + case 10: + Console.WriteLine("ten"); + break; + case 15: + Console.WriteLine("fifteen"); + break; + case 20: + Console.WriteLine("twenty"); + break; + case 25: + Console.WriteLine("twenty-five"); + break; + case 30: + Console.WriteLine("thirty"); + break; + } + } + // SwitchDetection.UseCSharpSwitch requires more complex heuristic to identify this when compiled with Roslyn public static void CompactSwitchOverInt(int i) { diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 635d32871..dfec27d8d 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -3900,17 +3900,20 @@ namespace ICSharpCode.Decompiler.CSharp } } - protected internal override TranslatedExpression VisitSwitchInstruction(SwitchInstruction inst, TranslationContext context) + internal (TranslatedExpression, IType) TranslateSwitchValue(SwitchInstruction inst, bool allowImplicitConversion) { TranslatedExpression value; IType type; if (inst.Value is StringToInt strToInt) { + // switch-expression does not support implicit conversions at all, + // switch-statement does support implicit conversions in general, however, the rules are + // not very intuitive and in order to prevent bugs, we emit an explicit cast. value = Translate(strToInt.Argument) .ConvertTo( strToInt.ExpectedType, this, - allowImplicitConversion: false // switch-expression does not support implicit conversions + allowImplicitConversion: false ); type = compilation.FindType(KnownTypeCode.String); } @@ -3918,12 +3921,20 @@ namespace ICSharpCode.Decompiler.CSharp { strToInt = null; value = Translate(inst.Value); + type = value.Type; if (inst.Type != null) { - value = value.ConvertTo(inst.Type, this, allowImplicitConversion: true); + value = value.ConvertTo(inst.Type, this, allowImplicitConversion: allowImplicitConversion); + type = inst.Type; } - type = value.Type; } + return (value, type); + } + + protected internal override TranslatedExpression VisitSwitchInstruction(SwitchInstruction inst, TranslationContext context) + { + // switch-expression does not support implicit conversions + var (value, type) = TranslateSwitchValue(inst, allowImplicitConversion: false); IL.SwitchSection defaultSection = inst.GetDefaultSection(); SwitchExpression switchExpr = new SwitchExpression(); diff --git a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs index 4dfc5f658..52fcb2302 100644 --- a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs @@ -210,30 +210,7 @@ namespace ICSharpCode.Decompiler.CSharp var oldCaseLabelMapping = caseLabelMapping; caseLabelMapping = new Dictionary(); - TranslatedExpression value; - IType type; - if (inst.Value is StringToInt strToInt) - { - value = exprBuilder.Translate(strToInt.Argument) - .ConvertTo( - strToInt.ExpectedType, - exprBuilder, - // switch statement does support implicit conversions in general, however, the rules are - // not very intuitive and in order to prevent bugs, we emit an explicit cast. - allowImplicitConversion: false - ); - type = exprBuilder.compilation.FindType(KnownTypeCode.String); - } - else - { - strToInt = null; - value = exprBuilder.Translate(inst.Value); - if (inst.Type != null) - { - value = value.ConvertTo(inst.Type, exprBuilder, allowImplicitConversion: true); - } - type = value.Type; - } + var (value, type) = exprBuilder.TranslateSwitchValue(inst, allowImplicitConversion: true); IL.SwitchSection defaultSection = inst.GetDefaultSection(); From e4285b751b7636e774b6552e809b8084c03bd74f Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 4 Jan 2025 13:06:27 +0100 Subject: [PATCH 21/26] Fix build. --- ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs | 11 ++++------- ICSharpCode.Decompiler/CSharp/StatementBuilder.cs | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index dfec27d8d..9f53f9c89 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -3900,20 +3900,17 @@ namespace ICSharpCode.Decompiler.CSharp } } - internal (TranslatedExpression, IType) TranslateSwitchValue(SwitchInstruction inst, bool allowImplicitConversion) + internal (TranslatedExpression, IType, StringToInt) TranslateSwitchValue(SwitchInstruction inst, bool allowImplicitConversion) { TranslatedExpression value; IType type; if (inst.Value is StringToInt strToInt) { - // switch-expression does not support implicit conversions at all, - // switch-statement does support implicit conversions in general, however, the rules are - // not very intuitive and in order to prevent bugs, we emit an explicit cast. value = Translate(strToInt.Argument) .ConvertTo( strToInt.ExpectedType, this, - allowImplicitConversion: false + allowImplicitConversion: allowImplicitConversion ); type = compilation.FindType(KnownTypeCode.String); } @@ -3928,13 +3925,13 @@ namespace ICSharpCode.Decompiler.CSharp type = inst.Type; } } - return (value, type); + return (value, type, strToInt); } protected internal override TranslatedExpression VisitSwitchInstruction(SwitchInstruction inst, TranslationContext context) { // switch-expression does not support implicit conversions - var (value, type) = TranslateSwitchValue(inst, allowImplicitConversion: false); + var (value, type, strToInt) = TranslateSwitchValue(inst, allowImplicitConversion: false); IL.SwitchSection defaultSection = inst.GetDefaultSection(); SwitchExpression switchExpr = new SwitchExpression(); diff --git a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs index 52fcb2302..a806e8bb7 100644 --- a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs @@ -210,7 +210,7 @@ namespace ICSharpCode.Decompiler.CSharp var oldCaseLabelMapping = caseLabelMapping; caseLabelMapping = new Dictionary(); - var (value, type) = exprBuilder.TranslateSwitchValue(inst, allowImplicitConversion: true); + var (value, type, strToInt) = exprBuilder.TranslateSwitchValue(inst, allowImplicitConversion: true); IL.SwitchSection defaultSection = inst.GetDefaultSection(); From e1e2f739f620a603c44ee66964be2703b02b9443 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 5 Jan 2025 20:21:15 +0100 Subject: [PATCH 22/26] Fix switch-on-string transform for optimized Roslyn. --- .../TestCases/Pretty/Switch.cs | 100 +++++++++++++++++- .../IL/Transforms/SwitchOnStringTransform.cs | 89 +++++++++------- 2 files changed, 148 insertions(+), 41 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs index e6e7e7ae4..f5647187f 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/Switch.cs @@ -82,6 +82,46 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } } + public class ImplicitConversionConflictWithLong + { + private readonly int s; + + public ImplicitConversionConflictWithLong(int s) + { + this.s = s; + } + + public static implicit operator int(ImplicitConversionConflictWithLong v) + { + return v.s; + } + + public static implicit operator long(ImplicitConversionConflictWithLong v) + { + return v.s; + } + } + + public class ImplicitConversionConflictWithString + { + private readonly int s; + + public ImplicitConversionConflictWithString(int s) + { + this.s = s; + } + + public static implicit operator int(ImplicitConversionConflictWithString v) + { + return v.s; + } + + public static implicit operator string(ImplicitConversionConflictWithString v) + { + return string.Empty; + } + } + public class ExplicitInt { private readonly int s; @@ -396,6 +436,62 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty } } + public static void SwitchOverImplicitIntConflictLong(ImplicitConversionConflictWithLong i) + { + switch ((int)i) + { + case 0: + Console.WriteLine("zero"); + break; + case 5: + Console.WriteLine("five"); + break; + case 10: + Console.WriteLine("ten"); + break; + case 15: + Console.WriteLine("fifteen"); + break; + case 20: + Console.WriteLine("twenty"); + break; + case 25: + Console.WriteLine("twenty-five"); + break; + case 30: + Console.WriteLine("thirty"); + break; + } + } + + public static void SwitchOverImplicitIntConflictString(ImplicitConversionConflictWithString i) + { + switch ((string)i) + { + case "0": + Console.WriteLine("zero"); + break; + case "5": + Console.WriteLine("five"); + break; + case "10": + Console.WriteLine("ten"); + break; + case "15": + Console.WriteLine("fifteen"); + break; + case "20": + Console.WriteLine("twenty"); + break; + case "25": + Console.WriteLine("twenty-five"); + break; + case "30": + Console.WriteLine("thirty"); + break; + } + } + // SwitchDetection.UseCSharpSwitch requires more complex heuristic to identify this when compiled with Roslyn public static void CompactSwitchOverInt(int i) { @@ -507,9 +603,7 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty public static string SwitchOverImplicitString(ImplicitString s) { - // we emit an explicit cast, because the rules used by the C# compiler are counter-intuitive: - // The C# compiler does *not* take the type of the switch labels into account at all. - switch ((string)s) + switch (s) { case "First case": return "Text1"; diff --git a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs index e254d243b..8302038b8 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/SwitchOnStringTransform.cs @@ -1070,10 +1070,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms stringValues.Add((null, nullValueCaseBlock)); } // In newer Roslyn versions (>=3.7) the null check appears in the default case, not prior to the switch. - if (!stringValues.Any(pair => pair.Value == null) && IsNullCheckInDefaultBlock(ref exitOrDefaultBlock, switchValueLoad.Variable, out nullValueCaseBlock)) + ILInstruction exitOrDefault = exitOrDefaultBlock; + if (!stringValues.Any(pair => pair.Value == null) && IsNullCheckInDefaultBlock(ref exitOrDefault, switchValueLoad.Variable, out nullValueCaseBlock)) { stringValues.Add((null, nullValueCaseBlock)); } + exitOrDefaultBlock = (Block)exitOrDefault; context.Step(nameof(MatchRoslynSwitchOnString), switchValueLoad); if (exitOrDefaultBlock != null) @@ -1176,7 +1178,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms { if (!instructions[i + 1].MatchBranch(out var nextBlock)) return false; - if (!exitBlockJump.MatchBranch(out nullCase)) + if (!exitBlockJump.MatchBranch(out nullCase) && !exitBlockJump.MatchLeave(out _)) return false; // if (comp(ldloc switchValueVar == ldnull)) br ... // br switchOnLengthBlock @@ -1202,7 +1204,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms switchValueVar = null; // will be extracted in MatchSwitchOnLengthBlock switchOnLengthBlockStartOffset = i; } - Block defaultCase = null; + ILInstruction defaultCase = null; if (!MatchSwitchOnLengthBlock(ref switchValueVar, switchOnLengthBlock, switchOnLengthBlockStartOffset, out var blocksByLength)) return false; List<(string, ILInstruction)> stringValues = new(); @@ -1216,41 +1218,51 @@ namespace ICSharpCode.Decompiler.IL.Transforms else { int length = (int)b.Length.Intervals[0].Start; - if (MatchSwitchOnCharBlock(b.TargetBlock, length, switchValueVar, out var mapping)) + switch (b.TargetBlock) { - foreach (var item in mapping) - { - if (!stringValues.Any(x => x.Item1 == item.StringValue)) + case Leave leave: + break; + case Block targetBlock: + if (MatchSwitchOnCharBlock(targetBlock, length, switchValueVar, out var mapping)) + { + foreach (var item in mapping) + { + if (!stringValues.Any(x => x.Item1 == item.StringValue)) + { + stringValues.Add(item); + } + else + { + return false; + } + } + } + else if (MatchRoslynCaseBlockHead(targetBlock, switchValueVar, out var bodyOrLeave, out var exit, out string stringValue, out _)) + { + if (exit != defaultCase) + return false; + if (!stringValues.Any(x => x.Item1 == stringValue)) + { + stringValues.Add((stringValue, bodyOrLeave)); + } + else + { + return false; + } + } + else if (length == 0) { - stringValues.Add(item); + stringValues.Add(("", b.TargetBlock)); } else { return false; } - } - } - else if (MatchRoslynCaseBlockHead(b.TargetBlock, switchValueVar, out var bodyOrLeave, out var exit, out string stringValue, out _)) - { - if (exit != defaultCase) + break; + default: return false; - if (!stringValues.Any(x => x.Item1 == stringValue)) - { - stringValues.Add((stringValue, bodyOrLeave)); - } - else - { - return false; - } - } - else if (length == 0) - { - stringValues.Add(("", b.TargetBlock)); - } - else - { - return false; } + } } @@ -1278,7 +1290,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms } var newSwitch = new SwitchInstruction(new StringToInt(new LdLoc(switchValueVar), values, switchValueVar.Type)); newSwitch.Sections.AddRange(sections); - newSwitch.Sections.Add(new SwitchSection { Labels = defaultLabel, Body = new Branch(defaultCase) }); + newSwitch.Sections.Add(new SwitchSection { Labels = defaultLabel, Body = defaultCase is Block b2 ? new Branch(b2) : defaultCase }); newSwitch.AddILRange(instructions[i]); if (nullCase != null) { @@ -1399,7 +1411,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms return results?.Count > 0; } - bool MatchSwitchOnLengthBlock(ref ILVariable switchValueVar, Block switchOnLengthBlock, int startOffset, out List<(LongSet Length, Block TargetBlock)> blocks) + bool MatchSwitchOnLengthBlock(ref ILVariable switchValueVar, Block switchOnLengthBlock, int startOffset, out List<(LongSet Length, ILInstruction TargetBlock)> blocks) { blocks = null; SwitchInstruction @switch; @@ -1482,17 +1494,18 @@ namespace ICSharpCode.Decompiler.IL.Transforms { if (section.HasNullLabel) return false; - if (!section.Body.MatchBranch(out var target)) + if (!section.Body.MatchBranch(out var target) && !section.Body.MatchLeave(out _)) return false; + ILInstruction targetInst = target ?? section.Body; if (section.Labels.Count() != 1) { - defaultCase ??= target; - if (defaultCase != target) + defaultCase ??= targetInst; + if (defaultCase != targetInst) return false; } else { - blocks.Add((section.Labels, target)); + blocks.Add((section.Labels, targetInst)); } } return true; @@ -1506,10 +1519,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms /// br newDefaultBlock /// } /// - private bool IsNullCheckInDefaultBlock(ref Block exitOrDefaultBlock, ILVariable switchVar, out Block nullValueCaseBlock) + private bool IsNullCheckInDefaultBlock(ref ILInstruction exitOrDefault, ILVariable switchVar, out Block nullValueCaseBlock) { nullValueCaseBlock = null; - if (exitOrDefaultBlock == null) + if (exitOrDefault is not Block exitOrDefaultBlock) return false; if (!exitOrDefaultBlock.Instructions[0].MatchIfInstruction(out var condition, out var thenBranch)) return false; @@ -1523,7 +1536,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms return false; if (elseBlock.Parent != exitOrDefaultBlock.Parent) return false; - exitOrDefaultBlock = elseBlock; + exitOrDefault = elseBlock; return true; } From 7c6f7fea0567af4a24a9c3c8df24a507c80892a0 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 5 Jan 2025 20:22:44 +0100 Subject: [PATCH 23/26] Make sure that there is only one applicable implicit conversion when dealing with switch, otherwise use an explicit cast. --- .../CSharp/ExpressionBuilder.cs | 83 +++++++++++++++---- .../CSharp/StatementBuilder.cs | 2 +- 2 files changed, 70 insertions(+), 15 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 9f53f9c89..2b32f842b 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -3900,38 +3900,93 @@ namespace ICSharpCode.Decompiler.CSharp } } - internal (TranslatedExpression, IType, StringToInt) TranslateSwitchValue(SwitchInstruction inst, bool allowImplicitConversion) + internal (TranslatedExpression, IType, StringToInt) TranslateSwitchValue(SwitchInstruction inst, bool isExpressionContext) { TranslatedExpression value; IType type; + // prepare expression and expected type if (inst.Value is StringToInt strToInt) { - value = Translate(strToInt.Argument) - .ConvertTo( - strToInt.ExpectedType, - this, - allowImplicitConversion: allowImplicitConversion - ); - type = compilation.FindType(KnownTypeCode.String); + value = Translate(strToInt.Argument); + type = strToInt.ExpectedType ?? compilation.FindType(KnownTypeCode.String); } else { strToInt = null; value = Translate(inst.Value); - type = value.Type; - if (inst.Type != null) + type = inst.Type ?? value.Type; + } + + // find and unwrap the input type + IType inputType = value.Type; + if (value.Expression is CastExpression && value.ResolveResult is ConversionResolveResult crr) + { + inputType = crr.Input.Type; + } + inputType = NullableType.GetUnderlyingType(inputType).GetEnumUnderlyingType(); + + // check input/underlying type for compatibility + bool allowImplicitConversion; + if (IsCompatibleWithSwitch(inputType) || (strToInt != null && inputType.Equals(type))) + { + allowImplicitConversion = !isExpressionContext; + } + else + { + var applicableImplicitConversionOperators = inputType.GetMethods(IsCompatibleImplicitConversionOperator).ToArray(); + switch (applicableImplicitConversionOperators.Length) { - value = value.ConvertTo(inst.Type, this, allowImplicitConversion: allowImplicitConversion); - type = inst.Type; + case 0: + allowImplicitConversion = !isExpressionContext; + break; + case 1: + allowImplicitConversion = !isExpressionContext; + // TODO validate + break; + default: + allowImplicitConversion = false; + break; } } - return (value, type, strToInt); + + value = value.ConvertTo(type, this, allowImplicitConversion: allowImplicitConversion); + + var caseType = strToInt != null + ? compilation.FindType(KnownTypeCode.String) + : type; + + return (value, caseType, strToInt); + + static bool IsCompatibleWithSwitch(IType type) + { + return type.IsKnownType(KnownTypeCode.SByte) + || type.IsKnownType(KnownTypeCode.Byte) + || type.IsKnownType(KnownTypeCode.Int16) + || type.IsKnownType(KnownTypeCode.UInt16) + || type.IsKnownType(KnownTypeCode.Int32) + || type.IsKnownType(KnownTypeCode.UInt32) + || type.IsKnownType(KnownTypeCode.Int64) + || type.IsKnownType(KnownTypeCode.UInt64) + || type.IsKnownType(KnownTypeCode.Char) + || type.IsKnownType(KnownTypeCode.String); + } + + bool IsCompatibleImplicitConversionOperator(IMethod operatorMethod) + { + if (!operatorMethod.IsOperator) + return false; + if (operatorMethod.Name != "op_Implicit") + return false; + if (operatorMethod.Parameters.Count != 1) + return false; + return IsCompatibleWithSwitch(operatorMethod.ReturnType); + } } protected internal override TranslatedExpression VisitSwitchInstruction(SwitchInstruction inst, TranslationContext context) { // switch-expression does not support implicit conversions - var (value, type, strToInt) = TranslateSwitchValue(inst, allowImplicitConversion: false); + var (value, type, strToInt) = TranslateSwitchValue(inst, true); IL.SwitchSection defaultSection = inst.GetDefaultSection(); SwitchExpression switchExpr = new SwitchExpression(); diff --git a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs index a806e8bb7..094a51355 100644 --- a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs @@ -210,7 +210,7 @@ namespace ICSharpCode.Decompiler.CSharp var oldCaseLabelMapping = caseLabelMapping; caseLabelMapping = new Dictionary(); - var (value, type, strToInt) = exprBuilder.TranslateSwitchValue(inst, allowImplicitConversion: true); + var (value, type, strToInt) = exprBuilder.TranslateSwitchValue(inst, false); IL.SwitchSection defaultSection = inst.GetDefaultSection(); From ee6d939478a40eb944c614c2b3b618e245665ec3 Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Mon, 6 Jan 2025 07:33:02 +0100 Subject: [PATCH 24/26] Package BamlDecompiler in CI --- .github/workflows/build-ilspy.yml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-ilspy.yml b/.github/workflows/build-ilspy.yml index f5edfdc97..d596d8fcb 100644 --- a/.github/workflows/build-ilspy.yml +++ b/.github/workflows/build-ilspy.yml @@ -158,7 +158,20 @@ jobs: if: github.ref == 'refs/heads/master' && matrix.configuration == 'release' run: | dotnet nuget push "ICSharpCode.ILSpyX\bin\Release\ICSharpCode.ILSpyX*.nupkg" --api-key ${{ secrets.GITHUB_TOKEN }} --source https://nuget.pkg.github.com/${{ github.repository_owner }} - + + - name: Upload BamlDecompiler NuGet release build artifacts + if: matrix.configuration == 'release' + uses: actions/upload-artifact@v4 + with: + name: ICSharpCode.BamlDecompiler NuGet Package (${{ matrix.configuration }}) + path: ICSharpCode.BamlDecompiler\bin\Release\ICSharpCode.BamlDecompiler*.nupkg + if-no-files-found: error + + - name: Publish DecomBamlDecompilerpiler NuGet + if: github.ref == 'refs/heads/master' && matrix.configuration == 'release' + run: | + dotnet nuget push "ICSharpCode.BamlDecompiler\bin\Release\ICSharpCode.BamlDecompiler*.nupkg" --api-key ${{ secrets.GITHUB_TOKEN }} --source https://nuget.pkg.github.com/${{ github.repository_owner }} + - name: Upload zip binaries build artifacts uses: actions/upload-artifact@v4 with: From 1853439d1d53e608cf165107f621a65aba6f4deb Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Tue, 7 Jan 2025 18:51:28 +0100 Subject: [PATCH 25/26] Create scorecard.yml (#3362) * Create scorecard.yml, only enable workflow_dispatch --- .github/workflows/scorecard.yml | 47 +++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 .github/workflows/scorecard.yml diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml new file mode 100644 index 000000000..1ba02149a --- /dev/null +++ b/.github/workflows/scorecard.yml @@ -0,0 +1,47 @@ +name: Scorecard supply-chain security +on: + # For Branch-Protection check. Only the default branch is supported. See + # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection (disabled) + # branch_protection_rule: + workflow_dispatch: + + # schedule ("Maintained") and push are disabled atm + # schedule: + # - cron: '25 1 * * 2' + # push: + # branches: [ "master" ] + +permissions: read-all + +jobs: + analysis: + name: Scorecard analysis + runs-on: ubuntu-latest + permissions: + security-events: write # Needed to upload the results to code-scanning dashboard. + id-token: write # Needed to publish results and get a badge (see publish_results below). + + steps: + - name: "Checkout code" + uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1 + with: + results_file: results.sarif + results_format: sarif + publish_results: true + + - name: "Upload artifact" + uses: actions/upload-artifact@97a0fba1372883ab732affbe8f94b823f91727db # v3.pre.node20 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: results.sarif From e734f7122c7d5f8cb262b4d375c9826c2aa19416 Mon Sep 17 00:00:00 2001 From: Christoph Wille Date: Wed, 4 Dec 2024 19:22:04 +0100 Subject: [PATCH 26/26] Use https://github.com/microsoft/sbom-tool/tree/main/src/Microsoft.Sbom.Targets to embed SBOM in ICSharpCode.Decompiler NuGet --- ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index 5314bd4f7..d45e054ca 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -20,6 +20,7 @@ false Copyright 2011-$([System.DateTime]::Now.Year) AlphaSierraPapa C# Decompiler ILSpy + true en-US False @@ -80,6 +81,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + @@ -707,7 +712,7 @@ - + powershell -NoProfile -ExecutionPolicy Bypass -File BuildTools/update-assemblyinfo.ps1 $(Configuration) git rev-parse HEAD^^{commit} @@ -726,6 +731,7 @@ +