teemperor created this revision.
teemperor added reviewers: davide, jingham, labath.
Herald added a subscriber: mgorny.

This patch refactors the internal completion API. It now takes (as far as 
possible) a single
CompletionRequest object instead o half a dozen in/out/in-out parameters. The 
CompletionRequest
contains a common superset of the different parameters as far as it makes 
sense. This includes
the raw command line string and raw cursor position, which should make the 
`expr` command
possible to implement (at least without hacks that reconstruct the command line 
from the args).

This patch is not intended to change the observable behavior of lldb in any 
way. It's also as
minimal as possible and doesn't attempt to fix all the problems the API has.

Some Q&A:

Q: Why is this not fixing all the problems in the completion API?
A: Because is a blocker for the expr command completion which I want to get in 
ASAP. This is the

  smallest patch that unblocks the expr completion patch and which allows 
trivial refactoring in the future.
  The patch also doesn't really change the internal information flow in the 
API, so that hopefully
  saves us from ever having to revert and resubmit this humongous patch.

Q: Can we merge all the copy-pasted code in the completion methods

  (like computing the current incomplete arg) into CompletionRequest class?

A: Yes, but it's out of scope for this patch.

Q: Why the `word_complete = request.GetWordComplete(); ... ` pattern?
A: I don't want to add a getter that returns a reference to the internal 
integer. So we have

  to use a temporary variable and the Getter/Setter instead. We don't throw 
exceptions
  from what I can tell, so the behavior doesn't change.

Q: Why are we not owning the list of matches?
A: Because that's how the previous API works. But that should be fixed too (in 
another patch).

Q: Can we make the constructor simpler and compute some of the values from the 
plain command?
A: I think this works, but I rather want to have this in a follow up commit. 
Especially when making nested

  request it's a bit awkward that the parsed arguments behave as both 
input/output (as we should in theory
  propagate the changes on the nested request back to the parent request if we 
don't want to change the
  behavior too much).

Q: Can't we pass one const request object and then just return another result 
object instead of mixing

  them together in one in/out parameter?

A: It's hard to get keep the same behavior with that pattern, but I think we 
can also get a nice API with just

  a single request object. If we make all input parameters read-only, we have a 
clear separation between what
  is actually an input and what an output parameter (and hopefully we get rid 
of the in-out parameters).

Q: Can we throw out the 'match' variables that are not implemented according to 
the comment?
A: We currently just forward them as in the old code to the different methods, 
even though I think

  they are really not used. We can easily remove and readd them once every 
single completion method just
  takes a CompletionRequest, but for now I prefer NFC behavior from the 
perspective of the API user.


https://reviews.llvm.org/D48796

Files:
  include/lldb/Interpreter/CommandAlias.h
  include/lldb/Interpreter/CommandInterpreter.h
  include/lldb/Interpreter/CommandObject.h
  include/lldb/Interpreter/CommandObjectMultiword.h
  include/lldb/Interpreter/CommandObjectRegexCommand.h
  include/lldb/Utility/CompletionRequest.h
  source/Commands/CommandObjectCommands.cpp
  source/Commands/CommandObjectFrame.cpp
  source/Commands/CommandObjectHelp.cpp
  source/Commands/CommandObjectHelp.h
  source/Commands/CommandObjectMultiword.cpp
  source/Commands/CommandObjectPlatform.cpp
  source/Commands/CommandObjectPlugin.cpp
  source/Commands/CommandObjectProcess.cpp
  source/Commands/CommandObjectSettings.cpp
  source/Commands/CommandObjectTarget.cpp
  source/Interpreter/CommandAlias.cpp
  source/Interpreter/CommandInterpreter.cpp
  source/Interpreter/CommandObject.cpp
  source/Interpreter/CommandObjectRegexCommand.cpp
  source/Utility/CMakeLists.txt
  source/Utility/CompletionRequest.cpp
  unittests/Utility/CMakeLists.txt
  unittests/Utility/CompletionRequestTest.cpp

Index: unittests/Utility/CompletionRequestTest.cpp
===================================================================
--- /dev/null
+++ unittests/Utility/CompletionRequestTest.cpp
@@ -0,0 +1,38 @@
+//===-- CompletionRequestTest.cpp -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+
+#include "lldb/Utility/CompletionRequest.h"
+using namespace lldb_private;
+
+TEST(CompletionRequest, Constructor) {
+  std::string command = "a b";
+  const unsigned cursor_pos = 2;
+  Args args(command);
+  const int arg_index = 1;
+  const int arg_cursor_pos = 0;
+  const int match_start = 2345;
+  const int match_max_return = 12345;
+  bool word_complete = false;
+  StringList matches;
+  CompletionRequest request(command, cursor_pos, args, arg_index,
+                            arg_cursor_pos, match_start, match_max_return,
+                            word_complete, matches);
+
+  EXPECT_STREQ(request.GetRawLine().str().c_str(), command.c_str());
+  EXPECT_EQ(request.GetRawCursorPos(), cursor_pos);
+  EXPECT_EQ(request.GetCursorIndex(), arg_index);
+  EXPECT_EQ(request.GetCursorCharPosition(), arg_cursor_pos);
+  EXPECT_EQ(request.GetMatchStartPoint(), match_start);
+  EXPECT_EQ(request.GetMaxReturnElements(), match_max_return);
+  EXPECT_EQ(request.GetWordComplete(), word_complete);
+  // This is the generated matches should be equal to our passed string list.
+  EXPECT_EQ(&request.GetMatches(), &matches);
+}
Index: unittests/Utility/CMakeLists.txt
===================================================================
--- unittests/Utility/CMakeLists.txt
+++ unittests/Utility/CMakeLists.txt
@@ -3,6 +3,7 @@
   ArchSpecTest.cpp
   CleanUpTest.cpp
   ConstStringTest.cpp
+  CompletionRequestTest.cpp
   EnvironmentTest.cpp
   FileSpecTest.cpp
   JSONTest.cpp
Index: source/Utility/CompletionRequest.cpp
===================================================================
--- /dev/null
+++ source/Utility/CompletionRequest.cpp
@@ -0,0 +1,26 @@
+//===-- CompletionRequest.cpp -----------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Utility/CompletionRequest.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+CompletionRequest::CompletionRequest(llvm::StringRef command,
+                                     unsigned raw_cursor_pos, Args &parsed_line,
+                                     int cursor_index, int cursor_char_position,
+                                     int match_start_point,
+                                     int max_return_elements,
+                                     bool word_complete, StringList &matches)
+    : m_command(command), m_raw_cursor_pos(raw_cursor_pos),
+      m_parsed_line(parsed_line), m_cursor_index(cursor_index),
+      m_cursor_char_position(cursor_char_position),
+      m_match_start_point(match_start_point),
+      m_max_return_elements(max_return_elements),
+      m_word_complete(word_complete), m_matches(&matches) {}
Index: source/Utility/CMakeLists.txt
===================================================================
--- source/Utility/CMakeLists.txt
+++ source/Utility/CMakeLists.txt
@@ -45,6 +45,7 @@
   Baton.cpp
   Connection.cpp
   ConstString.cpp
+  CompletionRequest.cpp
   DataBufferHeap.cpp
   DataBufferLLVM.cpp
   DataEncoder.cpp
Index: source/Interpreter/CommandObjectRegexCommand.cpp
===================================================================
--- source/Interpreter/CommandObjectRegexCommand.cpp
+++ source/Interpreter/CommandObjectRegexCommand.cpp
@@ -99,23 +99,21 @@
   return false;
 }
 
-int CommandObjectRegexCommand::HandleCompletion(Args &input, int &cursor_index,
-                                                int &cursor_char_position,
-                                                int match_start_point,
-                                                int max_return_elements,
-                                                bool &word_complete,
-                                                StringList &matches) {
+int CommandObjectRegexCommand::HandleCompletion(CompletionRequest &request) {
   if (m_completion_type_mask) {
-    std::string completion_str(input.GetArgumentAtIndex(cursor_index),
-                               cursor_char_position);
+    std::string completion_str(
+        request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex()),
+        request.GetCursorCharPosition());
+    bool word_complete = request.GetWordComplete();
     CommandCompletions::InvokeCommonCompletionCallbacks(
         GetCommandInterpreter(), m_completion_type_mask, completion_str.c_str(),
-        match_start_point, max_return_elements, nullptr, word_complete,
-        matches);
-    return matches.GetSize();
+        request.GetMatchStartPoint(), request.GetMaxReturnElements(), nullptr,
+        word_complete, request.GetMatches());
+    request.SetWordComplete(word_complete);
+    return request.GetMatches().GetSize();
   } else {
-    matches.Clear();
-    word_complete = false;
+    request.GetMatches().Clear();
+    request.SetWordComplete(false);
   }
   return 0;
 }
