Preserve reporting flag occurrence order

This commit is contained in:
2026-10-26 02:55:08 +00:00
parent f3bd6dc2ae
commit df21b75f9c
7 changed files with 320 additions and 19 deletions

View File

@@ -32,6 +32,74 @@ func flagGrammarOptions() ParseOptions {
}}
}
func reportingFlagTree() *commandmeta.Command {
return &commandmeta.Command{Name: "app", Children: []*commandmeta.Command{{
Name: "run", Runnable: true, CoreFlags: commandmeta.ReportingFlags(),
Flags: []commandmeta.Flag{{Name: "message"}},
}}}
}
func reportingFlagOptions() ParseOptions {
return ParseOptions{FlagAliases: []commandmeta.FlagAlias{
{Source: "-q", Target: "--quiet"},
{Source: "-v", Target: "--verbose"},
{Source: "-d", Target: "--debug"},
}}
}
func TestParseReportsFlagOccurrencesInEnteredOrder(t *testing.T) {
result := Parse(reportingFlagTree(), []string{
"run", "--verbose=true", "-qd", "--progress=false", "--message=--quiet", "--", "--debug",
}, reportingFlagOptions())
if result.Failure != nil {
t.Fatalf("parse failed: %s", result.Failure.Message)
}
want := []commandmeta.FlagOccurrence{
{Name: "verbose", Spelling: "--verbose", RawValue: "true"},
{Name: "quiet", Spelling: "-q", RawValue: "true"},
{Name: "debug", Spelling: "-d", RawValue: "true"},
{Name: "progress", Spelling: "--progress", RawValue: "false"},
{Name: "message", Spelling: "--message", RawValue: "--quiet"},
}
if !reflect.DeepEqual(result.FlagOccurrences, want) {
t.Fatalf("flag occurrences = %#v, want %#v", result.FlagOccurrences, want)
}
if !reflect.DeepEqual(result.FlagValues, [][]string{{"--quiet"}}) || !reflect.DeepEqual(result.FlagSpellings, [][]string{{"--message"}}) {
t.Fatalf("consumer values or spellings changed: %#v, %#v", result.FlagValues, result.FlagSpellings)
}
}
func TestParseFlagOccurrencesRetainOnlyConsumedPrefixOnFailure(t *testing.T) {
result := Parse(reportingFlagTree(), []string{"run", "--verbose", "--unknown", "--quiet"}, reportingFlagOptions())
if result.Failure == nil || len(result.FlagOccurrences) != 1 || result.FlagOccurrences[0].Name != "verbose" {
t.Fatalf("unknown flag result = %#v", result)
}
result = Parse(reportingFlagTree(), []string{"run", "-qd", "--message"}, reportingFlagOptions())
if result.Failure == nil || len(result.FlagOccurrences) != 2 || result.FlagOccurrences[0].Name != "quiet" || result.FlagOccurrences[1].Name != "debug" {
t.Fatalf("missing value result = %#v", result)
}
result = Parse(reportingFlagTree(), []string{"missing", "--quiet"}, reportingFlagOptions())
if result.Failure == nil || len(result.FlagOccurrences) != 0 {
t.Fatalf("malformed path result = %#v", result)
}
}
func TestParseFlagOccurrenceKeepsOptionLookingValueAndConsumesTerminator(t *testing.T) {
result := Parse(reportingFlagTree(), []string{"run", "--message", "--quiet", "--", "--verbose"}, reportingFlagOptions())
if result.Failure != nil {
t.Fatalf("parse failed: %s", result.Failure.Message)
}
want := []commandmeta.FlagOccurrence{{Name: "message", Spelling: "--message", RawValue: "--quiet"}}
if !reflect.DeepEqual(result.FlagOccurrences, want) {
t.Fatalf("flag occurrences = %#v, want %#v", result.FlagOccurrences, want)
}
if !reflect.DeepEqual(result.Operands, []string{"--verbose"}) {
t.Fatalf("operands = %#v", result.Operands)
}
}
func TestParseCanonicalAndAliasShortGrammar(t *testing.T) {
for _, test := range []struct {
name string