diff --git a/lldb/include/lldb/Interpreter/OptionGroupFormat.h b/lldb/include/lldb/Interpreter/OptionGroupFormat.h --- a/lldb/include/lldb/Interpreter/OptionGroupFormat.h +++ b/lldb/include/lldb/Interpreter/OptionGroupFormat.h @@ -16,6 +16,9 @@ namespace lldb_private { +typedef std::vector> + OptionGroupFormatUsageTextVector; + // OptionGroupFormat class OptionGroupFormat : public OptionGroup { @@ -30,7 +33,10 @@ uint64_t default_byte_size = UINT64_MAX, // Pass UINT64_MAX to disable the "--size" option uint64_t default_count = - UINT64_MAX); // Pass UINT64_MAX to disable the "--count" option + UINT64_MAX, // Pass UINT64_MAX to disable the "--count" option + OptionGroupFormatUsageTextVector usage_text_vector = {} + // Use to override default option usage text with the command specific one + ); ~OptionGroupFormat() override = default; @@ -73,6 +79,7 @@ char m_prev_gdb_format; char m_prev_gdb_size; bool m_has_gdb_format; + OptionDefinition m_option_definitions[4]; }; } // namespace lldb_private diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp --- a/lldb/source/Commands/CommandObjectMemory.cpp +++ b/lldb/source/Commands/CommandObjectMemory.cpp @@ -1222,7 +1222,15 @@ interpreter, "memory write", "Write to the memory of the current target process.", nullptr, eCommandRequiresProcess | eCommandProcessMustBeLaunched), - m_option_group(), m_format_options(eFormatBytes, 1, UINT64_MAX), + m_option_group(), + m_format_options( + eFormatBytes, 1, UINT64_MAX, + {std::make_tuple( + eArgTypeFormat, + "The format to use for each of the value to be written."), + std::make_tuple( + eArgTypeByteSize, + "The size in bytes to write from input file or each value.")}), m_memory_options() { CommandArgumentEntry arg1; CommandArgumentEntry arg2; diff --git a/lldb/source/Interpreter/OptionGroupFormat.cpp b/lldb/source/Interpreter/OptionGroupFormat.cpp --- a/lldb/source/Interpreter/OptionGroupFormat.cpp +++ b/lldb/source/Interpreter/OptionGroupFormat.cpp @@ -16,15 +16,7 @@ using namespace lldb; using namespace lldb_private; -OptionGroupFormat::OptionGroupFormat(lldb::Format default_format, - uint64_t default_byte_size, - uint64_t default_count) - : m_format(default_format, default_format), - m_byte_size(default_byte_size, default_byte_size), - m_count(default_count, default_count), m_prev_gdb_format('x'), - m_prev_gdb_size('w') {} - -static constexpr OptionDefinition g_option_table[] = { +static constexpr OptionDefinition g_default_option_definitions[] = { {LLDB_OPT_SET_1, false, "format", 'f', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFormat, "Specify a format to be used for display."}, @@ -39,8 +31,34 @@ "The number of total items to display."}, }; +OptionGroupFormat::OptionGroupFormat( + lldb::Format default_format, uint64_t default_byte_size, + uint64_t default_count, OptionGroupFormatUsageTextVector usage_text_vector) + : m_format(default_format, default_format), + m_byte_size(default_byte_size, default_byte_size), + m_count(default_count, default_count), m_prev_gdb_format('x'), + m_prev_gdb_size('w') { + // Copy the default option definitions. + std::copy(std::begin(g_default_option_definitions), + std::end(g_default_option_definitions), + std::begin(m_option_definitions)); + + for (auto usage_text_tuple : usage_text_vector) { + switch (std::get<0>(usage_text_tuple)) { + case eArgTypeFormat: + m_option_definitions[0].usage_text = std::get<1>(usage_text_tuple); + break; + case eArgTypeByteSize: + m_option_definitions[2].usage_text = std::get<1>(usage_text_tuple); + break; + default: + llvm_unreachable("Unimplemented option"); + } + } +} + llvm::ArrayRef OptionGroupFormat::GetDefinitions() { - auto result = llvm::makeArrayRef(g_option_table); + auto result = llvm::makeArrayRef(m_option_definitions); if (m_byte_size.GetDefaultValue() < UINT64_MAX) { if (m_count.GetDefaultValue() < UINT64_MAX) return result; @@ -54,7 +72,7 @@ llvm::StringRef option_arg, ExecutionContext *execution_context) { Status error; - const int short_option = g_option_table[option_idx].short_option; + const int short_option = m_option_definitions[option_idx].short_option; switch (short_option) { case 'f': diff --git a/lldb/test/API/commands/help/TestHelp.py b/lldb/test/API/commands/help/TestHelp.py --- a/lldb/test/API/commands/help/TestHelp.py +++ b/lldb/test/API/commands/help/TestHelp.py @@ -225,3 +225,21 @@ "help format", matching=True, substrs=[' -- One of the format names']) + + @no_debug_info_test + def test_help_option_group_format_options_usage(self): + """Test that help on commands that use OptionGroupFormat options provide relevant help specific to that command.""" + self.expect( + "help memory read", + matching=True, + substrs=[ + "-f ( --format )", "Specify a format to be used for display.", + "-s ( --size )", "The size in bytes to use when displaying with the selected format."]) + + self.expect( + "help memory write", + matching=True, + substrs=[ + "-f ( --format )", "The format to use for each of the value to be written.", + "-s ( --size )", "The size in bytes to write from input file or each value."]) +