Coverage Report

Created: 2023-09-21 18:56

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Utility/CompletionRequest.h
Line
Count
Source
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
18
namespace lldb_private {
19
enum class CompletionMode {
20
  /// The current token has been completed. The client should indicate this
21
  /// to the user (usually this is done by adding a trailing space behind the
22
  /// token).
23
  /// Example: "command sub" -> "command subcommand " (note the trailing space).
24
  Normal,
25
  /// The current token has been partially completed. This means that we found
26
  /// a completion, but that the token is still incomplete. Examples
27
  /// for this are file paths, where we want to complete "/bi" to "/bin/", but
28
  /// the file path token is still incomplete after the completion. Clients
29
  /// should not indicate to the user that this is a full completion (e.g. by
30
  /// not inserting the usual trailing space after a successful completion).
31
  /// Example: "file /us" -> "file /usr/" (note the missing trailing space).
32
  Partial,
33
  /// The full line has been rewritten by the completion.
34
  /// Example: "alias name" -> "other_command full_name".
35
  RewriteLine,
36
};
37
38
class CompletionResult {
39
public:
40
  /// A single completion and all associated data.
41
  class Completion {
42
43
    /// The actual text that should be completed. The meaning of this text
44
    /// is defined by the CompletionMode.
45
    /// \see m_mode
46
    std::string m_completion;
47
    /// The description that should be displayed to the user alongside the
48
    /// completion text.
49
    std::string m_descripton;
50
    CompletionMode m_mode;
51
52
  public:
53
    Completion(llvm::StringRef completion, llvm::StringRef description,
54
               CompletionMode mode)
55
3.42k
        : m_completion(completion.str()), m_descripton(description.str()),
56
3.42k
          m_mode(mode) {}
57
3.26k
    const std::string &GetCompletion() const { return m_completion; }
58
3.20k
    const std::string &GetDescription() const { return m_descripton; }
59
459
    CompletionMode GetMode() const { return m_mode; }
60
61
    /// Generates a string that uniquely identifies this completion result.
62
    std::string GetUniqueKey() const;
63
  };
64
65
private:
66
  /// List of found completions.
67
  std::vector<Completion> m_results;
68
69
  /// A set of the unique keys of all found completions so far. Used to filter
70
  /// out duplicates.
71
  /// \see CompletionResult::Completion::GetUniqueKey
72
  llvm::StringSet<> m_added_values;
73
74
public:
75
  void AddResult(llvm::StringRef completion, llvm::StringRef description,
76
                 CompletionMode mode);
77
78
4
  llvm::ArrayRef<Completion> GetResults() const { return m_results; }
79
80
  /// Adds all collected completion matches to the given list.
81
  /// The list will be cleared before the results are added. The number of
82
  /// results here is guaranteed to be equal to GetNumberOfResults().
83
  void GetMatches(StringList &matches) const;
84
85
  /// Adds all collected completion descriptions to the given list.
86
  /// The list will be cleared before the results are added. The number of
87
  /// results here is guaranteed to be equal to GetNumberOfResults().
88
  void GetDescriptions(StringList &descriptions) const;
89
90
339
  std::size_t GetNumberOfResults() const { return m_results.size(); }
91
};
92
93
/// \class CompletionRequest CompletionRequest.h
94
///   "lldb/Utility/ArgCompletionRequest.h"
95
///
96
/// Contains all information necessary to complete an incomplete command
97
/// for the user. Will be filled with the generated completions by the different
98
/// completions functions.
99
///
100
class CompletionRequest {
101
public:
102
  /// Constructs a completion request.
103
  ///
104
  /// \param [in] command_line
105
  ///     The command line the user has typed at this point.
106
  ///
107
  /// \param [in] raw_cursor_pos
108
  ///     The position of the cursor in the command line string. Index 0 means
109
  ///     the cursor is at the start of the line. The completion starts from
110
  ///     this cursor position.
111
  ///
112
  /// \param [out] result
113
  ///     The CompletionResult that will be filled with the results after this
114
  ///     request has been handled.
115
  CompletionRequest(llvm::StringRef command_line, unsigned raw_cursor_pos,
116
                    CompletionResult &result);
117
118
  /// Returns the raw user input used to create this CompletionRequest cut off
119
  /// at the cursor position. The cursor will be at the end of the raw line.
120
4
  llvm::StringRef GetRawLine() const {
121
4
    return m_command.substr(0, GetRawCursorPos());
122
4
  }
123
124
  /// Returns the full raw user input used to create this CompletionRequest.
125
  /// This string is not cut off at the cursor position and will include
126
  /// characters behind the cursor position.
127
  ///
128
  /// You should most likely *not* use this function unless the characters
129
  /// behind the cursor position influence the completion.
130
59
  llvm::StringRef GetRawLineWithUnusedSuffix() const { return m_command; }
131
132
63
  unsigned GetRawCursorPos() const { return m_raw_cursor_pos; }
133
134
6.35k
  const Args &GetParsedLine() const { return m_parsed_line; }
135
136
3.15k
  Args &GetParsedLine() { return m_parsed_line; }
137
138
306
  const Args::ArgEntry &GetParsedArg() {
139
306
    return GetParsedLine()[GetCursorIndex()];
140
306
  }
141
142
  /// Drops the first argument from the argument list.
143
587
  void ShiftArguments() {
144
587
    m_cursor_index--;
145
587
    m_parsed_line.Shift();
146
587
  }
147
148
  /// Adds an empty argument at the end of the argument list and moves
149
  /// the cursor to this new argument.
150
152
  void AppendEmptyArgument() {
151
152
    m_parsed_line.AppendArgument(llvm::StringRef());
152
152
    m_cursor_index++;
153
152
    m_cursor_char_position = 0;
154
152
  }
155
156
7.93k
  size_t GetCursorIndex() const { return m_cursor_index; }
157
158
  /// Adds a possible completion string. If the completion was already
159
  /// suggested before, it will not be added to the list of results. A copy of
160
  /// the suggested completion is stored, so the given string can be free'd
161
  /// afterwards.
162
  ///
163
  /// \param completion The suggested completion.
164
  /// \param description An optional description of the completion string. The
165
  ///     description will be displayed to the user alongside the completion.
166
  /// \param mode The CompletionMode for this completion.
167
  void AddCompletion(llvm::StringRef completion,
168
                     llvm::StringRef description = "",
169
2.96k
                     CompletionMode mode = CompletionMode::Normal) {
170
2.96k
    m_result.AddResult(completion, description, mode);
171
2.96k
  }
172
173
  /// Adds a possible completion string if the completion would complete the
174
  /// current argument.
175
  ///
176
  /// \param completion The suggested completion.
177
  /// \param description An optional description of the completion string. The
178
  ///     description will be displayed to the user alongside the completion.
179
  template <CompletionMode M = CompletionMode::Normal>
180
  void TryCompleteCurrentArg(llvm::StringRef completion,
181
5.65k
                             llvm::StringRef description = "") {
182
    // Trying to rewrite the whole line while checking for the current
183
    // argument never makes sense. Completion modes are always hardcoded, so
184
    // this can be a static_assert.
185
5.65k
    static_assert(M != CompletionMode::RewriteLine,
186
5.65k
                  "Shouldn't rewrite line with this function");
187
5.65k
    if (completion.startswith(GetCursorArgumentPrefix()))
188
2.12k
      AddCompletion(completion, description, M);
189
5.65k
  }
190
191
  /// Adds multiple possible completion strings.
192
  ///
193
  /// \param completions The list of completions.
194
  ///
195
  /// \see AddCompletion
196
288
  void AddCompletions(const StringList &completions) {
197
288
    for (const std::string &completion : completions)
198
1
      AddCompletion(completion);
199
288
  }
200
201
  /// Adds multiple possible completion strings alongside their descriptions.
202
  ///
203
  /// The number of completions and descriptions must be identical.
204
  ///
205
  /// \param completions The list of completions.
206
  /// \param descriptions The list of descriptions.
207
  ///
208
  /// \see AddCompletion
209
  void AddCompletions(const StringList &completions,
210
26
                      const StringList &descriptions) {
211
26
    lldbassert(completions.GetSize() == descriptions.GetSize());
212
162
    
for (std::size_t i = 0; 26
i < completions.GetSize();
++i136
)
213
136
      AddCompletion(completions.GetStringAtIndex(i),
214
136
                    descriptions.GetStringAtIndex(i));
215
26
  }
216
217
6.35k
  llvm::StringRef GetCursorArgumentPrefix() const {
218
6.35k
    return GetParsedLine().GetArgumentAtIndex(GetCursorIndex());
219
6.35k
  }
220
221
private:
222
  /// The raw command line we are supposed to complete.
223
  llvm::StringRef m_command;
224
  /// The cursor position in m_command.
225
  unsigned m_raw_cursor_pos;
226
  /// The command line parsed as arguments.
227
  Args m_parsed_line;
228
  /// The index of the argument in which the completion cursor is.
229
  size_t m_cursor_index;
230
  /// The cursor position in the argument indexed by m_cursor_index.
231
  size_t m_cursor_char_position;
232
233
  /// The result this request is supposed to fill out.
234
  /// We keep this object private to ensure that no backend can in any way
235
  /// depend on already calculated completions (which would make debugging and
236
  /// testing them much more complicated).
237
  CompletionResult &m_result;
238
};
239
240
} // namespace lldb_private
241
242
#endif // LLDB_UTILITY_COMPLETIONREQUEST_H