Skip to content

Will HelpBuilder.Default.GetLayout() return the same delegates as OptionsSection() etc.? #1888

Open
@KalleOlaviNiemitalo

Description

@KalleOlaviNiemitalo

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:

/// <summary>
/// Gets the default sections to be written for command line help.
/// </summary>
public static IEnumerable<HelpSectionDelegate> GetLayout()
{
yield return SynopsisSection();
yield return CommandUsageSection();
yield return CommandArgumentsSection();
yield return OptionsSection();
yield return SubcommandsSection();
yield return AdditionalArgumentsSection();
}

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:

public static HelpSectionDelegate OptionsSection() =>
ctx =>
{

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions