From 2fc20f652cd848abdbfc40b6ae7fc0b0b403ea7d Mon Sep 17 00:00:00 2001 From: Raphael Isemann Date: Thu, 15 Aug 2019 13:14:10 +0000 Subject: [PATCH] [lldb][NFC] Refactor remaining completion logic to use CompletionRequests This patch moves the remaining completion functions from the old completion API (that used several variables) to just passing a single CompletionRequest. This is for the most part a simple change as we just replace the old arguments with a single CompletionRequest argument. There are a few places where I had to create new CompletionRequests in the called functions as CompletionRequests itself are immutable and don't expose their internal match list anymore. This means that if a function wanted to change the CompletionRequest or directly access the result list, we need to work around this by creating a new CompletionRequest and a temporary match/description list. Preparation work for rdar://53769355 llvm-svn: 369000 --- lldb/include/lldb/Core/IOHandler.h | 16 +++---- lldb/include/lldb/Expression/REPL.h | 5 +- lldb/include/lldb/Host/Editline.h | 6 +-- lldb/include/lldb/Interpreter/CommandInterpreter.h | 20 ++------ lldb/include/lldb/Utility/CompletionRequest.h | 3 ++ lldb/source/API/SBCommandInterpreter.cpp | 7 ++- lldb/source/Core/IOHandler.cpp | 54 +++++++++++----------- lldb/source/Expression/REPL.cpp | 39 ++++++++-------- lldb/source/Host/common/Editline.cpp | 15 ++++-- lldb/source/Interpreter/CommandInterpreter.cpp | 16 +++---- 10 files changed, 89 insertions(+), 92 deletions(-) diff --git a/lldb/include/lldb/Core/IOHandler.h b/lldb/include/lldb/Core/IOHandler.h index c407b01..84af743 100644 --- a/lldb/include/lldb/Core/IOHandler.h +++ b/lldb/include/lldb/Core/IOHandler.h @@ -10,6 +10,7 @@ #define liblldb_IOHandler_h_ #include "lldb/Core/ValueObjectList.h" +#include "lldb/Utility/CompletionRequest.h" #include "lldb/Utility/ConstString.h" #include "lldb/Utility/Flags.h" #include "lldb/Utility/Predicate.h" @@ -198,9 +199,8 @@ public: virtual void IOHandlerDeactivated(IOHandler &io_handler) {} - virtual int IOHandlerComplete(IOHandler &io_handler, const char *current_line, - const char *cursor, const char *last_char, - StringList &matches, StringList &descriptions); + virtual int IOHandlerComplete(IOHandler &io_handler, + CompletionRequest &request); virtual const char *IOHandlerGetFixIndentationCharacters() { return nullptr; } @@ -414,10 +414,7 @@ private: static int FixIndentationCallback(Editline *editline, const StringList &lines, int cursor_position, void *baton); - static int AutoCompleteCallback(const char *current_line, const char *cursor, - const char *last_char, - StringList &matches, StringList &descriptions, - void *baton); + static int AutoCompleteCallback(CompletionRequest &request, void *baton); #endif protected: @@ -448,9 +445,8 @@ public: bool GetResponse() const { return m_user_response; } - int IOHandlerComplete(IOHandler &io_handler, const char *current_line, - const char *cursor, const char *last_char, - StringList &matches, StringList &descriptions) override; + int IOHandlerComplete(IOHandler &io_handler, + CompletionRequest &request) override; void IOHandlerInputComplete(IOHandler &io_handler, std::string &data) override; diff --git a/lldb/include/lldb/Expression/REPL.h b/lldb/include/lldb/Expression/REPL.h index 0d21772..4833665 100644 --- a/lldb/include/lldb/Expression/REPL.h +++ b/lldb/include/lldb/Expression/REPL.h @@ -103,9 +103,8 @@ public: void IOHandlerInputComplete(IOHandler &io_handler, std::string &line) override; - int IOHandlerComplete(IOHandler &io_handler, const char *current_line, - const char *cursor, const char *last_char, - StringList &matches, StringList &descriptions) override; + int IOHandlerComplete(IOHandler &io_handler, + CompletionRequest &request) override; protected: static int CalculateActualIndentation(const StringList &lines); diff --git a/lldb/include/lldb/Host/Editline.h b/lldb/include/lldb/Host/Editline.h index f16319d..d063d4a 100644 --- a/lldb/include/lldb/Host/Editline.h +++ b/lldb/include/lldb/Host/Editline.h @@ -53,6 +53,7 @@ #include #include "lldb/Host/ConnectionFileDescriptor.h" +#include "lldb/Utility/CompletionRequest.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/Predicate.h" @@ -97,10 +98,7 @@ typedef int (*FixIndentationCallbackType)(Editline *editline, const StringList &lines, int cursor_position, void *baton); -typedef int (*CompleteCallbackType)(const char *current_line, - const char *cursor, const char *last_char, - StringList &matches, - StringList &descriptions, void *baton); +typedef int (*CompleteCallbackType)(CompletionRequest &request, void *baton); /// Status used to decide when and how to start editing another line in /// multi-line sessions diff --git a/lldb/include/lldb/Interpreter/CommandInterpreter.h b/lldb/include/lldb/Interpreter/CommandInterpreter.h index 3d704d1..8590873 100644 --- a/lldb/include/lldb/Interpreter/CommandInterpreter.h +++ b/lldb/include/lldb/Interpreter/CommandInterpreter.h @@ -308,29 +308,17 @@ public: CommandObject *GetCommandObjectForCommand(llvm::StringRef &command_line); - // This handles command line completion. You are given a pointer to the - // command string buffer, to the current cursor, and to the end of the string - // (in case it is not NULL terminated). You also passed in an StringList - // object to fill with the returns. The first element of the array will be - // filled with the string that you would need to insert at the cursor point - // to complete the cursor point to the longest common matching prefix. If you - // want to limit the number of elements returned, set max_return_elements to - // the number of elements you want returned. Otherwise set - // max_return_elements to -1. If you want to start some way into the match - // list, then set match_start_point to the desired start point. Returns: -1 + // This handles command line completion. Returns: -1 // if the completion character should be inserted -2 if the entire command // line should be deleted and replaced with matches.GetStringAtIndex(0) // INT_MAX if the number of matches is > max_return_elements, but it is // expensive to compute. Otherwise, returns the number of matches. // // FIXME: Only max_return_elements == -1 is supported at present. - int HandleCompletion(const char *current_line, const char *cursor, - const char *last_char, StringList &matches, - StringList &descriptions); + int HandleCompletion(CompletionRequest &request); - // This version just returns matches, and doesn't compute the substring. It - // is here so the Help command can call it for the first argument. It uses - // a CompletionRequest for simplicity reasons. + // This version just returns matches, and doesn't compute the substring. It + // is here so the Help command can call it for the first argument. int HandleCompletionMatches(CompletionRequest &request); int GetCommandNamesMatchingPartialString(const char *cmd_cstr, diff --git a/lldb/include/lldb/Utility/CompletionRequest.h b/lldb/include/lldb/Utility/CompletionRequest.h index c7ad098..050976c 100644 --- a/lldb/include/lldb/Utility/CompletionRequest.h +++ b/lldb/include/lldb/Utility/CompletionRequest.h @@ -75,6 +75,9 @@ public: CompletionResult &result); llvm::StringRef GetRawLine() const { return m_command; } + llvm::StringRef GetRawLineUntilCursor() const { + return m_command.substr(0, m_cursor_index); + } unsigned GetRawCursorPos() const { return m_raw_cursor_pos; } diff --git a/lldb/source/API/SBCommandInterpreter.cpp b/lldb/source/API/SBCommandInterpreter.cpp index 1c07e85..ccc70b3 100644 --- a/lldb/source/API/SBCommandInterpreter.cpp +++ b/lldb/source/API/SBCommandInterpreter.cpp @@ -371,8 +371,11 @@ int SBCommandInterpreter::HandleCompletionWithDescriptions( if (IsValid()) { lldb_private::StringList lldb_matches, lldb_descriptions; - num_completions = m_opaque_ptr->HandleCompletion( - current_line, cursor, last_char, lldb_matches, lldb_descriptions); + CompletionResult result; + CompletionRequest request(current_line, cursor - current_line, result); + num_completions = m_opaque_ptr->HandleCompletion(request); + result.GetMatches(lldb_matches); + result.GetDescriptions(lldb_descriptions); SBStringList temp_matches_list(&lldb_matches); matches.AppendList(temp_matches_list); diff --git a/lldb/source/Core/IOHandler.cpp b/lldb/source/Core/IOHandler.cpp index 6dcd8e3..1a35f30 100644 --- a/lldb/source/Core/IOHandler.cpp +++ b/lldb/source/Core/IOHandler.cpp @@ -170,17 +170,15 @@ IOHandlerConfirm::IOHandlerConfirm(Debugger &debugger, llvm::StringRef prompt, IOHandlerConfirm::~IOHandlerConfirm() = default; -int IOHandlerConfirm::IOHandlerComplete( - IOHandler &io_handler, const char *current_line, const char *cursor, - const char *last_char, StringList &matches, StringList &descriptions) { - if (current_line == cursor) { - if (m_default_response) { - matches.AppendString("y"); - } else { - matches.AppendString("n"); - } +int IOHandlerConfirm::IOHandlerComplete(IOHandler &io_handler, + CompletionRequest &request) { + if (request.GetRawCursorPos() == 0) { + if (m_default_response) + request.AddCompletion("y"); + else + request.AddCompletion("n"); } - return matches.GetSize(); + return request.GetNumberOfMatches(); } void IOHandlerConfirm::IOHandlerInputComplete(IOHandler &io_handler, @@ -218,39 +216,43 @@ void IOHandlerConfirm::IOHandlerInputComplete(IOHandler &io_handler, } } -int IOHandlerDelegate::IOHandlerComplete( - IOHandler &io_handler, const char *current_line, const char *cursor, - const char *last_char, StringList &matches, StringList &descriptions) { +int IOHandlerDelegate::IOHandlerComplete(IOHandler &io_handler, + CompletionRequest &request) { switch (m_completion) { case Completion::None: break; case Completion::LLDBCommand: return io_handler.GetDebugger().GetCommandInterpreter().HandleCompletion( - current_line, cursor, last_char, matches, descriptions); + request); case Completion::Expression: { CompletionResult result; - CompletionRequest request(current_line, cursor - current_line, result); + CompletionRequest subrequest(request.GetRawLine(), + request.GetRawCursorPos(), result); CommandCompletions::InvokeCommonCompletionCallbacks( io_handler.GetDebugger().GetCommandInterpreter(), - CommandCompletions::eVariablePathCompletion, request, nullptr); + CommandCompletions::eVariablePathCompletion, subrequest, nullptr); + StringList matches; + StringList descriptions; result.GetMatches(matches); result.GetDescriptions(descriptions); - size_t num_matches = request.GetNumberOfMatches(); + size_t num_matches = subrequest.GetNumberOfMatches(); if (num_matches > 0) { std::string common_prefix = matches.LongestCommonPrefix(); - const size_t partial_name_len = request.GetCursorArgumentPrefix().size(); + const size_t partial_name_len = + subrequest.GetCursorArgumentPrefix().size(); // If we matched a unique single command, add a space... Only do this if // the completer told us this was a complete word, however... - if (num_matches == 1 && request.GetWordComplete()) { + if (num_matches == 1 && subrequest.GetWordComplete()) { common_prefix.push_back(' '); } common_prefix.erase(0, partial_name_len); - matches.InsertStringAtIndex(0, std::move(common_prefix)); + request.AddCompletion(common_prefix); } - return num_matches; + request.AddCompletions(matches, descriptions); + return request.GetNumberOfMatches(); } break; } @@ -443,14 +445,12 @@ int IOHandlerEditline::FixIndentationCallback(Editline *editline, *editline_reader, lines, cursor_position); } -int IOHandlerEditline::AutoCompleteCallback( - const char *current_line, const char *cursor, const char *last_char, - StringList &matches, StringList &descriptions, void *baton) { +int IOHandlerEditline::AutoCompleteCallback(CompletionRequest &request, + void *baton) { IOHandlerEditline *editline_reader = (IOHandlerEditline *)baton; if (editline_reader) - return editline_reader->m_delegate.IOHandlerComplete( - *editline_reader, current_line, cursor, last_char, matches, - descriptions); + return editline_reader->m_delegate.IOHandlerComplete(*editline_reader, + request); return 0; } #endif diff --git a/lldb/source/Expression/REPL.cpp b/lldb/source/Expression/REPL.cpp index ffcfc1a..d1e7b71 100644 --- a/lldb/source/Expression/REPL.cpp +++ b/lldb/source/Expression/REPL.cpp @@ -433,28 +433,28 @@ void REPL::IOHandlerInputComplete(IOHandler &io_handler, std::string &code) { } } -int REPL::IOHandlerComplete(IOHandler &io_handler, const char *current_line, - const char *cursor, const char *last_char, - StringList &matches, StringList &descriptions) { - matches.Clear(); - - llvm::StringRef line(current_line, cursor - current_line); - +int REPL::IOHandlerComplete(IOHandler &io_handler, CompletionRequest &request) { // Complete an LLDB command if the first character is a colon... - if (!line.empty() && line[0] == ':') { + if (request.GetRawLine().startswith(":")) { Debugger &debugger = m_target.GetDebugger(); // auto complete LLDB commands - const char *lldb_current_line = line.substr(1).data(); - return debugger.GetCommandInterpreter().HandleCompletion( - lldb_current_line, cursor, last_char, matches, descriptions); + llvm::StringRef new_line = request.GetRawLine().drop_front(); + CompletionResult sub_result; + CompletionRequest sub_request(new_line, request.GetRawCursorPos() - 1, + sub_result); + int result = debugger.GetCommandInterpreter().HandleCompletion(sub_request); + StringList matches, descriptions; + sub_result.GetMatches(matches); + sub_result.GetDescriptions(descriptions); + request.AddCompletions(matches, descriptions); + return result; } // Strip spaces from the line and see if we had only spaces - line = line.ltrim(); - if (line.empty()) { + if (request.GetRawLineUntilCursor().trim().empty()) { // Only spaces on this line, so just indent - matches.AppendString(m_indent_str); + request.AddCompletion(m_indent_str); return 1; } @@ -477,12 +477,13 @@ int REPL::IOHandlerComplete(IOHandler &io_handler, const char *current_line, } } - if (cursor > current_line) { - current_code.append("\n"); - current_code.append(current_line, cursor - current_line); - } + current_code.append("\n"); + current_code += request.GetRawLineUntilCursor(); - return CompleteCode(current_code, matches); + StringList matches; + int result = CompleteCode(current_code, matches); + request.AddCompletions(matches); + return result; } bool QuitCommandOverrideCallback(void *baton, const char **argv) { diff --git a/lldb/source/Host/common/Editline.cpp b/lldb/source/Host/common/Editline.cpp index 4a34f53..de6560c 100644 --- a/lldb/source/Host/common/Editline.cpp +++ b/lldb/source/Host/common/Editline.cpp @@ -14,6 +14,7 @@ #include "lldb/Host/Editline.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" +#include "lldb/Utility/CompletionRequest.h" #include "lldb/Utility/FileSpec.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/SelectHelper.h" @@ -894,9 +895,17 @@ unsigned char Editline::TabCommand(int ch) { StringList completions, descriptions; int page_size = 40; - const int num_completions = m_completion_callback( - line_info->buffer, line_info->cursor, line_info->lastchar, - completions, descriptions, m_completion_callback_baton); + llvm::StringRef line(line_info->buffer, + line_info->lastchar - line_info->buffer); + unsigned cursor_index = line_info->cursor - line_info->buffer; + CompletionResult result; + CompletionRequest request(line, cursor_index, result); + + const int num_completions = + m_completion_callback(request, m_completion_callback_baton); + + result.GetMatches(completions); + result.GetDescriptions(descriptions); if (num_completions == 0) return CC_ERROR; diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp index 114316a..86cca78 100644 --- a/lldb/source/Interpreter/CommandInterpreter.cpp +++ b/lldb/source/Interpreter/CommandInterpreter.cpp @@ -1814,18 +1814,16 @@ int CommandInterpreter::HandleCompletionMatches(CompletionRequest &request) { return num_command_matches; } -int CommandInterpreter::HandleCompletion(const char *current_line, - const char *cursor, - const char *last_char, - StringList &matches, - StringList &descriptions) { - - llvm::StringRef command_line(current_line, last_char - current_line); +int CommandInterpreter::HandleCompletion(CompletionRequest &orig_request) { + // Start a new subrequest we can modify. CompletionResult result; - CompletionRequest request(command_line, cursor - current_line, result); + CompletionRequest request(orig_request.GetRawLine(), + orig_request.GetRawCursorPos(), result); // Don't complete comments, and if the line we are completing is just the // history repeat character, substitute the appropriate history line. const char *first_arg = request.GetParsedLine().GetArgumentAtIndex(0); + StringList matches, descriptions; + if (first_arg) { if (first_arg[0] == m_comment_char) return 0; @@ -1872,6 +1870,8 @@ int CommandInterpreter::HandleCompletion(const char *current_line, matches.InsertStringAtIndex(0, common_prefix.c_str()); descriptions.InsertStringAtIndex(0, ""); } + // Add completion to original request. + orig_request.AddCompletions(matches, descriptions); return num_command_matches; } -- 2.7.4