Browse Source

Re-group File menu so DEBUG items aren't mixed with assembly loading

The File menu's MenuCategory metadata was inherited from the WPF tree
and showed two friction points: the four DEBUG diagnostics
(Decompile All / Disassemble All / Decompile 100x / Dump PDB) lived
in the Open category, so they appeared right after Reload with no
visual separator -- the menu read as if Decompile All was a variant
of Open; and the assembly-list mutators (Remove with load errors,
Clear assembly list, Manage assembly lists) were split across two
categories (Remove and Open) even though they all operate on the
same object.

Reshape into five categories with non-overlapping MenuOrder ranges
so category order is deterministic instead of falling out of MEF
discovery order:

  Open         (Open, GAC, Reload)              MenuOrder 0 .. 9
  AssemblyList (Manage, Remove, Clear)          MenuOrder 10 .. 19
  Save         (Save Code, Generate PDB)        MenuOrder 20 .. 29
  Debug        (DEBUG -- ...)                   MenuOrder 30 .. 39
  Exit         (Exit)                           MenuOrder 99999

The "AssemblyList" category replaces the previous "Remove" identifier
(carrying Remove-with-load-errors + Clear) since both members and the
newly-relocated Manage entry are list-of-assemblies operations rather
than pure removal. The category value is a string literal because it
is only ever used as a grouping key by ContextMenuProvider /
MainMenu.AppendRegistryCommands -- never displayed.

Stride-10 within each category gives room to insert later items
without renumbering. The earlier 2.5 / 2.55 / 2.6 / 2.7 fractional
scheme had no category-boundary contract: the existing 2.6 tie
between Remove-with-load-errors and Clear meant their order between
each other depended on whatever order reflection enumerated the
fields in. Generate portable PDB previously had no MenuOrder at all
so its position relative to Save Code was MEF-implementation defined.

Assisted-by: Claude:claude-opus-4-7:Claude Code
pull/3755/head
Siegfried Pammer 1 month ago
parent
commit
9427f76616
  1. 6
      ILSpy/Commands/DecompileAllCommand.cs
  2. 10
      ILSpy/Commands/FileCommands.cs
  3. 2
      ILSpy/Commands/Pdb2XmlCommand.cs

6
ILSpy/Commands/DecompileAllCommand.cs