Index: source/Interpreter/CommandObject.cpp
===================================================================
--- source/Interpreter/CommandObject.cpp
+++ source/Interpreter/CommandObject.cpp
@@ -260,41 +260,39 @@
     m_api_locker.unlock();
 }
 
-int CommandObject::HandleCompletion(Args &input, int &cursor_index,
-                                    int &cursor_char_position,
-                                    int match_start_point,
-                                    int max_return_elements,
-                                    bool &word_complete, StringList &matches) {
+int CommandObject::HandleCompletion(CompletionRequest &request) {
   // Default implementation of WantsCompletion() is !WantsRawCommandString().
   // Subclasses who want raw command string but desire, for example, argument
   // completion should override WantsCompletion() to return true, instead.
   if (WantsRawCommandString() && !WantsCompletion()) {
     // FIXME: Abstract telling the completion to insert the completion
     // character.
-    matches.Clear();
+    request.GetMatches().Clear();
     return -1;
   } else {
     // Can we do anything generic with the options?
     Options *cur_options = GetOptions();
     CommandReturnObject result;
     OptionElementVector opt_element_vector;
 
     if (cur_options != nullptr) {
-      opt_element_vector = cur_options->ParseForCompletion(input, cursor_index);
+      opt_element_vector = cur_options->ParseForCompletion(
+          request.GetParsedLine(), request.GetCursorIndex());
 
       bool handled_by_options;
+      bool word_complete = request.GetWordComplete();
       handled_by_options = cur_options->HandleOptionCompletion(
-          input, opt_element_vector, cursor_index, cursor_char_position,
-          match_start_point, max_return_elements, GetCommandInterpreter(),
-          word_complete, matches);
+          request.GetParsedLine(), opt_element_vector, request.GetCursorIndex(),
+          request.GetCursorCharPosition(), request.GetMatchStartPoint(),
+          request.GetMaxReturnElements(), GetCommandInterpreter(),
+          word_complete, request.GetMatches());
+      request.SetWordComplete(word_complete);
       if (handled_by_options)
-        return matches.GetSize();
+        return request.GetMatches().GetSize();
     }
 
     // If we got here, the last word is not an option or an option argument.
-    return HandleArgumentCompletion(
-        input, cursor_index, cursor_char_position, opt_element_vector,
-        match_start_point, max_return_elements, word_complete, matches);
+    return HandleArgumentCompletion(request, opt_element_vector);
   }
 }
 
Index: source/Interpreter/CommandInterpreter.cpp
===================================================================
--- source/Interpreter/CommandInterpreter.cpp
+++ source/Interpreter/CommandInterpreter.cpp
@@ -1677,13 +1677,14 @@
     // We didn't find the first command object, so complete the first argument.
     Args command_args(command_string);
     StringList matches;
-    int num_matches;
     int cursor_index = 0;
     int cursor_char_position = strlen(command_args.GetArgumentAtIndex(0));
-    bool word_complete;
-    num_matches = HandleCompletionMatches(command_args, cursor_index,
-                                          cursor_char_position, 0, -1,
-                                          word_complete, matches);
+    bool word_complete = true;
+    CompletionRequest request(command_line, cursor_char_position, command_args,
+                              cursor_index, cursor_char_position, 0, -1,
+                              word_complete, matches);
+    int num_matches = HandleCompletionMatches(request);
+    word_complete = request.GetWordComplete();
 
     if (num_matches > 0) {
       std::string error_msg;
@@ -1712,59 +1713,55 @@
   return result.Succeeded();
 }
 
