blob: 2d24843fcccaf87e163c48b9eb84196297db3969 [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- CommandCompletions.cpp ----------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Chris Lattner30fdc8d2010-06-08 16:52:24 +000010// C Includes
Jim Ingham558ce122010-06-30 05:02:46 +000011#include <sys/stat.h>
Greg Claytonfd184262011-02-05 02:27:52 +000012#if defined(__APPLE__) || defined(__linux__)
Jim Ingham7cc478b2010-07-02 00:45:55 +000013#include <pwd.h>
Greg Claytonfd184262011-02-05 02:27:52 +000014#endif
Jim Ingham558ce122010-06-30 05:02:46 +000015
Chris Lattner30fdc8d2010-06-08 16:52:24 +000016// C++ Includes
17// Other libraries and framework includes
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +000018#include "llvm/ADT/SmallString.h"
19
Chris Lattner30fdc8d2010-06-08 16:52:24 +000020// Project includes
Greg Clayton9b62fd22011-02-01 05:15:22 +000021#include "lldb/Core/FileSpecList.h"
Greg Clayton1f746072012-08-29 21:13:06 +000022#include "lldb/Core/Module.h"
Zachary Turner190fadc2016-03-22 17:58:09 +000023#include "lldb/Core/PluginManager.h"
24#include "lldb/Host/FileSpec.h"
25#include "lldb/Host/FileSystem.h"
Greg Clayton9b62fd22011-02-01 05:15:22 +000026#include "lldb/Interpreter/Args.h"
27#include "lldb/Interpreter/CommandCompletions.h"
28#include "lldb/Interpreter/CommandInterpreter.h"
Zachary Turner633a29c2015-03-04 01:58:01 +000029#include "lldb/Interpreter/OptionValueProperties.h"
Greg Clayton1f746072012-08-29 21:13:06 +000030#include "lldb/Symbol/CompileUnit.h"
Greg Claytonf21fead2013-05-14 23:43:18 +000031#include "lldb/Symbol/Variable.h"
Greg Clayton9b62fd22011-02-01 05:15:22 +000032#include "lldb/Target/Target.h"
33#include "lldb/Utility/CleanUp.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000034
Zachary Turner190fadc2016-03-22 17:58:09 +000035#include "llvm/ADT/SmallString.h"
Zachary Turner7d86ee52017-03-08 17:56:08 +000036#include "llvm/Support/FileSystem.h"
Zachary Turner190fadc2016-03-22 17:58:09 +000037
Chris Lattner30fdc8d2010-06-08 16:52:24 +000038using namespace lldb_private;
39
40CommandCompletions::CommonCompletionElement
Kate Stoneb9c1b512016-09-06 20:57:50 +000041 CommandCompletions::g_common_completions[] = {
42 {eCustomCompletion, nullptr},
43 {eSourceFileCompletion, CommandCompletions::SourceFiles},
44 {eDiskFileCompletion, CommandCompletions::DiskFiles},
45 {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories},
46 {eSymbolCompletion, CommandCompletions::Symbols},
47 {eModuleCompletion, CommandCompletions::Modules},
48 {eSettingsNameCompletion, CommandCompletions::SettingsNames},
49 {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames},
50 {eArchitectureCompletion, CommandCompletions::ArchitectureNames},
51 {eVariablePathCompletion, CommandCompletions::VariablePath},
52 {eNoCompletion, nullptr} // This one has to be last in the list.
Chris Lattner30fdc8d2010-06-08 16:52:24 +000053};
54
Kate Stoneb9c1b512016-09-06 20:57:50 +000055bool CommandCompletions::InvokeCommonCompletionCallbacks(
56 CommandInterpreter &interpreter, uint32_t completion_mask,
Zachary Turner4aa87532016-11-17 01:37:42 +000057 llvm::StringRef completion_str, int match_start_point,
58 int max_return_elements, SearchFilter *searcher, bool &word_complete,
59 StringList &matches) {
Kate Stoneb9c1b512016-09-06 20:57:50 +000060 bool handled = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000061
Kate Stoneb9c1b512016-09-06 20:57:50 +000062 if (completion_mask & eCustomCompletion)
63 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000064
Kate Stoneb9c1b512016-09-06 20:57:50 +000065 for (int i = 0;; i++) {
66 if (g_common_completions[i].type == eNoCompletion)
67 break;
68 else if ((g_common_completions[i].type & completion_mask) ==
69 g_common_completions[i].type &&
70 g_common_completions[i].callback != nullptr) {
71 handled = true;
72 g_common_completions[i].callback(interpreter, completion_str,
73 match_start_point, max_return_elements,
74 searcher, word_complete, matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000075 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000076 }
77 return handled;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000078}
79
Kate Stoneb9c1b512016-09-06 20:57:50 +000080int CommandCompletions::SourceFiles(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +000081 llvm::StringRef partial_file_name,
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +000082 int match_start_point,
83 int max_return_elements,
Kate Stoneb9c1b512016-09-06 20:57:50 +000084 SearchFilter *searcher, bool &word_complete,
85 StringList &matches) {
86 word_complete = true;
87 // Find some way to switch "include support files..."
88 SourceFileCompleter completer(interpreter, false, partial_file_name,
89 match_start_point, max_return_elements,
90 matches);
91
92 if (searcher == nullptr) {
93 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
94 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
95 completer.DoCompletion(&null_searcher);
96 } else {
97 completer.DoCompletion(searcher);
98 }
99 return matches.GetSize();
Jim Ingham558ce122010-06-30 05:02:46 +0000100}
101
Kate Stoneb9c1b512016-09-06 20:57:50 +0000102typedef struct DiskFilesOrDirectoriesBaton {
103 const char *remainder;
104 char *partial_name_copy;
105 bool only_directories;
106 bool *saw_directory;
107 StringList *matches;
108 char *end_ptr;
109 size_t baselen;
110} DiskFilesOrDirectoriesBaton;
111
112FileSpec::EnumerateDirectoryResult
Zachary Turner7d86ee52017-03-08 17:56:08 +0000113DiskFilesOrDirectoriesCallback(void *baton, llvm::sys::fs::file_type file_type,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000114 const FileSpec &spec) {
115 const char *name = spec.GetFilename().AsCString();
116
117 const DiskFilesOrDirectoriesBaton *parameters =
118 (DiskFilesOrDirectoriesBaton *)baton;
119 char *end_ptr = parameters->end_ptr;
120 char *partial_name_copy = parameters->partial_name_copy;
121 const char *remainder = parameters->remainder;
122
123 // Omit ".", ".." and any . files if the match string doesn't start with .
124 if (name[0] == '.') {
125 if (name[1] == '\0')
126 return FileSpec::eEnumerateDirectoryResultNext;
127 else if (name[1] == '.' && name[2] == '\0')
128 return FileSpec::eEnumerateDirectoryResultNext;
129 else if (remainder[0] != '.')
130 return FileSpec::eEnumerateDirectoryResultNext;
131 }
132
133 // If we found a directory, we put a "/" at the end of the name.
134
135 if (remainder[0] == '\0' || strstr(name, remainder) == name) {
136 if (strlen(name) + parameters->baselen >= PATH_MAX)
137 return FileSpec::eEnumerateDirectoryResultNext;
138
139 strcpy(end_ptr, name);
140
Zachary Turner7d86ee52017-03-08 17:56:08 +0000141 namespace fs = llvm::sys::fs;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000142 bool isa_directory = false;
Zachary Turner7d86ee52017-03-08 17:56:08 +0000143 if (file_type == fs::file_type::directory_file)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000144 isa_directory = true;
Zachary Turner7d86ee52017-03-08 17:56:08 +0000145 else if (file_type == fs::file_type::symlink_file)
146 isa_directory = fs::is_directory(partial_name_copy);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000147
148 if (isa_directory) {
149 *parameters->saw_directory = true;
150 size_t len = strlen(parameters->partial_name_copy);
151 partial_name_copy[len] = '/';
152 partial_name_copy[len + 1] = '\0';
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000153 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000154 if (parameters->only_directories && !isa_directory)
155 return FileSpec::eEnumerateDirectoryResultNext;
156 parameters->matches->AppendString(partial_name_copy);
157 }
158
159 return FileSpec::eEnumerateDirectoryResultNext;
160}
161
Zachary Turner4aa87532016-11-17 01:37:42 +0000162static int DiskFilesOrDirectories(llvm::StringRef partial_file_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000163 bool only_directories, bool &saw_directory,
164 StringList &matches) {
165 // I'm going to use the "glob" function with GLOB_TILDE for user directory
166 // expansion.
167 // If it is not defined on your host system, you'll need to implement it
168 // yourself...
169
Zachary Turner4aa87532016-11-17 01:37:42 +0000170 size_t partial_name_len = partial_file_name.size();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000171
172 if (partial_name_len >= PATH_MAX)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000173 return matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000174
Kate Stoneb9c1b512016-09-06 20:57:50 +0000175 // This copy of the string will be cut up into the directory part, and the
Zachary Turner4aa87532016-11-17 01:37:42 +0000176 // remainder. end_ptr below will point to the place of the remainder in this
177 // string. Then when we've resolved the containing directory, and opened it,
178 // we'll read the directory contents and overwrite the partial_name_copy
179 // starting from end_ptr with each of the matches. Thus we will preserve the
180 // form the user originally typed.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000181
Kate Stoneb9c1b512016-09-06 20:57:50 +0000182 char partial_name_copy[PATH_MAX];
Zachary Turner4aa87532016-11-17 01:37:42 +0000183 memcpy(partial_name_copy, partial_file_name.data(), partial_name_len);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000184 partial_name_copy[partial_name_len] = '\0';
185
186 // We'll need to save a copy of the remainder for comparison, which we do
187 // here.
188 char remainder[PATH_MAX];
189
190 // end_ptr will point past the last / in partial_name_copy, or if there is no
191 // slash to the beginning of the string.
192 char *end_ptr;
193
194 end_ptr = strrchr(partial_name_copy, '/');
195
196 // This will store the resolved form of the containing directory
197 llvm::SmallString<64> containing_part;
198
199 if (end_ptr == nullptr) {
200 // There's no directory. If the thing begins with a "~" then this is a bare
201 // user name.
202 if (*partial_name_copy == '~') {
203 // Nothing here but the user name. We could just put a slash on the end,
204 // but for completeness sake we'll resolve the user name and only put a
205 // slash
206 // on the end if it exists.
207 llvm::SmallString<64> resolved_username(partial_name_copy);
208 FileSpec::ResolveUsername(resolved_username);
209
210 // Not sure how this would happen, a username longer than PATH_MAX?
211 // Still...
212 if (resolved_username.size() == 0) {
213 // The user name didn't resolve, let's look in the password database for
214 // matches.
215 // The user name database contains duplicates, and is not in
216 // alphabetical order, so
217 // we'll use a set to manage that for us.
218 FileSpec::ResolvePartialUsername(partial_name_copy, matches);
219 if (matches.GetSize() > 0)
220 saw_directory = true;
221 return matches.GetSize();
222 } else {
223 // The thing exists, put a '/' on the end, and return it...
224 // FIXME: complete user names here:
225 partial_name_copy[partial_name_len] = '/';
226 partial_name_copy[partial_name_len + 1] = '\0';
227 matches.AppendString(partial_name_copy);
228 saw_directory = true;
229 return matches.GetSize();
230 }
231 } else {
232 // The containing part is the CWD, and the whole string is the remainder.
233 containing_part = ".";
234 strcpy(remainder, partial_name_copy);
235 end_ptr = partial_name_copy;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000236 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000237 } else {
238 if (end_ptr == partial_name_copy) {
239 // We're completing a file or directory in the root volume.
240 containing_part = "/";
241 } else {
242 containing_part.append(partial_name_copy, end_ptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000243 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000244 // Push end_ptr past the final "/" and set remainder.
245 end_ptr++;
246 strcpy(remainder, end_ptr);
247 }
248
249 // Look for a user name in the containing part, and if it's there, resolve it
250 // and stick the
251 // result back into the containing_part:
252
253 if (*partial_name_copy == '~') {
254 FileSpec::ResolveUsername(containing_part);
255 // User name doesn't exist, we're not getting any further...
256 if (containing_part.empty())
257 return matches.GetSize();
258 }
259
260 // Okay, containing_part is now the directory we want to open and look for
261 // files:
262
263 size_t baselen = end_ptr - partial_name_copy;
264
265 DiskFilesOrDirectoriesBaton parameters;
266 parameters.remainder = remainder;
267 parameters.partial_name_copy = partial_name_copy;
268 parameters.only_directories = only_directories;
269 parameters.saw_directory = &saw_directory;
270 parameters.matches = &matches;
271 parameters.end_ptr = end_ptr;
272 parameters.baselen = baselen;
273
274 FileSpec::EnumerateDirectory(containing_part.c_str(), true, true, true,
275 DiskFilesOrDirectoriesCallback, &parameters);
276
277 return matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000278}
279
Kate Stoneb9c1b512016-09-06 20:57:50 +0000280int CommandCompletions::DiskFiles(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000281 llvm::StringRef partial_file_name,
Greg Claytonf21fead2013-05-14 23:43:18 +0000282 int match_start_point,
283 int max_return_elements,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000284 SearchFilter *searcher, bool &word_complete,
285 StringList &matches) {
286 int ret_val =
287 DiskFilesOrDirectories(partial_file_name, false, word_complete, matches);
288 word_complete = !word_complete;
289 return ret_val;
290}
291
292int CommandCompletions::DiskDirectories(
Zachary Turner4aa87532016-11-17 01:37:42 +0000293 CommandInterpreter &interpreter, llvm::StringRef partial_file_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000294 int match_start_point, int max_return_elements, SearchFilter *searcher,
295 bool &word_complete, StringList &matches) {
296 int ret_val =
297 DiskFilesOrDirectories(partial_file_name, true, word_complete, matches);
298 word_complete = false;
299 return ret_val;
300}
301
302int CommandCompletions::Modules(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000303 llvm::StringRef partial_file_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000304 int match_start_point, int max_return_elements,
305 SearchFilter *searcher, bool &word_complete,
306 StringList &matches) {
307 word_complete = true;
308 ModuleCompleter completer(interpreter, partial_file_name, match_start_point,
309 max_return_elements, matches);
310
311 if (searcher == nullptr) {
312 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
313 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
314 completer.DoCompletion(&null_searcher);
315 } else {
316 completer.DoCompletion(searcher);
317 }
318 return matches.GetSize();
319}
320
321int CommandCompletions::Symbols(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000322 llvm::StringRef partial_file_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000323 int match_start_point, int max_return_elements,
324 SearchFilter *searcher, bool &word_complete,
325 StringList &matches) {
326 word_complete = true;
327 SymbolCompleter completer(interpreter, partial_file_name, match_start_point,
328 max_return_elements, matches);
329
330 if (searcher == nullptr) {
331 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
332 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
333 completer.DoCompletion(&null_searcher);
334 } else {
335 completer.DoCompletion(searcher);
336 }
337 return matches.GetSize();
338}
339
340int CommandCompletions::SettingsNames(
Zachary Turner4aa87532016-11-17 01:37:42 +0000341 CommandInterpreter &interpreter, llvm::StringRef partial_setting_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000342 int match_start_point, int max_return_elements, SearchFilter *searcher,
343 bool &word_complete, StringList &matches) {
344 // Cache the full setting name list
345 static StringList g_property_names;
346 if (g_property_names.GetSize() == 0) {
347 // Generate the full setting name list on demand
348 lldb::OptionValuePropertiesSP properties_sp(
349 interpreter.GetDebugger().GetValueProperties());
350 if (properties_sp) {
351 StreamString strm;
352 properties_sp->DumpValue(nullptr, strm, OptionValue::eDumpOptionName);
353 const std::string &str = strm.GetString();
354 g_property_names.SplitIntoLines(str.c_str(), str.size());
355 }
356 }
357
358 size_t exact_matches_idx = SIZE_MAX;
359 const size_t num_matches = g_property_names.AutoComplete(
360 partial_setting_name, matches, exact_matches_idx);
361 word_complete = exact_matches_idx != SIZE_MAX;
362 return num_matches;
363}
364
365int CommandCompletions::PlatformPluginNames(
Zachary Turner4aa87532016-11-17 01:37:42 +0000366 CommandInterpreter &interpreter, llvm::StringRef partial_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000367 int match_start_point, int max_return_elements, SearchFilter *searcher,
368 bool &word_complete, lldb_private::StringList &matches) {
369 const uint32_t num_matches =
370 PluginManager::AutoCompletePlatformName(partial_name, matches);
371 word_complete = num_matches == 1;
372 return num_matches;
373}
374
375int CommandCompletions::ArchitectureNames(
Zachary Turner4aa87532016-11-17 01:37:42 +0000376 CommandInterpreter &interpreter, llvm::StringRef partial_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000377 int match_start_point, int max_return_elements, SearchFilter *searcher,
378 bool &word_complete, lldb_private::StringList &matches) {
379 const uint32_t num_matches = ArchSpec::AutoComplete(partial_name, matches);
380 word_complete = num_matches == 1;
381 return num_matches;
382}
383
384int CommandCompletions::VariablePath(
Zachary Turner4aa87532016-11-17 01:37:42 +0000385 CommandInterpreter &interpreter, llvm::StringRef partial_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000386 int match_start_point, int max_return_elements, SearchFilter *searcher,
387 bool &word_complete, lldb_private::StringList &matches) {
388 return Variable::AutoComplete(interpreter.GetExecutionContext(), partial_name,
389 matches, word_complete);
Greg Claytonf21fead2013-05-14 23:43:18 +0000390}
391
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000392CommandCompletions::Completer::Completer(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000393 llvm::StringRef completion_str,
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000394 int match_start_point,
395 int max_return_elements,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000396 StringList &matches)
397 : m_interpreter(interpreter), m_completion_str(completion_str),
398 m_match_start_point(match_start_point),
399 m_max_return_elements(max_return_elements), m_matches(matches) {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000400
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000401CommandCompletions::Completer::~Completer() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000402
403//----------------------------------------------------------------------
404// SourceFileCompleter
405//----------------------------------------------------------------------
406
Kate Stoneb9c1b512016-09-06 20:57:50 +0000407CommandCompletions::SourceFileCompleter::SourceFileCompleter(
408 CommandInterpreter &interpreter, bool include_support_files,
Zachary Turner4aa87532016-11-17 01:37:42 +0000409 llvm::StringRef completion_str, int match_start_point,
410 int max_return_elements, StringList &matches)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000411 : CommandCompletions::Completer(interpreter, completion_str,
412 match_start_point, max_return_elements,
413 matches),
414 m_include_support_files(include_support_files), m_matching_files() {
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000415 FileSpec partial_spec(m_completion_str, false);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000416 m_file_name = partial_spec.GetFilename().GetCString();
417 m_dir_name = partial_spec.GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000418}
419
Kate Stoneb9c1b512016-09-06 20:57:50 +0000420Searcher::Depth CommandCompletions::SourceFileCompleter::GetDepth() {
421 return eDepthCompUnit;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000422}
423
424Searcher::CallbackReturn
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000425CommandCompletions::SourceFileCompleter::SearchCallback(SearchFilter &filter,
426 SymbolContext &context,
427 Address *addr,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000428 bool complete) {
429 if (context.comp_unit != nullptr) {
430 if (m_include_support_files) {
431 FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
432 for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++) {
433 const FileSpec &sfile_spec =
434 supporting_files.GetFileSpecAtIndex(sfiles);
435 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
436 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
437 bool match = false;
438 if (m_file_name && sfile_file_name &&
439 strstr(sfile_file_name, m_file_name) == sfile_file_name)
440 match = true;
441 if (match && m_dir_name && sfile_dir_name &&
442 strstr(sfile_dir_name, m_dir_name) != sfile_dir_name)
443 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000444
Kate Stoneb9c1b512016-09-06 20:57:50 +0000445 if (match) {
446 m_matching_files.AppendIfUnique(sfile_spec);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000447 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000448 }
449 } else {
450 const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
451 const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000452
Kate Stoneb9c1b512016-09-06 20:57:50 +0000453 bool match = false;
454 if (m_file_name && cur_file_name &&
455 strstr(cur_file_name, m_file_name) == cur_file_name)
456 match = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000457
Kate Stoneb9c1b512016-09-06 20:57:50 +0000458 if (match && m_dir_name && cur_dir_name &&
459 strstr(cur_dir_name, m_dir_name) != cur_dir_name)
460 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000461
Kate Stoneb9c1b512016-09-06 20:57:50 +0000462 if (match) {
463 m_matching_files.AppendIfUnique(context.comp_unit);
464 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000465 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000466 }
467 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000468}
469
470size_t
Kate Stoneb9c1b512016-09-06 20:57:50 +0000471CommandCompletions::SourceFileCompleter::DoCompletion(SearchFilter *filter) {
472 filter->Search(*this);
473 // Now convert the filelist to completions:
474 for (size_t i = 0; i < m_matching_files.GetSize(); i++) {
475 m_matches.AppendString(
476 m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
477 }
478 return m_matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000479}
480
481//----------------------------------------------------------------------
482// SymbolCompleter
483//----------------------------------------------------------------------
484
Kate Stoneb9c1b512016-09-06 20:57:50 +0000485static bool regex_chars(const char comp) {
486 return (comp == '[' || comp == ']' || comp == '(' || comp == ')' ||
487 comp == '{' || comp == '}' || comp == '+' || comp == '.' ||
488 comp == '*' || comp == '|' || comp == '^' || comp == '$' ||
489 comp == '\\' || comp == '?');
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000490}
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000491
Kate Stoneb9c1b512016-09-06 20:57:50 +0000492CommandCompletions::SymbolCompleter::SymbolCompleter(
Zachary Turner4aa87532016-11-17 01:37:42 +0000493 CommandInterpreter &interpreter, llvm::StringRef completion_str,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000494 int match_start_point, int max_return_elements, StringList &matches)
495 : CommandCompletions::Completer(interpreter, completion_str,
496 match_start_point, max_return_elements,
497 matches) {
498 std::string regex_str;
Zachary Turner4aa87532016-11-17 01:37:42 +0000499 if (!completion_str.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000500 regex_str.append("^");
501 regex_str.append(completion_str);
502 } else {
503 // Match anything since the completion string is empty
504 regex_str.append(".");
505 }
506 std::string::iterator pos =
507 find_if(regex_str.begin() + 1, regex_str.end(), regex_chars);
508 while (pos < regex_str.end()) {
509 pos = regex_str.insert(pos, '\\');
510 pos = find_if(pos + 2, regex_str.end(), regex_chars);
511 }
Zachary Turner95eae422016-09-21 16:01:28 +0000512 m_regex.Compile(regex_str);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000513}
514
Kate Stoneb9c1b512016-09-06 20:57:50 +0000515Searcher::Depth CommandCompletions::SymbolCompleter::GetDepth() {
516 return eDepthModule;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000517}
518
Kate Stoneb9c1b512016-09-06 20:57:50 +0000519Searcher::CallbackReturn CommandCompletions::SymbolCompleter::SearchCallback(
520 SearchFilter &filter, SymbolContext &context, Address *addr,
521 bool complete) {
522 if (context.module_sp) {
523 SymbolContextList sc_list;
524 const bool include_symbols = true;
525 const bool include_inlines = true;
526 const bool append = true;
527 context.module_sp->FindFunctions(m_regex, include_symbols, include_inlines,
528 append, sc_list);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000529
Kate Stoneb9c1b512016-09-06 20:57:50 +0000530 SymbolContext sc;
531 // Now add the functions & symbols to the list - only add if unique:
532 for (uint32_t i = 0; i < sc_list.GetSize(); i++) {
533 if (sc_list.GetContextAtIndex(i, sc)) {
534 ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
535 if (!func_name.IsEmpty())
536 m_match_set.insert(func_name);
537 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000538 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000539 }
540 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000541}
542
Kate Stoneb9c1b512016-09-06 20:57:50 +0000543size_t CommandCompletions::SymbolCompleter::DoCompletion(SearchFilter *filter) {
544 filter->Search(*this);
545 collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
546 for (pos = m_match_set.begin(); pos != end; pos++)
547 m_matches.AppendString((*pos).GetCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000548
Kate Stoneb9c1b512016-09-06 20:57:50 +0000549 return m_matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000550}
551
552//----------------------------------------------------------------------
553// ModuleCompleter
554//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000555CommandCompletions::ModuleCompleter::ModuleCompleter(
Zachary Turner4aa87532016-11-17 01:37:42 +0000556 CommandInterpreter &interpreter, llvm::StringRef completion_str,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000557 int match_start_point, int max_return_elements, StringList &matches)
558 : CommandCompletions::Completer(interpreter, completion_str,
559 match_start_point, max_return_elements,
560 matches) {
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000561 FileSpec partial_spec(m_completion_str, false);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000562 m_file_name = partial_spec.GetFilename().GetCString();
563 m_dir_name = partial_spec.GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000564}
565
Kate Stoneb9c1b512016-09-06 20:57:50 +0000566Searcher::Depth CommandCompletions::ModuleCompleter::GetDepth() {
567 return eDepthModule;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000568}
569
Kate Stoneb9c1b512016-09-06 20:57:50 +0000570Searcher::CallbackReturn CommandCompletions::ModuleCompleter::SearchCallback(
571 SearchFilter &filter, SymbolContext &context, Address *addr,
572 bool complete) {
573 if (context.module_sp) {
574 const char *cur_file_name =
575 context.module_sp->GetFileSpec().GetFilename().GetCString();
576 const char *cur_dir_name =
577 context.module_sp->GetFileSpec().GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000578
Kate Stoneb9c1b512016-09-06 20:57:50 +0000579 bool match = false;
580 if (m_file_name && cur_file_name &&
581 strstr(cur_file_name, m_file_name) == cur_file_name)
582 match = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000583
Kate Stoneb9c1b512016-09-06 20:57:50 +0000584 if (match && m_dir_name && cur_dir_name &&
585 strstr(cur_dir_name, m_dir_name) != cur_dir_name)
586 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000587
Kate Stoneb9c1b512016-09-06 20:57:50 +0000588 if (match) {
589 m_matches.AppendString(cur_file_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000590 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000591 }
592 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000593}
594
Kate Stoneb9c1b512016-09-06 20:57:50 +0000595size_t CommandCompletions::ModuleCompleter::DoCompletion(SearchFilter *filter) {
596 filter->Search(*this);
597 return m_matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000598}