1//===-- CompletionRequest.h -------------------------------------*- C++ -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8 9#ifndef LLDB_UTILITY_COMPLETIONREQUEST_H 10#define LLDB_UTILITY_COMPLETIONREQUEST_H 11 12#include "lldb/Utility/Args.h" 13#include "lldb/Utility/LLDBAssert.h" 14#include "lldb/Utility/StringList.h" 15#include "llvm/ADT/StringRef.h" 16#include "llvm/ADT/StringSet.h" 17 18namespace lldb_private { 19enum class CompletionMode { 20 // The current token has been completed. 21 Normal, 22 // The current token has been partially completed. This means that we found 23 // a completion, but that the completed token is still incomplete. Examples 24 // for this are file paths, where we want to complete "/bi" to "/bin/", but 25 // the file path token is still incomplete after the completion. Clients 26 // should not indicate to the user that this is a full completion (e.g. by 27 // not inserting the usual trailing space after a successful completion). 28 Partial, 29 // The full line has been rewritten by the completion. 30 RewriteLine, 31}; 32 33class CompletionResult { 34public: 35 /// A single completion and all associated data. 36 class Completion { 37 38 std::string m_completion; 39 std::string m_descripton; 40 CompletionMode m_mode; 41 42 public: 43 Completion(llvm::StringRef completion, llvm::StringRef description, 44 CompletionMode mode) 45 : m_completion(completion.str()), m_descripton(description.str()), 46 m_mode(mode) {} 47 const std::string &GetCompletion() const { return m_completion; } 48 const std::string &GetDescription() const { return m_descripton; } 49 CompletionMode GetMode() const { return m_mode; } 50 51 /// Generates a string that uniquely identifies this completion result. 52 std::string GetUniqueKey() const; 53 }; 54 55private: 56 std::vector<Completion> m_results; 57 58 /// List of added completions so far. Used to filter out duplicates. 59 llvm::StringSet<> m_added_values; 60 61public: 62 void AddResult(llvm::StringRef completion, llvm::StringRef description, 63 CompletionMode mode); 64 65 llvm::ArrayRef<Completion> GetResults() const { return m_results; } 66 67 /// Adds all collected completion matches to the given list. 68 /// The list will be cleared before the results are added. The number of 69 /// results here is guaranteed to be equal to GetNumberOfResults(). 70 void GetMatches(StringList &matches) const; 71 72 /// Adds all collected completion descriptions to the given list. 73 /// The list will be cleared before the results are added. The number of 74 /// results here is guaranteed to be equal to GetNumberOfResults(). 75 void GetDescriptions(StringList &descriptions) const; 76 77 std::size_t GetNumberOfResults() const { return m_results.size(); } 78}; 79 80/// \class CompletionRequest CompletionRequest.h 81/// "lldb/Utility/ArgCompletionRequest.h" 82/// 83/// Contains all information necessary to complete an incomplete command 84/// for the user. Will be filled with the generated completions by the different 85/// completions functions. 86/// 87class CompletionRequest { 88public: 89 /// Constructs a completion request. 90 /// 91 /// \param [in] command_line 92 /// The command line the user has typed at this point. 93 /// 94 /// \param [in] raw_cursor_pos 95 /// The position of the cursor in the command line string. Index 0 means 96 /// the cursor is at the start of the line. The completion starts from 97 /// this cursor position. 98 /// 99 /// \param [out] result 100 /// The CompletionResult that will be filled with the results after this 101 /// request has been handled. 102 CompletionRequest(llvm::StringRef command_line, unsigned raw_cursor_pos, 103 CompletionResult &result); 104 105 llvm::StringRef GetRawLine() const { return m_command; } 106 107 unsigned GetRawCursorPos() const { return m_raw_cursor_pos; } 108 109 const Args &GetParsedLine() const { return m_parsed_line; } 110 111 Args &GetParsedLine() { return m_parsed_line; } 112 113 const Args::ArgEntry &GetParsedArg() { 114 return GetParsedLine()[GetCursorIndex()]; 115 } 116 117 /// Drops the first argument from the argument list. 118 void ShiftArguments() { 119 m_cursor_index--; 120 m_parsed_line.Shift(); 121 } 122 123 /// Adds an empty argument at the end of the argument list and moves 124 /// the cursor to this new argument. 125 void AppendEmptyArgument() { 126 m_parsed_line.AppendArgument(llvm::StringRef()); 127 m_cursor_index++; 128 m_cursor_char_position = 0; 129 } 130 131 size_t GetCursorIndex() const { return m_cursor_index; } 132 133 /// Adds a possible completion string. If the completion was already 134 /// suggested before, it will not be added to the list of results. A copy of 135 /// the suggested completion is stored, so the given string can be free'd 136 /// afterwards. 137 /// 138 /// \param match The suggested completion. 139 /// \param completion An optional description of the completion string. The 140 /// description will be displayed to the user alongside the completion. 141 /// \param mode The CompletionMode for this completion. 142 void AddCompletion(llvm::StringRef completion, 143 llvm::StringRef description = "", 144 CompletionMode mode = CompletionMode::Normal) { 145 m_result.AddResult(completion, description, mode); 146 } 147 148 /// Adds a possible completion string if the completion would complete the 149 /// current argument. 150 /// 151 /// \param match The suggested completion. 152 /// \param description An optional description of the completion string. The 153 /// description will be displayed to the user alongside the completion. 154 template <CompletionMode M = CompletionMode::Normal> 155 void TryCompleteCurrentArg(llvm::StringRef completion, 156 llvm::StringRef description = "") { 157 // Trying to rewrite the whole line while checking for the current 158 // argument never makes sense. Completion modes are always hardcoded, so 159 // this can be a static_assert. 160 static_assert(M != CompletionMode::RewriteLine, 161 "Shouldn't rewrite line with this function"); 162 if (completion.startswith(GetCursorArgumentPrefix())) 163 AddCompletion(completion, description, M); 164 } 165 166 /// Adds multiple possible completion strings. 167 /// 168 /// \param completions The list of completions. 169 /// 170 /// \see AddCompletion 171 void AddCompletions(const StringList &completions) { 172 for (const std::string &completion : completions) 173 AddCompletion(completion); 174 } 175 176 /// Adds multiple possible completion strings alongside their descriptions. 177 /// 178 /// The number of completions and descriptions must be identical. 179 /// 180 /// \param completions The list of completions. 181 /// \param completions The list of descriptions. 182 /// 183 /// \see AddCompletion 184 void AddCompletions(const StringList &completions, 185 const StringList &descriptions) { 186 lldbassert(completions.GetSize() == descriptions.GetSize()); 187 for (std::size_t i = 0; i < completions.GetSize(); ++i) 188 AddCompletion(completions.GetStringAtIndex(i), 189 descriptions.GetStringAtIndex(i)); 190 } 191 192 llvm::StringRef GetCursorArgumentPrefix() const { 193 return GetParsedLine().GetArgumentAtIndex(GetCursorIndex()); 194 } 195 196private: 197 /// The raw command line we are supposed to complete. 198 llvm::StringRef m_command; 199 /// The cursor position in m_command. 200 unsigned m_raw_cursor_pos; 201 /// The command line parsed as arguments. 202 Args m_parsed_line; 203 /// The index of the argument in which the completion cursor is. 204 size_t m_cursor_index; 205 /// The cursor position in the argument indexed by m_cursor_index. 206 size_t m_cursor_char_position; 207 208 /// The result this request is supposed to fill out. 209 /// We keep this object private to ensure that no backend can in any way 210 /// depend on already calculated completions (which would make debugging and 211 /// testing them much more complicated). 212 CompletionResult &m_result; 213}; 214 215} // namespace lldb_private 216 217#endif // LLDB_UTILITY_COMPLETIONREQUEST_H 218