Description
I want to add a custom help section after OptionsSection. As of System.CommandLine 2.0.0-beta4.22272.1, HelpBuilder.Default.GetLayout() returns the sections in this order:
command-line-api/src/System.CommandLine/Help/HelpBuilder.Default.cs
Lines 141 to 152 in 209b724
The documentation "Add or replace help sections" suggests using Enumerable.Skip, i.e. trusting that the positions of the sections never change, but that seems risky to me. If a future version of System.CommandLine adds a new section between SynopsisSection and CommandUsageSection, and I keep adding my section between the fourth and fifth default section, then my section will go above OptionsSection even though I want it to go below.
So, I'm considering this kind of code instead:
private static IEnumerable<HelpSectionDelegate> GetLayout(HelpContext helpContext)
{
var layout = new List<HelpSectionDelegate>(HelpBuilder.Default.GetLayout());
int index = layout.IndexOf(HelpBuilder.Default.OptionsSection());
layout.Insert(index + 1, ShowOptionDetails);
return layout;
}
i.e. locate the OptionsSection in the list and then insert after that. However, does the System.CommandLine API promise that this kind of search will find the delegate in the list? I mean, the list might contain a different delegate instance that does not compare equal to the delegate that HelpBuilder.Default.OptionsSection() returns, even though both delegates do the same thing. The OptionsSection() method returns a delegate constructed from an anonymous function:
command-line-api/src/System.CommandLine/Help/HelpBuilder.Default.cs
Lines 199 to 201 in 209b724
and ECMA-334:2022 §11.11.9 (Delegate equality operators) seems to say that invocation list entries constructed that way are not necessarily equal. So the questions are:
- Will future versions of System.CommandLine ensure that such a search keeps working?
- Is System.CommandLine relying on Roslyn implementation-specific behavior to keep the delegates equal?