-int CommandInterpreter::HandleCompletionMatches(
-    Args &parsed_line, int &cursor_index, int &cursor_char_position,
-    int match_start_point, int max_return_elements, bool &word_complete,
-    StringList &matches) {
+int CommandInterpreter::HandleCompletionMatches(CompletionRequest &request) {
+  auto &matches = request.GetMatches();
   int num_command_matches = 0;
   bool look_for_subcommand = false;
 
   // For any of the command completions a unique match will be a complete word.
-  word_complete = true;
+  request.SetWordComplete(true);
 
-  if (cursor_index == -1) {
+  if (request.GetCursorIndex() == -1) {
     // We got nothing on the command line, so return the list of commands
     bool include_aliases = true;
     num_command_matches =
         GetCommandNamesMatchingPartialString("", include_aliases, matches);
-  } else if (cursor_index == 0) {
+  } else if (request.GetCursorIndex() == 0) {
     // The cursor is in the first argument, so just do a lookup in the
     // dictionary.
-    CommandObject *cmd_obj =
-        GetCommandObject(parsed_line.GetArgumentAtIndex(0), &matches);
+    CommandObject *cmd_obj = GetCommandObject(
+        request.GetParsedLine().GetArgumentAtIndex(0), &matches);
     num_command_matches = matches.GetSize();
 
     if (num_command_matches == 1 && cmd_obj && cmd_obj->IsMultiwordObject() &&
         matches.GetStringAtIndex(0) != nullptr &&
-        strcmp(parsed_line.GetArgumentAtIndex(0),
+        strcmp(request.GetParsedLine().GetArgumentAtIndex(0),
                matches.GetStringAtIndex(0)) == 0) {
-      if (parsed_line.GetArgumentCount() == 1) {
-        word_complete = true;
+      if (request.GetParsedLine().GetArgumentCount() == 1) {
+        request.SetWordComplete(true);
       } else {
         look_for_subcommand = true;
         num_command_matches = 0;
         matches.DeleteStringAtIndex(0);
-        parsed_line.AppendArgument(llvm::StringRef());
-        cursor_index++;
-        cursor_char_position = 0;
+        request.GetParsedLine().AppendArgument(llvm::StringRef());
+        request.SetCursorIndex(request.GetCursorIndex() + 1);
+        request.SetCursorCharPosition(0);
       }
     }
   }
 
-  if (cursor_index > 0 || look_for_subcommand) {
+  if (request.GetCursorIndex() > 0 || look_for_subcommand) {
     // We are completing further on into a commands arguments, so find the
     // command and tell it to complete the command. First see if there is a
     // matching initial command:
     CommandObject *command_object =
-        GetCommandObject(parsed_line.GetArgumentAtIndex(0));
+        GetCommandObject(request.GetParsedLine().GetArgumentAtIndex(0));
     if (command_object == nullptr) {
       return 0;
     } else {
-      parsed_line.Shift();
-      cursor_index--;
-      num_command_matches = command_object->HandleCompletion(
-          parsed_line, cursor_index, cursor_char_position, match_start_point,
-          max_return_elements, word_complete, matches);
+      request.GetParsedLine().Shift();
+      request.SetCursorIndex(request.GetCursorIndex() - 1);
+      num_command_matches = command_object->HandleCompletion(request);
     }
   }
 
@@ -1778,7 +1775,8 @@
   // parsed_line is the one containing the cursor, and the cursor is after the
   // last character.
 
-  Args parsed_line(llvm::StringRef(current_line, last_char - current_line));
+  llvm::StringRef command_line(current_line, last_char - current_line);
+  Args parsed_line(command_line);
   Args partial_parsed_line(
       llvm::StringRef(current_line, cursor - current_line));
 
@@ -1833,10 +1831,15 @@
 
   // Only max_return_elements == -1 is supported at present:
   lldbassert(max_return_elements == -1);
-  bool word_complete;
-  num_command_matches = HandleCompletionMatches(
-      parsed_line, cursor_index, cursor_char_position, match_start_point,
-      max_return_elements, word_complete, matches);
+  bool word_complete = false;
+
+  CompletionRequest request(command_line, cursor - current_line, parsed_line,
+                            cursor_index, cursor_char_position,
+                            match_start_point, max_return_elements,
+                            word_complete, matches);
+
+  num_command_matches = HandleCompletionMatches(request);
+  word_complete = request.GetWordComplete();
 
   if (num_command_matches <= 0)
     return num_command_matches;
Index: source/Interpreter/CommandAlias.cpp
===================================================================
--- source/Interpreter/CommandAlias.cpp
+++ source/Interpreter/CommandAlias.cpp
@@ -114,26 +114,17 @@
   return false;
 }
 
-int CommandAlias::HandleCompletion(Args &input, int &cursor_index,
-                                   int &cursor_char_position,
-                                   int match_start_point,
-                                   int max_return_elements, bool &word_complete,
-                                   StringList &matches) {
+int CommandAlias::HandleCompletion(CompletionRequest &request) {
   if (IsValid())
-    return m_underlying_command_sp->HandleCompletion(
-        input, cursor_index, cursor_char_position, match_start_point,
-        max_return_elements, word_complete, matches);
+    return m_underlying_command_sp->HandleCompletion(request);
   return -1;
 }
 
 int CommandAlias::HandleArgumentCompletion(
-    Args &input, int &cursor_index, int &cursor_char_position,
-    OptionElementVector &opt_element_vector, int match_start_point,
-    int max_return_elements, bool &word_complete, StringList &matches) {
+    CompletionRequest &request, OptionElementVector &opt_element_vector) {
   if (IsValid())
     return m_underlying_command_sp->HandleArgumentCompletion(
-        input, cursor_index, cursor_char_position, opt_element_vector,
-        match_start_point, max_return_elements, word_complete, matches);
+        request, opt_element_vector);
   return -1;
 }
 
Index: source/Commands/CommandObjectTarget.cpp
===================================================================
--- source/Commands/CommandObjectTarget.cpp
+++ source/Commands/CommandObjectTarget.cpp
@@ -195,20 +195,21 @@
 
   Options *GetOptions() override { return &m_option_group; }
 
-  int HandleArgumentCompletion(Args &input, int &cursor_index,
-                               int &cursor_char_position,
-                               OptionElementVector &opt_element_vector,
-                               int match_start_point, int max_return_elements,
-                               bool &word_complete,
-                               StringList &matches) override {
-    std::string completion_str(input.GetArgumentAtIndex(cursor_index));
-    completion_str.erase(cursor_char_position);
-
+  int HandleArgumentCompletion(
+      CompletionRequest &request,
+      OptionElementVector &opt_element_vector) override {
+    std::string completion_str(
+        request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex()));
+    completion_str.erase(request.GetCursorCharPosition());
+
+    bool word_complete = request.GetWordComplete();
     CommandCompletions::InvokeCommonCompletionCallbacks(
         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
-        completion_str.c_str(), match_start_point, max_return_elements, nullptr,
-        word_complete, matches);
-    return matches.GetSize();
+        completion_str.c_str(), request.GetMatchStartPoint(),
+        request.GetMaxReturnElements(), nullptr, word_complete,
+        request.GetMatches());
+    request.SetWordComplete(word_complete);
+    return request.GetMatches().GetSize();
   }
 
 protected:
@@ -1811,21 +1812,22 @@
 
   ~CommandObjectTargetModulesModuleAutoComplete() override = default;
 
-  int HandleArgumentCompletion(Args &input, int &cursor_index,
-                               int &cursor_char_position,
-                               OptionElementVector &opt_element_vector,
-                               int match_start_point, int max_return_elements,
-                               bool &word_complete,
-                               StringList &matches) override {
+  int HandleArgumentCompletion(
+      CompletionRequest &request,
+      OptionElementVector &opt_element_vector) override {
     // Arguments are the standard module completer.
-    std::string completion_str(input.GetArgumentAtIndex(cursor_index));
-    completion_str.erase(cursor_char_position);
+    std::string completion_str(
+        request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex()));
+    completion_str.erase(request.GetCursorCharPosition());
 
+    bool word_complete = request.GetWordComplete();
     CommandCompletions::InvokeCommonCompletionCallbacks(
         GetCommandInterpreter(), CommandCompletions::eModuleCompletion,
-        completion_str.c_str(), match_start_point, max_return_elements, nullptr,
-        word_complete, matches);
-    return matches.GetSize();
+        completion_str.c_str(), request.GetMatchStartPoint(),
+        request.GetMaxReturnElements(), nullptr, word_complete,
+        request.GetMatches());
+    request.SetWordComplete(word_complete);
+    return request.GetMatches().GetSize();
   }
 };
 
@@ -1860,21 +1862,22 @@
 
   ~CommandObjectTargetModulesSourceFileAutoComplete() override = default;
 
-  int HandleArgumentCompletion(Args &input, int &cursor_index,
-                               int &cursor_char_position,
-                               OptionElementVector &opt_element_vector,
-                               int match_start_point, int max_return_elements,
-                               bool &word_complete,
-                               StringList &matches) override {
+  int HandleArgumentCompletion(
+      CompletionRequest &request,
+      OptionElementVector &opt_element_vector) override {
     // Arguments are the standard source file completer.
-    std::string completion_str(input.GetArgumentAtIndex(cursor_index));
-    completion_str.erase(cursor_char_position);
+    std::string completion_str(
+        request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex()));
+    completion_str.erase(request.GetCursorCharPosition());
 
+    bool word_complete = request.GetWordComplete();
     CommandCompletions::InvokeCommonCompletionCallbacks(
         GetCommandInterpreter(), CommandCompletions::eSourceFileCompletion,
-        completion_str.c_str(), match_start_point, max_return_elements, nullptr,
-        word_complete, matches);
-    return matches.GetSize();
+        completion_str.c_str(), request.GetMatchStartPoint(),
+        request.GetMaxReturnElements(), nullptr, word_complete,
+        request.GetMatches());
+    request.SetWordComplete(word_complete);
+    return request.GetMatches().GetSize();
   }
 };
 
@@ -2410,20 +2413,21 @@
 
   Options *GetOptions() override { return &m_option_group; }
 
-  int HandleArgumentCompletion(Args &input, int &cursor_index,
-                               int &cursor_char_position,
-                               OptionElementVector &opt_element_vector,
-                               int match_start_point, int max_return_elements,
-                               bool &word_complete,
-                               StringList &matches) override {
-    std::string completion_str(input.GetArgumentAtIndex(cursor_index));
-    completion_str.erase(cursor_char_position);
+  int HandleArgumentCompletion(
+      CompletionRequest &request,
+      OptionElementVector &opt_element_vector) override {
+    std::string completion_str(
+        request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex()));
+    completion_str.erase(request.GetCursorCharPosition());
 
+    bool word_complete = request.GetWordComplete();
     CommandCompletions::InvokeCommonCompletionCallbacks(
         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
-        completion_str.c_str(), match_start_point, max_return_elements, nullptr,
-        word_complete, matches);
-    return matches.GetSize();
+        completion_str.c_str(), request.GetMatchStartPoint(),
+        request.GetMaxReturnElements(), nullptr, word_complete,
+        request.GetMatches());
+    request.SetWordComplete(word_complete);
+    return request.GetMatches().GetSize();
   }
 
 protected:
@@ -4011,20 +4015,21 @@
 
   ~CommandObjectTargetSymbolsAdd() override = default;
 
-  int HandleArgumentCompletion(Args &input, int &cursor_index,
-                               int &cursor_char_position,
-                               OptionElementVector &opt_element_vector,
-                               int match_start_point, int max_return_elements,
-                               bool &word_complete,
-                               StringList &matches) override {
-    std::string completion_str(input.GetArgumentAtIndex(cursor_index));
-    completion_str.erase(cursor_char_position);
+  int HandleArgumentCompletion(
+      CompletionRequest &request,
+      OptionElementVector &opt_element_vector) override {
+    std::string completion_str(
+        request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex()));
+    completion_str.erase(request.GetCursorCharPosition());
 
+    bool word_complete = request.GetWordComplete();
     CommandCompletions::InvokeCommonCompletionCallbacks(
         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
-        completion_str.c_str(), match_start_point, max_return_elements, nullptr,
-        word_complete, matches);
-    return matches.GetSize();
+        completion_str.c_str(), request.GetMatchStartPoint(),
+        request.GetMaxReturnElements(), nullptr, word_complete,
+        request.GetMatches());
+    request.SetWordComplete(word_complete);
+    return request.GetMatches().GetSize();
   }
 
   Options *GetOptions() override { return &m_option_group; }
