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