From 8b26f2c0e94098e69950e4ce6cd78d0e7b1bbdf8 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Fri, 29 May 2026 08:18:51 +0200 Subject: [PATCH] Add "Add preconfigured list" to Manage Assembly Lists The dialog lost the entry point for building a preconfigured list when the view-model wasn't ported; the backing AssemblyListManager. CreateDefaultList was already present and cross-platform. Re-add the button and a flyout of the generated lists. The three GAC-based framework lists resolve nothing without a GAC, so they're only offered when a GAC directory exists (i.e. on Windows); the per-installed-runtime entries work everywhere. Assisted-by: Claude:claude-opus-4-8:Claude Code --- .../PreconfiguredAssemblyListTests.cs | 91 ++++++++++++++++ ILSpy/Views/ManageAssemblyListsDialog.axaml | 12 +- .../Views/ManageAssemblyListsDialog.axaml.cs | 103 ++++++++++++++++++ 3 files changed, 202 insertions(+), 4 deletions(-) create mode 100644 ILSpy.Tests/AssemblyList/PreconfiguredAssemblyListTests.cs diff --git a/ILSpy.Tests/AssemblyList/PreconfiguredAssemblyListTests.cs b/ILSpy.Tests/AssemblyList/PreconfiguredAssemblyListTests.cs new file mode 100644 index 000000000..c976f0f99 --- /dev/null +++ b/ILSpy.Tests/AssemblyList/PreconfiguredAssemblyListTests.cs @@ -0,0 +1,91 @@ +// Copyright (c) 2026 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.Linq; + +using Avalonia.Headless.NUnit; + +using AwesomeAssertions; + +using ICSharpCode.ILSpyX; + +using ILSpy; +using ILSpy.AppEnv; +using ILSpy.Views; + +using NUnit.Framework; + +namespace ICSharpCode.ILSpy.Tests; + +[TestFixture] +public class PreconfiguredAssemblyListTests +{ + [AvaloniaTest] + public void Preconfigured_Menu_Offers_Installed_Runtimes_And_Creates_A_Populated_List() + { + // The "Add preconfigured list..." menu resolves one entry per installed .NET runtime + // (discovered under the dotnet install's shared folder) on every platform, and + // selecting one builds a populated assembly list via the shared AssemblyListManager. + + var settingsService = AppComposition.Current.GetExport(); + var manager = settingsService.AssemblyListManager; + var dialog = new ManageAssemblyListsDialog(settingsService); + + var configs = dialog.GetPreconfiguredAssemblyLists().ToList(); + + // At least one runtime-path entry must be discovered (ILSpy itself runs on one). + var runtimeEntry = configs.FirstOrDefault(c => c.Path != null); + ((object?)runtimeEntry).Should().NotBeNull( + "the running machine has at least one installed .NET runtime to offer"); + + var newName = "Preconfigured Test " + System.Guid.NewGuid().ToString("N"); + manager.AssemblyLists.Should().NotContain(newName); + + var created = dialog.CreatePreconfiguredList(runtimeEntry!, newName); + + ((object?)created).Should().NotBeNull("a runtime directory resolves to a non-empty list"); + created!.Count.Should().BeGreaterThan(0, "the runtime's framework assemblies populate the list"); + manager.AssemblyLists.Should().Contain(newName, "the new preconfigured list is registered"); + } + + [AvaloniaTest] + public void Preconfigured_Menu_Hides_Gac_Lists_When_No_Gac_Is_Present() + { + // The three GAC-based framework lists (.NET 4.x / 3.5 / ASP.NET MVC) resolve nothing on + // platforms without a GAC, so they are only offered when a GAC directory actually + // exists (i.e. on Windows). On a GAC-less host they must not appear. + var settingsService = AppComposition.Current.GetExport(); + var dialog = new ManageAssemblyListsDialog(settingsService); + + var names = dialog.GetPreconfiguredAssemblyLists().Select(c => c.Name).ToList(); + + bool gacPresent = ICSharpCode.Decompiler.Metadata.UniversalAssemblyResolver + .GetGacPaths().Any(System.IO.Directory.Exists); + + if (gacPresent) + { + names.Should().Contain(AssemblyListManager.DotNet4List); + } + else + { + names.Should().NotContain(AssemblyListManager.DotNet4List); + names.Should().NotContain(AssemblyListManager.DotNet35List); + names.Should().NotContain(AssemblyListManager.ASPDotNetMVC3List); + } + } +} diff --git a/ILSpy/Views/ManageAssemblyListsDialog.axaml b/ILSpy/Views/ManageAssemblyListsDialog.axaml index eb92e7ff8..55db36634 100644 --- a/ILSpy/Views/ManageAssemblyListsDialog.axaml +++ b/ILSpy/Views/ManageAssemblyListsDialog.axaml @@ -13,9 +13,13 @@