@ -43,7 +43,7 @@ namespace ILSpy.Commands @@ -43,7 +43,7 @@ namespace ILSpy.Commands
/// timing in a results tab. Hard-coded output path matches WPF — the command's
/// CanExecute gates on that directory existing so it's effectively opt-in.
/// </summary>
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.DEBUGDecompile), MenuCategory = nameof(Resources.Open), MenuOrder = 2.5)]
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.DEBUGDecompile), MenuCategory = "Debug", MenuOrder = 30)]
[Shared]
sealed class DecompileAllCommand : SimpleCommand
{
@ -114,7 +114,7 @@ namespace ILSpy.Commands @@ -114,7 +114,7 @@ namespace ILSpy.Commands
/// <see cref="DecompileAllCommand"/> but routes through <see cref="ILLanguage"/>.
/// CanExecute gates on the output directory existing.
/// </summary>
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.DEBUGDisassemble), MenuCategory = nameof(Resources.Open), MenuOrder = 2.55)]
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.DEBUGDisassemble), MenuCategory = "Debug", MenuOrder = 31)]
[Shared]
sealed class DisassembleAllCommand : SimpleCommand
{
@ -185,7 +185,7 @@ namespace ILSpy.Commands @@ -185,7 +185,7 @@ namespace ILSpy.Commands
/// and report average wall-clock time. Used for tracking decompilation perf
/// regressions across changes.
/// </summary>
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.DEBUGDecompile100x), MenuCategory = nameof(Resources.Open), MenuOrder = 2.6)]
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.DEBUGDecompile100x), MenuCategory = "Debug", MenuOrder = 32)]
[Shared]
sealed class Decompile100TimesCommand : SimpleCommand
{

10
ILSpy/Commands/FileCommands.cs

@ -124,7 +124,7 @@ namespace ILSpy.Commands @@ -124,7 +124,7 @@ namespace ILSpy.Commands
}
}
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.ManageAssembly_Lists), MenuIcon = "Images/AssemblyList", MenuCategory = nameof(Resources.Open), MenuOrder = 1.7)]
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.ManageAssembly_Lists), MenuIcon = "Images/AssemblyList", MenuCategory = "AssemblyList", MenuOrder = 10)]
[Shared]
sealed class ManageAssemblyListsCommand : SimpleCommand
{
@ -165,7 +165,7 @@ namespace ILSpy.Commands @@ -165,7 +165,7 @@ namespace ILSpy.Commands
// DEBUG-only Pdb2XmlCommand moved to its own file with `#if DEBUG && WINDOWS` gating.
// On non-Windows or non-Debug builds the entry simply isn't compiled.
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources._RemoveAssembliesWithLoadErrors), MenuCategory = nameof(Resources.Remove), MenuOrder = 2.6)]
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources._RemoveAssembliesWithLoadErrors), MenuCategory = "AssemblyList", MenuOrder = 11)]
[Shared]
[method: ImportingConstructor]
sealed class RemoveAssembliesWithLoadErrors(AssemblyTreeModel assemblyTreeModel) : SimpleCommand
@ -186,7 +186,7 @@ namespace ILSpy.Commands @@ -186,7 +186,7 @@ namespace ILSpy.Commands
}
}
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.ClearAssemblyList), MenuCategory = nameof(Resources.Remove), MenuOrder = 2.6)]
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.ClearAssemblyList), MenuCategory = "AssemblyList", MenuOrder = 12)]
[Shared]
[method: ImportingConstructor]
sealed class ClearAssemblyListCommand(AssemblyTreeModel assemblyTreeModel) : SimpleCommand
@ -197,7 +197,7 @@ namespace ILSpy.Commands @@ -197,7 +197,7 @@ namespace ILSpy.Commands
public override void Execute(object? parameter) => assemblyTreeModel.AssemblyList?.Clear();
}
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources._SaveCode), MenuIcon = "Images/Save", MenuCategory = nameof(Resources.Save), MenuOrder = 0, InputGestureText = "Ctrl+S")]
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources._SaveCode), MenuIcon = "Images/Save", MenuCategory = nameof(Resources.Save), MenuOrder = 20, InputGestureText = "Ctrl+S")]
[Shared]
[method: ImportingConstructor]
internal sealed class SaveCommand(
@ -275,7 +275,7 @@ namespace ILSpy.Commands @@ -275,7 +275,7 @@ namespace ILSpy.Commands
}
}
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.GeneratePortable), MenuCategory = nameof(Resources.Save))]
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.GeneratePortable), MenuCategory = nameof(Resources.Save), MenuOrder = 21)]
[Shared]
sealed class GeneratePdbCommand : SimpleCommand
{

2
ILSpy/Commands/Pdb2XmlCommand.cs

@ -40,7 +40,7 @@ namespace ILSpy.Commands @@ -40,7 +40,7 @@ namespace ILSpy.Commands
/// <c>Microsoft.DiaSymReader</c> uses native COM interop. WPF gates this command
/// identically (<c>#if DEBUG &amp;&amp; WINDOWS</c>).
/// </summary>
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.DEBUGDumpPDBAsXML), MenuCategory = nameof(Resources.Open), MenuOrder = 2.7)]
[ExportMainMenuCommand(ParentMenuID = nameof(Resources._File), Header = nameof(Resources.DEBUGDumpPDBAsXML), MenuCategory = "Debug", MenuOrder = 33)]
[Shared]
sealed class Pdb2XmlCommand : SimpleCommand
{

Loading…
Cancel
Save