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
/// timing in a results tab. Hard-coded output path matches WPF — the command's /// 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. /// CanExecute gates on that directory existing so it's effectively opt-in.
/// </summary> /// </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] [Shared]
sealed class DecompileAllCommand : SimpleCommand sealed class DecompileAllCommand : SimpleCommand
{ {
@ -114,7 +114,7 @@ namespace ILSpy.Commands
/// <see cref="DecompileAllCommand"/> but routes through <see cref="ILLanguage"/>. /// <see cref="DecompileAllCommand"/> but routes through <see cref="ILLanguage"/>.
/// CanExecute gates on the output directory existing. /// CanExecute gates on the output directory existing.
/// </summary> /// </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] [Shared]
sealed class DisassembleAllCommand : SimpleCommand sealed class DisassembleAllCommand : SimpleCommand
{ {
@ -185,7 +185,7 @@ namespace ILSpy.Commands
/// and report average wall-clock time. Used for tracking decompilation perf /// and report average wall-clock time. Used for tracking decompilation perf
/// regressions across changes. /// regressions across changes.
/// </summary> /// </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] [Shared]
sealed class Decompile100TimesCommand : SimpleCommand sealed class Decompile100TimesCommand : SimpleCommand
{ {

10
ILSpy/Commands/FileCommands.cs

@ -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] [Shared]
sealed class ManageAssemblyListsCommand : SimpleCommand sealed class ManageAssemblyListsCommand : SimpleCommand
{ {
@ -165,7 +165,7 @@ namespace ILSpy.Commands
// DEBUG-only Pdb2XmlCommand moved to its own file with `#if DEBUG && WINDOWS` gating. // 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. // 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] [Shared]
[method: ImportingConstructor] [method: ImportingConstructor]
sealed class RemoveAssembliesWithLoadErrors(AssemblyTreeModel assemblyTreeModel) : SimpleCommand sealed class RemoveAssembliesWithLoadErrors(AssemblyTreeModel assemblyTreeModel) : SimpleCommand
@ -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] [Shared]
[method: ImportingConstructor] [method: ImportingConstructor]
sealed class ClearAssemblyListCommand(AssemblyTreeModel assemblyTreeModel) : SimpleCommand sealed class ClearAssemblyListCommand(AssemblyTreeModel assemblyTreeModel) : SimpleCommand
@ -197,7 +197,7 @@ namespace ILSpy.Commands
public override void Execute(object? parameter) => assemblyTreeModel.AssemblyList?.Clear(); 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] [Shared]
[method: ImportingConstructor] [method: ImportingConstructor]
internal sealed class SaveCommand( internal sealed class SaveCommand(
@ -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] [Shared]
sealed class GeneratePdbCommand : SimpleCommand sealed class GeneratePdbCommand : SimpleCommand
{ {

2
ILSpy/Commands/Pdb2XmlCommand.cs

@ -40,7 +40,7 @@ namespace ILSpy.Commands
/// <c>Microsoft.DiaSymReader</c> uses native COM interop. WPF gates this command /// <c>Microsoft.DiaSymReader</c> uses native COM interop. WPF gates this command
/// identically (<c>#if DEBUG &amp;&amp; WINDOWS</c>). /// identically (<c>#if DEBUG &amp;&amp; WINDOWS</c>).
/// </summary> /// </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] [Shared]
sealed class Pdb2XmlCommand : SimpleCommand sealed class Pdb2XmlCommand : SimpleCommand
{ {

Loading…
Cancel
Save