From 217a9fc29a97210d23c861d4f90b1df2c69c8f4e Mon Sep 17 00:00:00 2001 From: Ian Cottrell Date: Wed, 24 Nov 2021 16:41:22 -0500 Subject: [PATCH] gopls: take control of the flag printing Add a copy of flag.PrintDefaults so that we can make changes. This CL does not actually modify anything (although it does have to detect the private stringValue type a slightly different way) For #41860 Change-Id: I19512041f9c1bfde56226aea48302cd63cf670e2 Reviewed-on: https://go-review.googlesource.com/c/tools/+/367837 Trust: Ian Cottrell Run-TryBot: Ian Cottrell Reviewed-by: Robert Findley gopls-CI: kokoro TryBot-Result: Gopher Robot --- internal/lsp/cmd/call_hierarchy.go | 2 +- internal/lsp/cmd/check.go | 2 +- internal/lsp/cmd/cmd.go | 49 +++++++++++++++++++++++++++- internal/lsp/cmd/definition.go | 2 +- internal/lsp/cmd/folding_range.go | 2 +- internal/lsp/cmd/format.go | 2 +- internal/lsp/cmd/highlight.go | 2 +- internal/lsp/cmd/implementation.go | 2 +- internal/lsp/cmd/imports.go | 2 +- internal/lsp/cmd/info.go | 8 ++--- internal/lsp/cmd/links.go | 2 +- internal/lsp/cmd/prepare_rename.go | 2 +- internal/lsp/cmd/references.go | 2 +- internal/lsp/cmd/remote.go | 4 +-- internal/lsp/cmd/rename.go | 2 +- internal/lsp/cmd/semantictokens.go | 2 +- internal/lsp/cmd/serve.go | 2 +- internal/lsp/cmd/signature.go | 2 +- internal/lsp/cmd/subcommands.go | 2 +- internal/lsp/cmd/suggested_fix.go | 2 +- internal/lsp/cmd/symbols.go | 2 +- internal/lsp/cmd/workspace.go | 2 +- internal/lsp/cmd/workspace_symbol.go | 2 +- 23 files changed, 74 insertions(+), 27 deletions(-) diff --git a/internal/lsp/cmd/call_hierarchy.go b/internal/lsp/cmd/call_hierarchy.go index 3ab925ef4bf..c9f9e73e0e2 100644 --- a/internal/lsp/cmd/call_hierarchy.go +++ b/internal/lsp/cmd/call_hierarchy.go @@ -32,7 +32,7 @@ Example: $ gopls call_hierarchy helper/helper.go:8:6 $ gopls call_hierarchy helper/helper.go:#53 `) - f.PrintDefaults() + printFlagDefaults(f) } func (c *callHierarchy) Run(ctx context.Context, args ...string) error { diff --git a/internal/lsp/cmd/check.go b/internal/lsp/cmd/check.go index bd8cb6fa141..566924aa635 100644 --- a/internal/lsp/cmd/check.go +++ b/internal/lsp/cmd/check.go @@ -28,7 +28,7 @@ Example: show the diagnostic results of this file: $ gopls check internal/lsp/cmd/check.go `) - f.PrintDefaults() + printFlagDefaults(f) } // Run performs the check on the files specified by args and prints the diff --git a/internal/lsp/cmd/cmd.go b/internal/lsp/cmd/cmd.go index 629a5e0199c..e23bca45e53 100644 --- a/internal/lsp/cmd/cmd.go +++ b/internal/lsp/cmd/cmd.go @@ -15,6 +15,7 @@ import ( "io/ioutil" "log" "os" + "reflect" "strings" "sync" "text/tabwriter" @@ -132,7 +133,53 @@ command: fmt.Fprintf(w, " %s\t%s\n", c.Name(), c.ShortHelp()) } fmt.Fprint(w, "\nflags:\n") - f.PrintDefaults() + printFlagDefaults(f) +} + +// this is a slightly modified version of flag.PrintDefaults to give us control +func printFlagDefaults(s *flag.FlagSet) { + s.VisitAll(func(f *flag.Flag) { + var b strings.Builder + fmt.Fprintf(&b, " -%s", f.Name) // Two spaces before -; see next two comments. + name, usage := flag.UnquoteUsage(f) + if len(name) > 0 { + b.WriteString(" ") + b.WriteString(name) + } + // Boolean flags of one ASCII letter are so common we + // treat them specially, putting their usage on the same line. + if b.Len() <= 4 { // space, space, '-', 'x'. + b.WriteString("\t") + } else { + // Four spaces before the tab triggers good alignment + // for both 4- and 8-space tab stops. + b.WriteString("\n \t") + } + b.WriteString(strings.ReplaceAll(usage, "\n", "\n \t")) + if !isZeroValue(f, f.DefValue) { + if reflect.TypeOf(f.Value).Elem().Name() == "stringValue" { + fmt.Fprintf(&b, " (default %q)", f.DefValue) + } else { + fmt.Fprintf(&b, " (default %v)", f.DefValue) + } + } + fmt.Fprint(s.Output(), b.String(), "\n") + }) +} + +// isZeroValue is copied from the flags package +func isZeroValue(f *flag.Flag, value string) bool { + // Build a zero value of the flag's Value type, and see if the + // result of calling its String method equals the value passed in. + // This works unless the Value type is itself an interface type. + typ := reflect.TypeOf(f.Value) + var z reflect.Value + if typ.Kind() == reflect.Ptr { + z = reflect.New(typ.Elem()) + } else { + z = reflect.Zero(typ) + } + return value == z.Interface().(flag.Value).String() } // Run takes the args after top level flag processing, and invokes the correct diff --git a/internal/lsp/cmd/definition.go b/internal/lsp/cmd/definition.go index d147fa4a7be..f3c71b671f7 100644 --- a/internal/lsp/cmd/definition.go +++ b/internal/lsp/cmd/definition.go @@ -55,7 +55,7 @@ Example: show the definition of the identifier at syntax at offset %[1]v in this definition-flags: `, exampleLine, exampleColumn, exampleOffset) - f.PrintDefaults() + printFlagDefaults(f) } // Run performs the definition query as specified by args and prints the diff --git a/internal/lsp/cmd/folding_range.go b/internal/lsp/cmd/folding_range.go index 584a39f5a1b..513c9bdd227 100644 --- a/internal/lsp/cmd/folding_range.go +++ b/internal/lsp/cmd/folding_range.go @@ -29,7 +29,7 @@ Example: $ gopls folding_ranges helper/helper.go `) - f.PrintDefaults() + printFlagDefaults(f) } func (r *foldingRanges) Run(ctx context.Context, args ...string) error { diff --git a/internal/lsp/cmd/format.go b/internal/lsp/cmd/format.go index 1a8db1780be..458df5d1e91 100644 --- a/internal/lsp/cmd/format.go +++ b/internal/lsp/cmd/format.go @@ -40,7 +40,7 @@ Example: reformat this file: format-flags: `) - f.PrintDefaults() + printFlagDefaults(f) } // Run performs the check on the files specified by args and prints the diff --git a/internal/lsp/cmd/highlight.go b/internal/lsp/cmd/highlight.go index 31ca6f2cda6..a325a2d53d9 100644 --- a/internal/lsp/cmd/highlight.go +++ b/internal/lsp/cmd/highlight.go @@ -32,7 +32,7 @@ Example: $ gopls highlight helper/helper.go:8:6 $ gopls highlight helper/helper.go:#53 `) - f.PrintDefaults() + printFlagDefaults(f) } func (r *highlight) Run(ctx context.Context, args ...string) error { diff --git a/internal/lsp/cmd/implementation.go b/internal/lsp/cmd/implementation.go index 4c688c6dfed..7b42d994303 100644 --- a/internal/lsp/cmd/implementation.go +++ b/internal/lsp/cmd/implementation.go @@ -32,7 +32,7 @@ Example: $ gopls implementation helper/helper.go:8:6 $ gopls implementation helper/helper.go:#53 `) - f.PrintDefaults() + printFlagDefaults(f) } func (i *implementation) Run(ctx context.Context, args ...string) error { diff --git a/internal/lsp/cmd/imports.go b/internal/lsp/cmd/imports.go index 10e1082da6e..405e279b769 100644 --- a/internal/lsp/cmd/imports.go +++ b/internal/lsp/cmd/imports.go @@ -38,7 +38,7 @@ Example: update imports statements in a file: imports-flags: `) - f.PrintDefaults() + printFlagDefaults(f) } // Run performs diagnostic checks on the file specified and either; diff --git a/internal/lsp/cmd/info.go b/internal/lsp/cmd/info.go index 5622c2ce2e4..2dc8fb57eb9 100644 --- a/internal/lsp/cmd/info.go +++ b/internal/lsp/cmd/info.go @@ -30,7 +30,7 @@ func (v *version) Usage() string { return "" } func (v *version) ShortHelp() string { return "print the gopls version information" } func (v *version) DetailedHelp(f *flag.FlagSet) { fmt.Fprint(f.Output(), ``) - f.PrintDefaults() + printFlagDefaults(f) } // Run prints version information to stdout. @@ -50,7 +50,7 @@ func (b *bug) Usage() string { return "" } func (b *bug) ShortHelp() string { return "report a bug in gopls" } func (b *bug) DetailedHelp(f *flag.FlagSet) { fmt.Fprint(f.Output(), ``) - f.PrintDefaults() + printFlagDefaults(f) } const goplsBugPrefix = "x/tools/gopls: " @@ -98,7 +98,7 @@ func (j *apiJSON) Usage() string { return "" } func (j *apiJSON) ShortHelp() string { return "print json describing gopls API" } func (j *apiJSON) DetailedHelp(f *flag.FlagSet) { fmt.Fprint(f.Output(), ``) - f.PrintDefaults() + printFlagDefaults(f) } func (j *apiJSON) Run(ctx context.Context, args ...string) error { @@ -120,7 +120,7 @@ func (l *licenses) Usage() string { return "" } func (l *licenses) ShortHelp() string { return "print licenses of included software" } func (l *licenses) DetailedHelp(f *flag.FlagSet) { fmt.Fprint(f.Output(), ``) - f.PrintDefaults() + printFlagDefaults(f) } const licensePreamble = ` diff --git a/internal/lsp/cmd/links.go b/internal/lsp/cmd/links.go index 2196698fa21..d49aabb6f8f 100644 --- a/internal/lsp/cmd/links.go +++ b/internal/lsp/cmd/links.go @@ -36,7 +36,7 @@ Example: list links contained within a file: links-flags: `) - f.PrintDefaults() + printFlagDefaults(f) } // Run finds all the links within a document diff --git a/internal/lsp/cmd/prepare_rename.go b/internal/lsp/cmd/prepare_rename.go index 58d90c3129f..e1ae4139aa4 100644 --- a/internal/lsp/cmd/prepare_rename.go +++ b/internal/lsp/cmd/prepare_rename.go @@ -32,7 +32,7 @@ Example: $ gopls prepare_rename helper/helper.go:8:6 $ gopls prepare_rename helper/helper.go:#53 `) - f.PrintDefaults() + printFlagDefaults(f) } // ErrInvalidRenamePosition is returned when prepareRename is run at a position that diff --git a/internal/lsp/cmd/references.go b/internal/lsp/cmd/references.go index 4a452c5db4f..d3e10516935 100644 --- a/internal/lsp/cmd/references.go +++ b/internal/lsp/cmd/references.go @@ -36,7 +36,7 @@ Example: references-flags: `) - f.PrintDefaults() + printFlagDefaults(f) } func (r *references) Run(ctx context.Context, args ...string) error { diff --git a/internal/lsp/cmd/remote.go b/internal/lsp/cmd/remote.go index b6ab7f4bcc2..f71113576df 100644 --- a/internal/lsp/cmd/remote.go +++ b/internal/lsp/cmd/remote.go @@ -85,7 +85,7 @@ $ gopls -remote=localhost:8082 remote sessions func (c *listSessions) DetailedHelp(f *flag.FlagSet) { fmt.Fprint(f.Output(), listSessionsExamples) - f.PrintDefaults() + printFlagDefaults(f) } func (c *listSessions) Run(ctx context.Context, args ...string) error { @@ -131,7 +131,7 @@ $ gopls -remote=localhost:8082 remote debug localhost:8083 func (c *startDebugging) DetailedHelp(f *flag.FlagSet) { fmt.Fprint(f.Output(), startDebuggingExamples) - f.PrintDefaults() + printFlagDefaults(f) } func (c *startDebugging) Run(ctx context.Context, args ...string) error { diff --git a/internal/lsp/cmd/rename.go b/internal/lsp/cmd/rename.go index 12e3ac398c8..819106295d5 100644 --- a/internal/lsp/cmd/rename.go +++ b/internal/lsp/cmd/rename.go @@ -44,7 +44,7 @@ Example: rename-flags: `) - f.PrintDefaults() + printFlagDefaults(f) } // Run renames the specified identifier and either; diff --git a/internal/lsp/cmd/semantictokens.go b/internal/lsp/cmd/semantictokens.go index 0cb1270dd66..120f91d3692 100644 --- a/internal/lsp/cmd/semantictokens.go +++ b/internal/lsp/cmd/semantictokens.go @@ -61,7 +61,7 @@ Example: show the semantic tokens for this file: $ gopls semtok internal/lsp/cmd/semtok.go `) - f.PrintDefaults() + printFlagDefaults(f) } // Run performs the semtok on the files specified by args and prints the diff --git a/internal/lsp/cmd/serve.go b/internal/lsp/cmd/serve.go index 152ee6dad66..e47d71f1125 100644 --- a/internal/lsp/cmd/serve.go +++ b/internal/lsp/cmd/serve.go @@ -54,7 +54,7 @@ a child of an editor process. server-flags: `) - f.PrintDefaults() + printFlagDefaults(f) } func (s *Serve) remoteArgs(network, address string) []string { diff --git a/internal/lsp/cmd/signature.go b/internal/lsp/cmd/signature.go index 8db7ca7b43d..db948430183 100644 --- a/internal/lsp/cmd/signature.go +++ b/internal/lsp/cmd/signature.go @@ -31,7 +31,7 @@ Example: $ gopls signature helper/helper.go:8:6 $ gopls signature helper/helper.go:#53 `) - f.PrintDefaults() + printFlagDefaults(f) } func (r *signature) Run(ctx context.Context, args ...string) error { diff --git a/internal/lsp/cmd/subcommands.go b/internal/lsp/cmd/subcommands.go index 1903c920771..e4045fb0077 100644 --- a/internal/lsp/cmd/subcommands.go +++ b/internal/lsp/cmd/subcommands.go @@ -24,7 +24,7 @@ func (s subcommands) DetailedHelp(f *flag.FlagSet) { for _, c := range s { fmt.Fprintf(w, " %s\t%s\n", c.Name(), c.ShortHelp()) } - f.PrintDefaults() + printFlagDefaults(f) } func (s subcommands) Usage() string { return " [arg]..." } diff --git a/internal/lsp/cmd/suggested_fix.go b/internal/lsp/cmd/suggested_fix.go index c99e4d07167..932335457b4 100644 --- a/internal/lsp/cmd/suggested_fix.go +++ b/internal/lsp/cmd/suggested_fix.go @@ -38,7 +38,7 @@ Example: apply suggested fixes for this file fix-flags: `) - f.PrintDefaults() + printFlagDefaults(f) } // Run performs diagnostic checks on the file specified and either; diff --git a/internal/lsp/cmd/symbols.go b/internal/lsp/cmd/symbols.go index 2549cacdd50..b43a6dcd1f7 100644 --- a/internal/lsp/cmd/symbols.go +++ b/internal/lsp/cmd/symbols.go @@ -30,7 +30,7 @@ func (r *symbols) DetailedHelp(f *flag.FlagSet) { Example: $ gopls symbols helper/helper.go `) - f.PrintDefaults() + printFlagDefaults(f) } func (r *symbols) Run(ctx context.Context, args ...string) error { if len(args) != 1 { diff --git a/internal/lsp/cmd/workspace.go b/internal/lsp/cmd/workspace.go index 03a6e411222..c0ddd9eb46e 100644 --- a/internal/lsp/cmd/workspace.go +++ b/internal/lsp/cmd/workspace.go @@ -51,7 +51,7 @@ func (c *generateWorkspaceMod) ShortHelp() string { } func (c *generateWorkspaceMod) DetailedHelp(f *flag.FlagSet) { - f.PrintDefaults() + printFlagDefaults(f) } func (c *generateWorkspaceMod) Run(ctx context.Context, args ...string) error { diff --git a/internal/lsp/cmd/workspace_symbol.go b/internal/lsp/cmd/workspace_symbol.go index fdbe4c4f506..38fe5decf7f 100644 --- a/internal/lsp/cmd/workspace_symbol.go +++ b/internal/lsp/cmd/workspace_symbol.go @@ -33,7 +33,7 @@ Example: workspace_symbol-flags: `) - f.PrintDefaults() + printFlagDefaults(f) } func (r *workspaceSymbol) Run(ctx context.Context, args ...string) error {