xref: /src/contrib/llvm-project/lldb/source/Utility/CompletionRequest.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
1cfca06d7SDimitry Andric //===-- CompletionRequest.cpp ---------------------------------------------===//
2f73363f1SDimitry Andric //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f73363f1SDimitry Andric //
7f73363f1SDimitry Andric //===----------------------------------------------------------------------===//
8f73363f1SDimitry Andric 
9f73363f1SDimitry Andric #include "lldb/Utility/CompletionRequest.h"
10f73363f1SDimitry Andric 
11f73363f1SDimitry Andric using namespace lldb;
12f73363f1SDimitry Andric using namespace lldb_private;
13f73363f1SDimitry Andric 
CompletionRequest(llvm::StringRef command_line,unsigned raw_cursor_pos,CompletionResult & result)14f73363f1SDimitry Andric CompletionRequest::CompletionRequest(llvm::StringRef command_line,
15f73363f1SDimitry Andric                                      unsigned raw_cursor_pos,
1694994d37SDimitry Andric                                      CompletionResult &result)
17f73363f1SDimitry Andric     : m_command(command_line), m_raw_cursor_pos(raw_cursor_pos),
18ead24645SDimitry Andric       m_result(result) {
19ead24645SDimitry Andric   assert(raw_cursor_pos <= command_line.size() && "Out of bounds cursor?");
20f73363f1SDimitry Andric 
21f73363f1SDimitry Andric   // We parse the argument up to the cursor, so the last argument in
22f73363f1SDimitry Andric   // parsed_line is the one containing the cursor, and the cursor is after the
23f73363f1SDimitry Andric   // last character.
24ead24645SDimitry Andric   llvm::StringRef partial_command(command_line.substr(0, raw_cursor_pos));
25ead24645SDimitry Andric   m_parsed_line = Args(partial_command);
26f73363f1SDimitry Andric 
27ead24645SDimitry Andric   if (GetParsedLine().GetArgumentCount() == 0) {
28ead24645SDimitry Andric     m_cursor_index = 0;
29f73363f1SDimitry Andric     m_cursor_char_position = 0;
30ead24645SDimitry Andric   } else {
31ead24645SDimitry Andric     m_cursor_index = GetParsedLine().GetArgumentCount() - 1U;
32f73363f1SDimitry Andric     m_cursor_char_position =
33ead24645SDimitry Andric         strlen(GetParsedLine().GetArgumentAtIndex(m_cursor_index));
34f73363f1SDimitry Andric   }
35ead24645SDimitry Andric 
36ead24645SDimitry Andric   // The cursor is after a space but the space is not part of the argument.
37ead24645SDimitry Andric   // Let's add an empty fake argument to the end to make sure the completion
38ead24645SDimitry Andric   // code. Note: The space could be part of the last argument when it's quoted.
39312c0ed1SDimitry Andric   if (partial_command.ends_with(" ") &&
40312c0ed1SDimitry Andric       !GetCursorArgumentPrefix().ends_with(" "))
41ead24645SDimitry Andric     AppendEmptyArgument();
42f73363f1SDimitry Andric }
4394994d37SDimitry Andric 
GetUniqueKey() const4494994d37SDimitry Andric std::string CompletionResult::Completion::GetUniqueKey() const {
4594994d37SDimitry Andric 
4694994d37SDimitry Andric   // We build a unique key for this pair of completion:description. We
4794994d37SDimitry Andric   // prefix the key with the length of the completion string. This prevents
4894994d37SDimitry Andric   // that we could get any collisions from completions pairs such as these:
4994994d37SDimitry Andric   // "foo:", "bar" would be "foo:bar", but will now be: "4foo:bar"
5094994d37SDimitry Andric   // "foo", ":bar" would be "foo:bar", but will now be: "3foo:bar"
5194994d37SDimitry Andric 
5294994d37SDimitry Andric   std::string result;
5394994d37SDimitry Andric   result.append(std::to_string(m_completion.size()));
5494994d37SDimitry Andric   result.append(m_completion);
55ead24645SDimitry Andric   result.append(std::to_string(static_cast<int>(m_mode)));
56ead24645SDimitry Andric   result.append(":");
5794994d37SDimitry Andric   result.append(m_descripton);
5894994d37SDimitry Andric   return result;
5994994d37SDimitry Andric }
6094994d37SDimitry Andric 
AddResult(llvm::StringRef completion,llvm::StringRef description,CompletionMode mode)6194994d37SDimitry Andric void CompletionResult::AddResult(llvm::StringRef completion,
62ead24645SDimitry Andric                                  llvm::StringRef description,
63ead24645SDimitry Andric                                  CompletionMode mode) {
64ead24645SDimitry Andric   Completion r(completion, description, mode);
6594994d37SDimitry Andric 
6694994d37SDimitry Andric   // Add the completion if we haven't seen the same value before.
6794994d37SDimitry Andric   if (m_added_values.insert(r.GetUniqueKey()).second)
6894994d37SDimitry Andric     m_results.push_back(r);
6994994d37SDimitry Andric }
7094994d37SDimitry Andric 
GetMatches(StringList & matches) const7194994d37SDimitry Andric void CompletionResult::GetMatches(StringList &matches) const {
7294994d37SDimitry Andric   matches.Clear();
7394994d37SDimitry Andric   for (const Completion &completion : m_results)
74ead24645SDimitry Andric     matches.AppendString(completion.GetCompletion());
7594994d37SDimitry Andric }
7694994d37SDimitry Andric 
GetDescriptions(StringList & descriptions) const7794994d37SDimitry Andric void CompletionResult::GetDescriptions(StringList &descriptions) const {
7894994d37SDimitry Andric   descriptions.Clear();
7994994d37SDimitry Andric   for (const Completion &completion : m_results)
80ead24645SDimitry Andric     descriptions.AppendString(completion.GetDescription());
8194994d37SDimitry Andric }
82