Index: source/Commands/CommandObjectSettings.cpp
===================================================================
--- source/Commands/CommandObjectSettings.cpp
+++ source/Commands/CommandObjectSettings.cpp
@@ -133,53 +133,58 @@
     bool m_global;
   };
 
-  int HandleArgumentCompletion(Args &input, int &cursor_index,
-                               int &cursor_char_position,
-                               OptionElementVector &opt_element_vector,
-                               int match_start_point, int max_return_elements,
-                               bool &word_complete,
-                               StringList &matches) override {
-    std::string completion_str(input.GetArgumentAtIndex(cursor_index),
-                               cursor_char_position);
-
-    const size_t argc = input.GetArgumentCount();
+  int HandleArgumentCompletion(
+      CompletionRequest &request,
+      OptionElementVector &opt_element_vector) override {
+    std::string completion_str(
+        request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex()),
+        request.GetCursorCharPosition());
+
+    const size_t argc = request.GetParsedLine().GetArgumentCount();
     const char *arg = nullptr;
     int setting_var_idx;
     for (setting_var_idx = 0; setting_var_idx < static_cast<int>(argc);
          ++setting_var_idx) {
-      arg = input.GetArgumentAtIndex(setting_var_idx);
+      arg = request.GetParsedLine().GetArgumentAtIndex(setting_var_idx);
       if (arg && arg[0] != '-')
         break; // We found our setting variable name index
     }
-    if (cursor_index == setting_var_idx) {
+    if (request.GetCursorIndex() == setting_var_idx) {
       // Attempting to complete setting variable name
+      bool word_complete = request.GetWordComplete();
       CommandCompletions::InvokeCommonCompletionCallbacks(
           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
-          completion_str.c_str(), match_start_point, max_return_elements,
-          nullptr, word_complete, matches);
+          completion_str.c_str(), request.GetMatchStartPoint(),
+          request.GetMaxReturnElements(), nullptr, word_complete,
+          request.GetMatches());
+      request.SetWordComplete(word_complete);
     } else {
-      arg = input.GetArgumentAtIndex(cursor_index);
+      arg =
+          request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex());
 
       if (arg) {
         if (arg[0] == '-') {
           // Complete option name
         } else {
           // Complete setting value
           const char *setting_var_name =
-              input.GetArgumentAtIndex(setting_var_idx);
+              request.GetParsedLine().GetArgumentAtIndex(setting_var_idx);
           Status error;
           lldb::OptionValueSP value_sp(
               m_interpreter.GetDebugger().GetPropertyValue(
                   &m_exe_ctx, setting_var_name, false, error));
           if (value_sp) {
+            bool word_complete = request.GetWordComplete();
             value_sp->AutoComplete(m_interpreter, completion_str.c_str(),
-                                   match_start_point, max_return_elements,
-                                   word_complete, matches);
+                                   request.GetMatchStartPoint(),
+                                   request.GetMaxReturnElements(),
+                                   word_complete, request.GetMatches());
+            request.SetWordComplete(word_complete);
           }
         }
       }
     }
-    return matches.GetSize();
+    return request.GetMatches().GetSize();
   }
 
 protected:
@@ -272,20 +277,21 @@
 
   ~CommandObjectSettingsShow() override = default;
 
-  int HandleArgumentCompletion(Args &input, int &cursor_index,
-                               int &cursor_char_position,
-                               OptionElementVector &opt_element_vector,
-                               int match_start_point, int max_return_elements,
-                               bool &word_complete,
-                               StringList &matches) override {
-    std::string completion_str(input.GetArgumentAtIndex(cursor_index),
-                               cursor_char_position);
+  int HandleArgumentCompletion(
+      CompletionRequest &request,
+      OptionElementVector &opt_element_vector) override {
+    std::string completion_str(
+        request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex()),
+        request.GetCursorCharPosition());
 
+    bool word_complete = request.GetWordComplete();
     CommandCompletions::InvokeCommonCompletionCallbacks(
         GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
-        completion_str.c_str(), match_start_point, max_return_elements, nullptr,
-        word_complete, matches);
-    return matches.GetSize();
+        completion_str.c_str(), request.GetMatchStartPoint(),
+        request.GetMaxReturnElements(), nullptr, word_complete,
+        request.GetMatches());
+    request.SetWordComplete(word_complete);
+    return request.GetMatches().GetSize();
   }
 
 protected:
@@ -345,20 +351,21 @@
 
   ~CommandObjectSettingsList() override = default;
 
-  int HandleArgumentCompletion(Args &input, int &cursor_index,
-                               int &cursor_char_position,
-                               OptionElementVector &opt_element_vector,
-                               int match_start_point, int max_return_elements,
-                               bool &word_complete,
-                               StringList &matches) override {
-    std::string completion_str(input.GetArgumentAtIndex(cursor_index),
-                               cursor_char_position);
+  int HandleArgumentCompletion(
+      CompletionRequest &request,
+      OptionElementVector &opt_element_vector) override {
+    std::string completion_str(
+        request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex()),
+        request.GetCursorCharPosition());
 
+    bool word_complete = request.GetWordComplete();
     CommandCompletions::InvokeCommonCompletionCallbacks(
         GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
-        completion_str.c_str(), match_start_point, max_return_elements, nullptr,
-        word_complete, matches);
-    return matches.GetSize();
+        completion_str.c_str(), request.GetMatchStartPoint(),
+        request.GetMaxReturnElements(), nullptr, word_complete,
+        request.GetMatches());
+    request.SetWordComplete(word_complete);
+    return request.GetMatches().GetSize();
   }
 
 protected:
@@ -440,22 +447,23 @@
 
   ~CommandObjectSettingsRemove() override = default;
 
-  int HandleArgumentCompletion(Args &input, int &cursor_index,
-                               int &cursor_char_position,
-                               OptionElementVector &opt_element_vector,
-                               int match_start_point, int max_return_elements,
-                               bool &word_complete,
-                               StringList &matches) override {
-    std::string completion_str(input.GetArgumentAtIndex(cursor_index),
-                               cursor_char_position);
+  int HandleArgumentCompletion(
+      CompletionRequest &request,
+      OptionElementVector &opt_element_vector) override {
+    std::string completion_str(
+        request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex()),
+        request.GetCursorCharPosition());
 
     // Attempting to complete variable name
-    if (cursor_index < 2)
+    bool word_complete = request.GetWordComplete();
+    if (request.GetCursorIndex() < 2)
       CommandCompletions::InvokeCommonCompletionCallbacks(
           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
-          completion_str.c_str(), match_start_point, max_return_elements,
-          nullptr, word_complete, matches);
-    return matches.GetSize();
+          completion_str.c_str(), request.GetMatchStartPoint(),
+          request.GetMaxReturnElements(), nullptr, word_complete,
+          request.GetMatches());
+    request.SetWordComplete(word_complete);
+    return request.GetMatches().GetSize();
   }
 
 protected:
@@ -562,23 +570,24 @@
   // !WantsRawCommandString.
   bool WantsCompletion() override { return true; }
 
-  int HandleArgumentCompletion(Args &input, int &cursor_index,
-                               int &cursor_char_position,
-                               OptionElementVector &opt_element_vector,
-                               int match_start_point, int max_return_elements,
-                               bool &word_complete,
-                               StringList &matches) override {
-    std::string completion_str(input.GetArgumentAtIndex(cursor_index),
-                               cursor_char_position);
+  int HandleArgumentCompletion(
+      CompletionRequest &request,
+      OptionElementVector &opt_element_vector) override {
+    std::string completion_str(
+        request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex()),
+        request.GetCursorCharPosition());
 
+    bool word_complete = request.GetWordComplete();
     // Attempting to complete variable name
-    if (cursor_index < 2)
+    if (request.GetCursorIndex() < 2)
       CommandCompletions::InvokeCommonCompletionCallbacks(
           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
-          completion_str.c_str(), match_start_point, max_return_elements,
-          nullptr, word_complete, matches);
+          completion_str.c_str(), request.GetMatchStartPoint(),
+          request.GetMaxReturnElements(), nullptr, word_complete,
+          request.GetMatches());
+    request.SetWordComplete(word_complete);
 
-    return matches.GetSize();
+    return request.GetMatches().GetSize();
   }
 
 protected:
@@ -668,23 +677,24 @@
   // !WantsRawCommandString.
   bool WantsCompletion() override { return true; }
 
