[lldb] Reduce some dangerous boilerplate with CompletionRequest::ShiftArguments
authorRaphael Isemann <teemperor@gmail.com>
Mon, 23 Sep 2019 08:16:19 +0000 (08:16 +0000)
committerRaphael Isemann <teemperor@gmail.com>
Mon, 23 Sep 2019 08:16:19 +0000 (08:16 +0000)
We should in general not allow external code to fiddle with the internals of
CompletionRequest, but until this is gone let's at least provide a utility
function that makes this less dangerous.

This also now correct updates the partially parsed argument list,
but it doesn't seem to be used by anything that is behind one of
the current shift/SetCursorIndex calls, so this doesn't seeem to
fix any currently used completion.

llvm-svn: 372556

lldb/include/lldb/Utility/CompletionRequest.h
lldb/source/Commands/CommandObjectHelp.cpp
lldb/source/Commands/CommandObjectMultiword.cpp
lldb/source/Interpreter/CommandInterpreter.cpp
lldb/unittests/Utility/CompletionRequestTest.cpp

index 28ac78a..e10c1f7 100644 (file)
@@ -119,6 +119,13 @@ public:
     return GetParsedLine()[GetCursorIndex()];
   }
 
+  /// Drops the first argument from the argument list.
+  void ShiftArguments() {
+    m_cursor_index--;
+    m_parsed_line.Shift();
+    m_partial_parsed_line.Shift();
+  }
+
   void SetCursorIndex(int i) { m_cursor_index = i; }
   int GetCursorIndex() const { return m_cursor_index; }
 
index 34f6e5d..c02a583 100644 (file)
@@ -215,8 +215,7 @@ void CommandObjectHelp::HandleCompletion(CompletionRequest &request) {
   // user is getting help on...
 
   if (cmd_obj) {
-    request.GetParsedLine().Shift();
-    request.SetCursorIndex(request.GetCursorIndex() - 1);
+    request.ShiftArguments();
     cmd_obj->HandleCompletion(request);
     return;
   }
index e33a5e0..e06c733 100644 (file)
@@ -214,8 +214,7 @@ void CommandObjectMultiword::HandleCompletion(CompletionRequest &request) {
   // Remove the one match that we got from calling GetSubcommandObject.
   new_matches.DeleteStringAtIndex(0);
   request.AddCompletions(new_matches);
-  request.GetParsedLine().Shift();
-  request.SetCursorIndex(request.GetCursorIndex() - 1);
+  request.ShiftArguments();
   sub_command_object->HandleCompletion(request);
 }
 
index e9f22b5..c8a64b0 100644 (file)
@@ -1794,8 +1794,7 @@ void CommandInterpreter::HandleCompletionMatches(CompletionRequest &request) {
     CommandObject *command_object =
         GetCommandObject(request.GetParsedLine().GetArgumentAtIndex(0));
     if (command_object) {
-      request.GetParsedLine().Shift();
-      request.SetCursorIndex(request.GetCursorIndex() - 1);
+      request.ShiftArguments();
       command_object->HandleCompletion(request);
     }
   }
index 54bd342..469aad2 100644 (file)
@@ -31,6 +31,41 @@ TEST(CompletionRequest, Constructor) {
   EXPECT_STREQ(request.GetPartialParsedLine().GetArgumentAtIndex(1), "b");
 }
 
+TEST(CompletionRequest, ShiftArguments) {
+  std::string command = "a bad c";
+  const unsigned cursor_pos = 3;
+  const int arg_index = 1;
+  const int arg_cursor_pos = 1;
+  StringList matches;
+  CompletionResult result;
+
+  CompletionRequest request(command, cursor_pos, result);
+  result.GetMatches(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.GetPartialParsedLine().GetArgumentCount(), 2u);
+  EXPECT_STREQ(request.GetPartialParsedLine().GetArgumentAtIndex(1), "b");
+
+  // Shift away the 'a' argument.
+  request.ShiftArguments();
+
+  // The raw line/cursor stays identical.
+  EXPECT_STREQ(request.GetRawLine().str().c_str(), command.c_str());
+  EXPECT_EQ(request.GetRawCursorPos(), cursor_pos);
+
+  // Relative cursor position in arg is identical.
+  EXPECT_EQ(request.GetCursorCharPosition(), arg_cursor_pos);
+
+  // Partially parsed line and cursor should be updated.
+  EXPECT_EQ(request.GetCursorIndex(), arg_index - 1U);
+  EXPECT_EQ(request.GetPartialParsedLine().GetArgumentCount(), 1u);
+  EXPECT_STREQ(request.GetPartialParsedLine().GetArgumentAtIndex(0), "b");
+}
+
 TEST(CompletionRequest, DuplicateFiltering) {
   std::string command = "a bad c";
   const unsigned cursor_pos = 3;