Index: lldb/trunk/include/lldb/Utility/Log.h =================================================================== --- lldb/trunk/include/lldb/Utility/Log.h +++ lldb/trunk/include/lldb/Utility/Log.h @@ -14,6 +14,7 @@ #include "lldb/lldb-defines.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" @@ -112,6 +113,14 @@ static bool ListChannelCategories(llvm::StringRef channel, llvm::raw_ostream &stream); + /// Returns the list of log channels. + static std::vector ListChannels(); + /// Calls the given lambda for every category in the given channel. + /// If no channel with the given name exists, lambda is never called. + static void ForEachChannelCategory( + llvm::StringRef channel, + llvm::function_ref lambda); + static void DisableAllLogChannels(); static void ListAllLogChannels(llvm::raw_ostream &stream); @@ -193,6 +202,10 @@ typedef llvm::StringMap ChannelMap; static llvm::ManagedStatic g_channel_map; + static void ForEachCategory( + const Log::ChannelMap::value_type &entry, + llvm::function_ref lambda); + static void ListCategories(llvm::raw_ostream &stream, const ChannelMap::value_type &entry); static uint32_t GetFlags(llvm::raw_ostream &stream, const ChannelMap::value_type &entry, Index: lldb/trunk/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py +++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/completion/TestCompletion.py @@ -102,6 +102,38 @@ self.complete_from_to('plugin load ', []) @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_log_enable(self): + self.completions_match('log enable ', + ['dwarf', + 'gdb-remote', + 'kdp-remote', + 'lldb']) + self.complete_from_to('log enable ll', ['lldb']) + self.complete_from_to('log enable lldb al', ['all']) + self.complete_from_to('log enable lldb sym', ['symbol']) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_log_enable(self): + self.completions_match('log disable ', + ['dwarf', + 'gdb-remote', + 'kdp-remote', + 'lldb']) + self.complete_from_to('log disable ll', ['lldb']) + self.complete_from_to('log disable lldb al', ['all']) + self.complete_from_to('log disable lldb sym', ['symbol']) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot + def test_log_list(self): + self.completions_match('log list ', + ['dwarf', + 'gdb-remote', + 'kdp-remote', + 'lldb']) + self.complete_from_to('log list ll', ['lldb']) + self.complete_from_to('log list lldb dwa', ['dwarf']) + + @skipIfFreeBSD # timing out on the FreeBSD buildbot def test_quoted_command(self): self.complete_from_to('"set', ['"settings" ']) Index: lldb/trunk/source/Commands/CommandObjectLog.cpp =================================================================== --- lldb/trunk/source/Commands/CommandObjectLog.cpp +++ lldb/trunk/source/Commands/CommandObjectLog.cpp @@ -34,6 +34,21 @@ #define LLDB_OPTIONS_log #include "CommandOptions.inc" +/// Common completion logic for log enable/disable. +static void CompleteEnableDisable(CompletionRequest &request) { + size_t arg_index = request.GetCursorIndex(); + if (arg_index == 0) { // We got: log enable/disable x[tab] + for (llvm::StringRef channel : Log::ListChannels()) + request.TryCompleteCurrentArg(channel); + } else if (arg_index >= 1) { // We got: log enable/disable channel x[tab] + llvm::StringRef channel = request.GetParsedLine().GetArgumentAtIndex(0); + Log::ForEachChannelCategory( + channel, [&request](llvm::StringRef name, llvm::StringRef desc) { + request.TryCompleteCurrentArg(name, desc); + }); + } +} + class CommandObjectLogEnable : public CommandObjectParsed { public: // Constructors and Destructors @@ -134,6 +149,12 @@ uint32_t log_options; }; + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { + CompleteEnableDisable(request); + } + protected: bool DoExecute(Args &args, CommandReturnObject &result) override { if (args.GetArgumentCount() < 2) { @@ -202,6 +223,12 @@ ~CommandObjectLogDisable() override = default; + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { + CompleteEnableDisable(request); + } + protected: bool DoExecute(Args &args, CommandReturnObject &result) override { if (args.empty()) { @@ -254,6 +281,13 @@ ~CommandObjectLogList() override = default; + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { + for (llvm::StringRef channel : Log::ListChannels()) + request.TryCompleteCurrentArg(channel); + } + protected: bool DoExecute(Args &args, CommandReturnObject &result) override { std::string output; Index: lldb/trunk/source/Utility/Log.cpp =================================================================== --- lldb/trunk/source/Utility/Log.cpp +++ lldb/trunk/source/Utility/Log.cpp @@ -9,7 +9,6 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/VASPrintf.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" #include "llvm/ADT/iterator.h" @@ -38,13 +37,21 @@ llvm::ManagedStatic Log::g_channel_map; -void Log::ListCategories(llvm::raw_ostream &stream, const ChannelMap::value_type &entry) { - stream << llvm::formatv("Logging categories for '{0}':\n", entry.first()); - stream << " all - all available logging categories\n"; - stream << " default - default set of logging categories\n"; +void Log::ForEachCategory( + const Log::ChannelMap::value_type &entry, + llvm::function_ref lambda) { + lambda("all", "all available logging categories"); + lambda("default", "default set of logging categories"); for (const auto &category : entry.second.m_channel.categories) - stream << llvm::formatv(" {0} - {1}\n", category.name, - category.description); + lambda(category.name, category.description); +} + +void Log::ListCategories(llvm::raw_ostream &stream, + const ChannelMap::value_type &entry) { + ForEachCategory(entry, + [&stream](llvm::StringRef name, llvm::StringRef description) { + stream << llvm::formatv(" {0} - {1}\n", name, description); + }); } uint32_t Log::GetFlags(llvm::raw_ostream &stream, const ChannelMap::value_type &entry, @@ -237,6 +244,23 @@ entry.second.Disable(UINT32_MAX); } +void Log::ForEachChannelCategory( + llvm::StringRef channel, + llvm::function_ref lambda) { + auto ch = g_channel_map->find(channel); + if (ch == g_channel_map->end()) + return; + + ForEachCategory(*ch, lambda); +} + +std::vector Log::ListChannels() { + std::vector result; + for (const auto &channel : *g_channel_map) + result.push_back(channel.first()); + return result; +} + void Log::ListAllLogChannels(llvm::raw_ostream &stream) { if (g_channel_map->empty()) { stream << "No logging channels are currently registered.\n";