-  int HandleArgumentCompletion(Args &input, int &cursor_index,
-                               int &cursor_char_position,
-                               OptionElementVector &opt_element_vector,
-                               int match_start_point, int max_return_elements,
-                               bool &word_complete,
-                               StringList &matches) override {
-    std::string completion_str(input.GetArgumentAtIndex(cursor_index),
-                               cursor_char_position);
+  int HandleArgumentCompletion(
+      CompletionRequest &request,
+      OptionElementVector &opt_element_vector) override {
+    std::string completion_str(
+        request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex()),
+        request.GetCursorCharPosition());
 
+    bool word_complete = request.GetWordComplete();
     // Attempting to complete variable name
-    if (cursor_index < 2)
+    if (request.GetCursorIndex() < 2)
       CommandCompletions::InvokeCommonCompletionCallbacks(
           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
-          completion_str.c_str(), match_start_point, max_return_elements,
-          nullptr, word_complete, matches);
+          completion_str.c_str(), request.GetMatchStartPoint(),
+          request.GetMaxReturnElements(), nullptr, word_complete,
+          request.GetMatches());
+    request.SetWordComplete(word_complete);
 
-    return matches.GetSize();
+    return request.GetMatches().GetSize();
   }
 
 protected:
@@ -779,23 +789,24 @@
   // !WantsRawCommandString.
   bool WantsCompletion() override { return true; }
 
-  int HandleArgumentCompletion(Args &input, int &cursor_index,
-                               int &cursor_char_position,
-                               OptionElementVector &opt_element_vector,
-                               int match_start_point, int max_return_elements,
-                               bool &word_complete,
-                               StringList &matches) override {
-    std::string completion_str(input.GetArgumentAtIndex(cursor_index),
-                               cursor_char_position);
+  int HandleArgumentCompletion(
+      CompletionRequest &request,
+      OptionElementVector &opt_element_vector) override {
+    std::string completion_str(
+        request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex()),
+        request.GetCursorCharPosition());
 
+    bool word_complete = request.GetWordComplete();
     // Attempting to complete variable name
-    if (cursor_index < 2)
+    if (request.GetCursorIndex() < 2)
       CommandCompletions::InvokeCommonCompletionCallbacks(
           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
-          completion_str.c_str(), match_start_point, max_return_elements,
-          nullptr, word_complete, matches);
+          completion_str.c_str(), request.GetMatchStartPoint(),
+          request.GetMaxReturnElements(), nullptr, word_complete,
+          request.GetMatches());
+    request.SetWordComplete(word_complete);
 
-    return matches.GetSize();
+    return request.GetMatches().GetSize();
   }
 
 protected:
@@ -879,23 +890,24 @@
   // !WantsRawCommandString.
   bool WantsCompletion() override { return true; }
 
-  int HandleArgumentCompletion(Args &input, int &cursor_index,
-                               int &cursor_char_position,
-                               OptionElementVector &opt_element_vector,
-                               int match_start_point, int max_return_elements,
-                               bool &word_complete,
-                               StringList &matches) override {
-    std::string completion_str(input.GetArgumentAtIndex(cursor_index),
-                               cursor_char_position);
+  int HandleArgumentCompletion(
+      CompletionRequest &request,
+      OptionElementVector &opt_element_vector) override {
+    std::string completion_str(
+        request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex()),
+        request.GetCursorCharPosition());
 
+    bool word_complete = request.GetWordComplete();
     // Attempting to complete variable name
-    if (cursor_index < 2)
+    if (request.GetCursorIndex() < 2)
       CommandCompletions::InvokeCommonCompletionCallbacks(
           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
-          completion_str.c_str(), match_start_point, max_return_elements,
-          nullptr, word_complete, matches);
+          completion_str.c_str(), request.GetMatchStartPoint(),
+          request.GetMaxReturnElements(), nullptr, word_complete,
+          request.GetMatches());
+    request.SetWordComplete(word_complete);
 
-    return matches.GetSize();
+    return request.GetMatches().GetSize();
   }
 
 protected:
@@ -966,23 +978,24 @@
 
   ~CommandObjectSettingsClear() override = default;
 
-  int HandleArgumentCompletion(Args &input, int &cursor_index,
-                               int &cursor_char_position,
-                               OptionElementVector &opt_element_vector,
-                               int match_start_point, int max_return_elements,
-                               bool &word_complete,
-                               StringList &matches) override {
-    std::string completion_str(input.GetArgumentAtIndex(cursor_index),
-                               cursor_char_position);
+  int HandleArgumentCompletion(
+      CompletionRequest &request,
+      OptionElementVector &opt_element_vector) override {
+    std::string completion_str(
+        request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex()),
+        request.GetCursorCharPosition());
 
+    bool word_complete = request.GetWordComplete();
     // Attempting to complete variable name
-    if (cursor_index < 2)
+    if (request.GetCursorIndex() < 2)
       CommandCompletions::InvokeCommonCompletionCallbacks(
           GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion,
-          completion_str.c_str(), match_start_point, max_return_elements,
-          nullptr, word_complete, matches);
+          completion_str.c_str(), request.GetMatchStartPoint(),
+          request.GetMaxReturnElements(), nullptr, word_complete,
+          request.GetMatches());
+    request.SetWordComplete(word_complete);
 
-    return matches.GetSize();
+    return request.GetMatches().GetSize();
   }
 
 protected:
Index: source/Commands/CommandObjectProcess.cpp
===================================================================
--- source/Commands/CommandObjectProcess.cpp
+++ source/Commands/CommandObjectProcess.cpp
@@ -134,20 +134,21 @@
 
   ~CommandObjectProcessLaunch() override = default;
 
-  int HandleArgumentCompletion(Args &input, int &cursor_index,
-                               int &cursor_char_position,
-                               OptionElementVector &opt_element_vector,
-                               int match_start_point, int max_return_elements,
-                               bool &word_complete,
-                               StringList &matches) override {
-    std::string completion_str(input.GetArgumentAtIndex(cursor_index));
-    completion_str.erase(cursor_char_position);
-
+  int HandleArgumentCompletion(
+      CompletionRequest &request,
+      OptionElementVector &opt_element_vector) override {
+    std::string completion_str(
+        request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex()));
+    completion_str.erase(request.GetCursorCharPosition());
+
+    bool word_complete = request.GetWordComplete();
     CommandCompletions::InvokeCommonCompletionCallbacks(
         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
-        completion_str.c_str(), match_start_point, max_return_elements, nullptr,
-        word_complete, matches);
-    return matches.GetSize();
+        completion_str.c_str(), request.GetMatchStartPoint(),
+        request.GetMaxReturnElements(), nullptr, word_complete,
+        request.GetMatches());
+    request.SetWordComplete(word_complete);
+    return request.GetMatches().GetSize();
   }
 
   Options *GetOptions() override { return &m_options; }
Index: source/Commands/CommandObjectPlugin.cpp
===================================================================
--- source/Commands/CommandObjectPlugin.cpp
+++ source/Commands/CommandObjectPlugin.cpp
@@ -42,20 +42,20 @@
 
   ~CommandObjectPluginLoad() override = default;
 
-  int HandleArgumentCompletion(Args &input, int &cursor_index,
-                               int &cursor_char_position,
-                               OptionElementVector &opt_element_vector,
-                               int match_start_point, int max_return_elements,
-                               bool &word_complete,
-                               StringList &matches) override {
-    auto completion_str = input[cursor_index].ref;
-    completion_str = completion_str.take_front(cursor_char_position);
+  int HandleArgumentCompletion(
+      CompletionRequest &request,
+      OptionElementVector &opt_element_vector) override {
+    auto completion_str = request.GetParsedLine()[request.GetCursorIndex()].ref;
+    completion_str = completion_str.take_front(request.GetCursorCharPosition());
 
+    bool word_complete = request.GetWordComplete();
     CommandCompletions::InvokeCommonCompletionCallbacks(
         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
-        completion_str, match_start_point, max_return_elements, nullptr,
-        word_complete, matches);
-    return matches.GetSize();
+        completion_str, request.GetMatchStartPoint(),
+        request.GetMaxReturnElements(), nullptr, word_complete,
+        request.GetMatches());
+    request.SetWordComplete(word_complete);
+    return request.GetMatches().GetSize();
   }
 
 protected:
