Skip to content

Commit

Permalink
flag: test IsBoolFlag when creating the usage message
Browse files Browse the repository at this point in the history
Although I can't think of any reason to do this, it is possible for
a user-defined flag to implement IsBoolFlag but return "false".
This is nuts because checking the interface is satisfied should
obviously be sufficient, but the documentation kinda implies it's
not. And if you try this, you'll discover that the usage message
ignores the return value even though the rest of the package plays
nice. Bother.

So we fix it, as the fix is trivial: call the method when creating
the usage message.

Fixes #53473

Change-Id: I1ac80a876ad5626eebfc5ef6cb972cd3007afaad
Reviewed-on: https://go-review.googlesource.com/c/go/+/431102
Reviewed-by: Cherry Mui <[email protected]>
Run-TryBot: Ian Lance Taylor <[email protected]>
TryBot-Result: Gopher Robot <[email protected]>
Reviewed-by: Ian Lance Taylor <[email protected]>
  • Loading branch information
robpike committed Sep 19, 2022
1 parent d31f850 commit 2d74194
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 2 deletions.
6 changes: 4 additions & 2 deletions src/flag/flag.go
Original file line number Diff line number Diff line change
Expand Up @@ -550,9 +550,11 @@ func UnquoteUsage(flag *Flag) (name string, usage string) {
}
// No explicit name, so use type if we can find one.
name = "value"
switch flag.Value.(type) {
switch fv := flag.Value.(type) {
case boolFlag:
name = ""
if fv.IsBoolFlag() {
name = ""
}
case *durationValue:
name = "duration"
case *float64Value:
Expand Down
26 changes: 26 additions & 0 deletions src/flag/flag_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package flag_test

import (
"bytes"
. "flag"
"fmt"
"internal/testenv"
Expand Down Expand Up @@ -355,6 +356,31 @@ func TestUserDefinedBool(t *testing.T) {
}
}

func TestUserDefinedBoolUsage(t *testing.T) {
var flags FlagSet
flags.Init("test", ContinueOnError)
var buf bytes.Buffer
flags.SetOutput(&buf)
var b boolFlagVar
flags.Var(&b, "b", "X")
b.count = 0
// b.IsBoolFlag() will return true and usage will look boolean.
flags.PrintDefaults()
got := buf.String()
want := " -b\tX\n"
if got != want {
t.Errorf("false: want %q; got %q", want, got)
}
b.count = 4
// b.IsBoolFlag() will return false and usage will look non-boolean.
flags.PrintDefaults()
got = buf.String()
want = " -b\tX\n -b value\n \tX\n"
if got != want {
t.Errorf("false: want %q; got %q", want, got)
}
}

func TestSetOutput(t *testing.T) {
var flags FlagSet
var buf strings.Builder
Expand Down

0 comments on commit 2d74194

Please sign in to comment.