Index: source/Commands/CommandObjectPlatform.cpp
===================================================================
--- source/Commands/CommandObjectPlatform.cpp
+++ source/Commands/CommandObjectPlatform.cpp
@@ -178,17 +178,18 @@
 
   ~CommandObjectPlatformSelect() override = default;
 
-  int HandleCompletion(Args &input, int &cursor_index,
-                       int &cursor_char_position, int match_start_point,
-                       int max_return_elements, bool &word_complete,
-                       StringList &matches) override {
-    std::string completion_str(input.GetArgumentAtIndex(cursor_index));
-    completion_str.erase(cursor_char_position);
+  int HandleCompletion(CompletionRequest &request) override {
+    std::string completion_str(
+        request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex()));
+    completion_str.erase(request.GetCursorCharPosition());
 
+    bool word_complete = request.GetWordComplete();
     CommandCompletions::PlatformPluginNames(
-        GetCommandInterpreter(), completion_str.c_str(), match_start_point,
-        max_return_elements, nullptr, word_complete, matches);
-    return matches.GetSize();
+        GetCommandInterpreter(), completion_str.c_str(),
+        request.GetMatchStartPoint(), request.GetMaxReturnElements(), nullptr,
+        word_complete, request.GetMatches());
+    request.SetWordComplete(word_complete);
+    return request.GetMatches().GetSize();
   }
 
   Options *GetOptions() override { return &m_option_group; }
Index: source/Commands/CommandObjectMultiword.cpp
===================================================================
--- source/Commands/CommandObjectMultiword.cpp
+++ source/Commands/CommandObjectMultiword.cpp
@@ -186,35 +186,29 @@
                            "'help <command> <subcommand>'.\n");
 }
 
-int CommandObjectMultiword::HandleCompletion(Args &input, int &cursor_index,
-                                             int &cursor_char_position,
-                                             int match_start_point,
-                                             int max_return_elements,
-                                             bool &word_complete,
-                                             StringList &matches) {
+int CommandObjectMultiword::HandleCompletion(CompletionRequest &request) {
   // Any of the command matches will provide a complete word, otherwise the
   // individual completers will override this.
-  word_complete = true;
+  request.SetWordComplete(true);
+  auto &matches = request.GetMatches();
 
-  auto arg0 = input[0].ref;
-  if (cursor_index == 0) {
+  auto arg0 = request.GetParsedLine()[0].ref;
+  if (request.GetCursorIndex() == 0) {
     AddNamesMatchingPartialString(m_subcommand_dict, arg0, matches);
 
     if (matches.GetSize() == 1 && matches.GetStringAtIndex(0) != nullptr &&
         (arg0 == matches.GetStringAtIndex(0))) {
       StringList temp_matches;
       CommandObject *cmd_obj = GetSubcommandObject(arg0, &temp_matches);
       if (cmd_obj != nullptr) {
-        if (input.GetArgumentCount() == 1) {
-          word_complete = true;
+        if (request.GetParsedLine().GetArgumentCount() == 1) {
+          request.SetWordComplete(true);
         } else {
           matches.DeleteStringAtIndex(0);
-          input.Shift();
-          cursor_char_position = 0;
-          input.AppendArgument(llvm::StringRef());
-          return cmd_obj->HandleCompletion(
-              input, cursor_index, cursor_char_position, match_start_point,
-              max_return_elements, word_complete, matches);
+          request.GetParsedLine().Shift();
+          request.SetCursorCharPosition(0);
+          request.GetParsedLine().AppendArgument(llvm::StringRef());
+          return cmd_obj->HandleCompletion(request);
         }
       }
     }
@@ -226,11 +220,9 @@
     } else {
       // Remove the one match that we got from calling GetSubcommandObject.
       matches.DeleteStringAtIndex(0);
-      input.Shift();
-      cursor_index--;
-      return sub_command_object->HandleCompletion(
-          input, cursor_index, cursor_char_position, match_start_point,
-          max_return_elements, word_complete, matches);
+      request.GetParsedLine().Shift();
+      request.SetCursorIndex(request.GetCursorIndex() - 1);
+      return sub_command_object->HandleCompletion(request);
     }
   }
 }
@@ -370,31 +362,20 @@
   return nullptr;
 }
 
-int CommandObjectProxy::HandleCompletion(Args &input, int &cursor_index,
-                                         int &cursor_char_position,
-                                         int match_start_point,
-                                         int max_return_elements,
-                                         bool &word_complete,
-                                         StringList &matches) {
+int CommandObjectProxy::HandleCompletion(CompletionRequest &request) {
   CommandObject *proxy_command = GetProxyCommandObject();
   if (proxy_command)
-    return proxy_command->HandleCompletion(
-        input, cursor_index, cursor_char_position, match_start_point,
-        max_return_elements, word_complete, matches);
-  matches.Clear();
+    return proxy_command->HandleCompletion(request);
+  request.GetMatches().Clear();
   return 0;
 }
 
 int CommandObjectProxy::HandleArgumentCompletion(
-    Args &input, int &cursor_index, int &cursor_char_position,
-    OptionElementVector &opt_element_vector, int match_start_point,
-    int max_return_elements, bool &word_complete, StringList &matches) {
+    CompletionRequest &request, OptionElementVector &opt_element_vector) {
   CommandObject *proxy_command = GetProxyCommandObject();
   if (proxy_command)
-    return proxy_command->HandleArgumentCompletion(
-        input, cursor_index, cursor_char_position, opt_element_vector,
-        match_start_point, max_return_elements, word_complete, matches);
-  matches.Clear();
+    return proxy_command->HandleArgumentCompletion(request, opt_element_vector);
+  request.GetMatches().Clear();
   return 0;
 }
 
Index: source/Commands/CommandObjectHelp.h
===================================================================
--- source/Commands/CommandObjectHelp.h
+++ source/Commands/CommandObjectHelp.h
@@ -30,10 +30,7 @@
 
   ~CommandObjectHelp() override;
 
-  int HandleCompletion(Args &input, int &cursor_index,
-                       int &cursor_char_position, int match_start_point,
-                       int max_return_elements, bool &word_complete,
-                       StringList &matches) override;
+  int HandleCompletion(CompletionRequest &request) override;
 
   static void GenerateAdditionalHelpAvenuesMessage(
       Stream *s, llvm::StringRef command, llvm::StringRef prefix,
Index: source/Commands/CommandObjectHelp.cpp
===================================================================
--- source/Commands/CommandObjectHelp.cpp
+++ source/Commands/CommandObjectHelp.cpp
@@ -209,34 +209,24 @@
   return result.Succeeded();
 }
 
-int CommandObjectHelp::HandleCompletion(Args &input, int &cursor_index,
-                                        int &cursor_char_position,
-                                        int match_start_point,
-                                        int max_return_elements,
-                                        bool &word_complete,
-                                        StringList &matches) {
+int CommandObjectHelp::HandleCompletion(CompletionRequest &request) {
   // Return the completions of the commands in the help system:
-  if (cursor_index == 0) {
-    return m_interpreter.HandleCompletionMatches(
-        input, cursor_index, cursor_char_position, match_start_point,
-        max_return_elements, word_complete, matches);
+  if (request.GetCursorIndex() == 0) {
+    return m_interpreter.HandleCompletionMatches(request);
   } else {
-    CommandObject *cmd_obj = m_interpreter.GetCommandObject(input[0].ref);
+    CommandObject *cmd_obj =
+        m_interpreter.GetCommandObject(request.GetParsedLine()[0].ref);
 
     // The command that they are getting help on might be ambiguous, in which
     // case we should complete that, otherwise complete with the command the
     // user is getting help on...
 
     if (cmd_obj) {
-      input.Shift();
-      cursor_index--;
-      return cmd_obj->HandleCompletion(
-          input, cursor_index, cursor_char_position, match_start_point,
-          max_return_elements, word_complete, matches);
+      request.GetParsedLine().Shift();
+      request.SetCursorIndex(request.GetCursorIndex() - 1);
+      return cmd_obj->HandleCompletion(request);
     } else {
-      return m_interpreter.HandleCompletionMatches(
-          input, cursor_index, cursor_char_position, match_start_point,
-          max_return_elements, word_complete, matches);
+      return m_interpreter.HandleCompletionMatches(request);
     }
   }
 }
Index: source/Commands/CommandObjectFrame.cpp
===================================================================
--- source/Commands/CommandObjectFrame.cpp
+++ source/Commands/CommandObjectFrame.cpp
@@ -463,21 +463,21 @@
 
   Options *GetOptions() override { return &m_option_group; }
 
-  int HandleArgumentCompletion(Args &input, int &cursor_index,
-                               int &cursor_char_position,
-                               OptionElementVector &opt_element_vector,
-                               int match_start_point, int max_return_elements,
-                               bool &word_complete,
-                               StringList &matches) override {
+  int HandleArgumentCompletion(
+      CompletionRequest &request,
+      OptionElementVector &opt_element_vector) override {
     // Arguments are the standard source file completer.
-    auto completion_str = input[cursor_index].ref;
-    completion_str = completion_str.take_front(cursor_char_position);
+    auto completion_str = request.GetParsedLine()[request.GetCursorIndex()].ref;
+    completion_str = completion_str.take_front(request.GetCursorCharPosition());
 
+    bool word_complete = request.GetWordComplete();
     CommandCompletions::InvokeCommonCompletionCallbacks(
         GetCommandInterpreter(), CommandCompletions::eVariablePathCompletion,
-        completion_str, match_start_point, max_return_elements, nullptr,
-        word_complete, matches);
-    return matches.GetSize();
+        completion_str, request.GetMatchStartPoint(),
+        request.GetMaxReturnElements(), nullptr, word_complete,
+        request.GetMatches());
+    request.SetWordComplete(word_complete);
+    return request.GetMatches().GetSize();
   }
 
 protected:
Index: source/Commands/CommandObjectCommands.cpp
===================================================================
--- source/Commands/CommandObjectCommands.cpp
+++ source/Commands/CommandObjectCommands.cpp
@@ -235,20 +235,20 @@
     return "";
   }
 
-  int HandleArgumentCompletion(Args &input, int &cursor_index,
-                               int &cursor_char_position,
-                               OptionElementVector &opt_element_vector,
-                               int match_start_point, int max_return_elements,
-                               bool &word_complete,
-                               StringList &matches) override {
-    auto completion_str = input[cursor_index].ref;
-    completion_str = completion_str.take_front(cursor_char_position);
+  int HandleArgumentCompletion(
+      CompletionRequest &request,
+      OptionElementVector &opt_element_vector) override {
+    auto completion_str = request.GetParsedLine()[request.GetCursorIndex()].ref;
+    completion_str = completion_str.take_front(request.GetCursorCharPosition());
 
+    bool word_complete = request.GetWordComplete();
     CommandCompletions::InvokeCommonCompletionCallbacks(
         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
-        completion_str, match_start_point, max_return_elements, nullptr,
-        word_complete, matches);
-    return matches.GetSize();
+        completion_str, request.GetMatchStartPoint(),
+        request.GetMaxReturnElements(), nullptr, word_complete,
+        request.GetMatches());
+    request.SetWordComplete(word_complete);
+    return request.GetMatches().GetSize();
   }
 
   Options *GetOptions() override { return &m_options; }
@@ -1459,20 +1459,21 @@
 
   ~CommandObjectCommandsScriptImport() override = default;
 
-  int HandleArgumentCompletion(Args &input, int &cursor_index,
-                               int &cursor_char_position,
-                               OptionElementVector &opt_element_vector,
-                               int match_start_point, int max_return_elements,
-                               bool &word_complete,
-                               StringList &matches) override {
-    llvm::StringRef completion_str = input[cursor_index].ref;
-    completion_str = completion_str.take_front(cursor_char_position);
+  int HandleArgumentCompletion(
+      CompletionRequest &request,
+      OptionElementVector &opt_element_vector) override {
+    llvm::StringRef completion_str =
+        request.GetParsedLine()[request.GetCursorIndex()].ref;
+    completion_str = completion_str.take_front(request.GetCursorCharPosition());
 
+    bool word_complete = request.GetWordComplete();
     CommandCompletions::InvokeCommonCompletionCallbacks(
         GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion,
-        completion_str, match_start_point, max_return_elements, nullptr,
-        word_complete, matches);
-    return matches.GetSize();
+        completion_str, request.GetMatchStartPoint(),
+        request.GetMaxReturnElements(), nullptr, word_complete,
+        request.GetMatches());
+    request.SetWordComplete(word_complete);
+    return request.GetMatches().GetSize();
   }
 
   Options *GetOptions() override { return &m_options; }
Index: include/lldb/Utility/CompletionRequest.h
===================================================================
--- /dev/null
+++ include/lldb/Utility/CompletionRequest.h
@@ -0,0 +1,94 @@
+//===-- CompletionRequest.h -------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_UTILITY_COMPLETIONREQUEST_H
+#define LLDB_UTILITY_COMPLETIONREQUEST_H
+
+#include <lldb/Utility/Args.h>
+#include <lldb/Utility/StringList.h>
+#include <llvm/ADT/StringRef.h>
+
+namespace lldb_private {
+
+//----------------------------------------------------------------------
+/// @class CompletionRequest CompletionRequest.h
+///   "lldb/Utility/ArgCompletionRequest.h"
+///
+/// Contains all information necessary to complete an incomplete command
+/// for the user. Will be filled with the generated completions by the different
+/// completions functions.
+///
+//----------------------------------------------------------------------
+class CompletionRequest {
+public:
+  //----------------------------------------------------------------------
+  /// Constructs a completion request.
+  ///
+  /// See the respective members of this class for documentation for the
+  /// parameters.
+  // TODO: Infer the parsed_line and the cursor positions from the other
+  // arguments.
+  //----------------------------------------------------------------------
+  CompletionRequest(llvm::StringRef command, unsigned raw_cursor_pos,
+                    Args &parsed_line, int cursor_index,
+                    int cursor_char_position, int match_start_point,
+                    int max_return_elements, bool word_complete,
+                    StringList &matches);
+
+  llvm::StringRef GetRawLine() const { return m_command; }
+
+  unsigned GetRawCursorPos() const { return m_raw_cursor_pos; }
+
+  Args &GetParsedLine() { return m_parsed_line; }
+
+  void SetCursorIndex(int i) { m_cursor_index = i; }
+  int GetCursorIndex() const { return m_cursor_index; }
+
+  void SetCursorCharPosition(int pos) { m_cursor_char_position = pos; }
+  int GetCursorCharPosition() const { return m_cursor_char_position; }
+
+  int GetMatchStartPoint() const { return m_match_start_point; }
+
+  int GetMaxReturnElements() const { return m_max_return_elements; }
+
+  bool GetWordComplete() { return m_word_complete; }
+
+  void SetWordComplete(bool v) { m_word_complete = v; }
+
+  /// The array of matches returned.
+  StringList &GetMatches() { return *m_matches; }
+
+private:
+  /// The raw command line we are supposed to complete.
+  llvm::StringRef m_command;
+  /// The cursor position in m_command.
+  unsigned m_raw_cursor_pos;
+  /// The command line parsed as arguments.
+  Args m_parsed_line;
+  /// The index of the argument in which the completion cursor is.
+  int m_cursor_index;
+  /// The cursor position in the argument indexed by m_cursor_index.
+  int m_cursor_char_position;
+  /// If there is a match that is expensive
+  /// to compute, these are here to allow you to compute the completions in
+  /// batches.  Start the completion from \amatch_start_point, and return
+  /// \amatch_return_elements elements.
+  // FIXME: These two values are not implemented.
+  int m_match_start_point;
+  int m_max_return_elements;
+  /// \btrue if this is a complete option value (a space will be inserted
+  /// after the completion.)  \bfalse otherwise.
+  bool m_word_complete;
+  // We don't own the list.
+  StringList *m_matches;
+};
+
+} // namespace lldb_private
+
+#endif // LLDB_UTILITY_COMPLETIONREQUEST_H
Index: include/lldb/Interpreter/CommandObjectRegexCommand.h
===================================================================
--- include/lldb/Interpreter/CommandObjectRegexCommand.h
+++ include/lldb/Interpreter/CommandObjectRegexCommand.h
@@ -40,10 +40,7 @@
 
   bool HasRegexEntries() const { return !m_entries.empty(); }
 
-  int HandleCompletion(Args &input, int &cursor_index,
-                       int &cursor_char_position, int match_start_point,
-                       int max_return_elements, bool &word_complete,
-                       StringList &matches) override;
+  int HandleCompletion(CompletionRequest &request) override;
 
 protected:
   bool DoExecute(const char *command, CommandReturnObject &result) override;
Index: include/lldb/Interpreter/CommandObjectMultiword.h
===================================================================
--- include/lldb/Interpreter/CommandObjectMultiword.h
+++ include/lldb/Interpreter/CommandObjectMultiword.h
@@ -56,10 +56,7 @@
 
   bool WantsRawCommandString() override { return false; }
 
-  int HandleCompletion(Args &input, int &cursor_index,
-                       int &cursor_char_position, int match_start_point,
-                       int max_return_elements, bool &word_complete,
-                       StringList &matches) override;
+  int HandleCompletion(CompletionRequest &request) override;
 
   const char *GetRepeatCommand(Args &current_command_args,
                                uint32_t index) override;
@@ -121,17 +118,11 @@
 
   Options *GetOptions() override;
 
-  int HandleCompletion(Args &input, int &cursor_index,
-                       int &cursor_char_position, int match_start_point,
-                       int max_return_elements, bool &word_complete,
-                       StringList &matches) override;
-
-  int HandleArgumentCompletion(Args &input, int &cursor_index,
-                               int &cursor_char_position,
-                               OptionElementVector &opt_element_vector,
-                               int match_start_point, int max_return_elements,
-                               bool &word_complete,
-                               StringList &matches) override;
+  int HandleCompletion(CompletionRequest &request) override;
+
+  int HandleArgumentCompletion(
+      CompletionRequest &request,
+      OptionElementVector &opt_element_vector) override;
 
   const char *GetRepeatCommand(Args &current_command_args,
                                uint32_t index) override;
Index: include/lldb/Interpreter/CommandObject.h
===================================================================
--- include/lldb/Interpreter/CommandObject.h
+++ include/lldb/Interpreter/CommandObject.h
@@ -16,6 +16,8 @@
 #include <string>
 #include <vector>
 
+#include <lldb/Utility/CompletionRequest.h>
+
 // Other libraries and framework includes
 // Project includes
 #include "lldb/Utility/Flags.h"
@@ -222,105 +224,44 @@
   void SetCommandName(llvm::StringRef name);
 
   //------------------------------------------------------------------
-  /// The input array contains a parsed version of the line.  The insertion
-  /// point is given by cursor_index (the index in input of the word containing
-  /// the cursor) and cursor_char_position (the position of the cursor in that
-  /// word.)
   /// This default version handles calling option argument completions and then
-  /// calls
-  /// HandleArgumentCompletion if the cursor is on an argument, not an option.
-  /// Don't override this method, override HandleArgumentCompletion instead
-  /// unless
-  /// you have special reasons.
-  ///
-  /// @param[in] interpreter
-  ///    The command interpreter doing the completion.
-  ///
-  /// @param[in] input
-  ///    The command line parsed into words
-  ///
-  /// @param[in] cursor_index
-  ///     The index in \ainput of the word in which the cursor lies.
-  ///
-  /// @param[in] cursor_char_pos
-  ///     The character position of the cursor in its argument word.
+  /// calls HandleArgumentCompletion if the cursor is on an argument, not an
+  /// option. Don't override this method, override HandleArgumentCompletion
+  /// instead unless you have special reasons.
   ///
-  /// @param[in] match_start_point
-  /// @param[in] match_return_elements
-  ///     FIXME: Not yet implemented...  If there is a match that is expensive
-  ///     to compute, these are
-  ///     here to allow you to compute the completions in batches.  Start the
-  ///     completion from \amatch_start_point,
-  ///     and return \amatch_return_elements elements.
-  ///
-  /// @param[out] word_complete
-  ///     \btrue if this is a complete option value (a space will be inserted
-  ///     after the
-  ///     completion.)  \bfalse otherwise.
-  ///
-  /// @param[out] matches
-  ///     The array of matches returned.
+  /// @param[in/out] request
+  ///    The completion request that needs to be answered.
   ///
   /// FIXME: This is the wrong return value, since we also need to make a
   /// distinction between
   /// total number of matches, and the window the user wants returned.
   ///
   /// @return
   ///     \btrue if we were in an option, \bfalse otherwise.
   //------------------------------------------------------------------
-  virtual int HandleCompletion(Args &input, int &cursor_index,
-                               int &cursor_char_position, int match_start_point,
-                               int max_return_elements, bool &word_complete,
-                               StringList &matches);
+  virtual int HandleCompletion(CompletionRequest &request);
 
   //------------------------------------------------------------------
   /// The input array contains a parsed version of the line.  The insertion
   /// point is given by cursor_index (the index in input of the word containing
   /// the cursor) and cursor_char_position (the position of the cursor in that
   /// word.)
   /// We've constructed the map of options and their arguments as well if that
-  /// is
-  /// helpful for the completion.
-  ///
-  /// @param[in] interpreter
-  ///    The command interpreter doing the completion.
-  ///
-  /// @param[in] input
-  ///    The command line parsed into words
-  ///
-  /// @param[in] cursor_index
-  ///     The index in \ainput of the word in which the cursor lies.
-  ///
-  /// @param[in] cursor_char_pos
-  ///     The character position of the cursor in its argument word.
-  ///
-  /// @param[in] opt_element_vector
-  ///     The results of the options parse of \a input.
-  ///
-  /// @param[in] match_start_point
-  /// @param[in] match_return_elements
-  ///     See CommandObject::HandleCompletions for a description of how these
-  ///     work.
-  ///
-  /// @param[out] word_complete
-  ///     \btrue if this is a complete option value (a space will be inserted
-  ///     after the
-  ///     completion.)  \bfalse otherwise.
+  /// is helpful for the completion.
   ///
-  /// @param[out] matches
-  ///     The array of matches returned.
+  /// @param[in/out] request
+  ///    The completion request that needs to be answered.
   ///
   /// FIXME: This is the wrong return value, since we also need to make a
   /// distinction between
   /// total number of matches, and the window the user wants returned.
   ///
   /// @return
   ///     The number of completions.
   //------------------------------------------------------------------
-  virtual int HandleArgumentCompletion(
-      Args &input, int &cursor_index, int &cursor_char_position,
-      OptionElementVector &opt_element_vector, int match_start_point,
-      int max_return_elements, bool &word_complete, StringList &matches) {
+  virtual int
+  HandleArgumentCompletion(CompletionRequest &request,
+                           OptionElementVector &opt_element_vector) {
     return 0;
   }
 
Index: include/lldb/Interpreter/CommandInterpreter.h
===================================================================
--- include/lldb/Interpreter/CommandInterpreter.h
+++ include/lldb/Interpreter/CommandInterpreter.h
@@ -312,14 +312,9 @@
                        int max_return_elements, StringList &matches);
 
   // 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.
-  // word_complete tells whether the completions are considered a "complete"
-  // response (so the completer should complete the quote & put a space after
-  // the word.
-  int HandleCompletionMatches(Args &input, int &cursor_index,
-                              int &cursor_char_position, int match_start_point,
-                              int max_return_elements, bool &word_complete,
-                              StringList &matches);
+  // is here so the Help command can call it for the first argument. It uses
+  // a CompletionRequest for simplicity reasons.
+  int HandleCompletionMatches(CompletionRequest &request);
 
   int GetCommandNamesMatchingPartialString(const char *cmd_cstr,
                                            bool include_aliases,
Index: include/lldb/Interpreter/CommandAlias.h
===================================================================
--- include/lldb/Interpreter/CommandAlias.h
+++ include/lldb/Interpreter/CommandAlias.h
@@ -40,17 +40,11 @@
 
   bool WantsCompletion() override;
 
-  int HandleCompletion(Args &input, int &cursor_index,
-                       int &cursor_char_position, int match_start_point,
-                       int max_return_elements, bool &word_complete,
-                       StringList &matches) override;
-
-  int HandleArgumentCompletion(Args &input, int &cursor_index,
-                               int &cursor_char_position,
-                               OptionElementVector &opt_element_vector,
-                               int match_start_point, int max_return_elements,
-                               bool &word_complete,
-                               StringList &matches) override;
+  int HandleCompletion(CompletionRequest &request) override;
+
+  int HandleArgumentCompletion(
+      CompletionRequest &request,
+      OptionElementVector &opt_element_vector) override;
 
   Options *GetOptions() override;
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to