blob: 9e277db0c5e004e9debd659bc6615dcb6b35535e [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 Turner990e3cd2017-03-07 03:43:17 +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 Turner990e3cd2017-03-07 03:43:17 +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
141 bool isa_directory = false;
Zachary Turner990e3cd2017-03-07 03:43:17 +0000142 if (file_type == llvm::sys::fs::file_type::directory_file)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000143 isa_directory = true;
Zachary Turner990e3cd2017-03-07 03:43:17 +0000144 else if (file_type == llvm::sys::fs::file_type::symlink_file) {
145 if (llvm::sys::fs::is_directory(partial_name_copy))
Kate Stoneb9c1b512016-09-06 20:57:50 +0000146 isa_directory = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000147 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000148
149 if (isa_directory) {
150 *parameters->saw_directory = true;
151 size_t len = strlen(parameters->partial_name_copy);
152 partial_name_copy[len] = '/';
153 partial_name_copy[len + 1] = '\0';
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000154 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000155 if (parameters->only_directories && !isa_directory)
156 return FileSpec::eEnumerateDirectoryResultNext;
157 parameters->matches->AppendString(partial_name_copy);
158 }
159
160 return FileSpec::eEnumerateDirectoryResultNext;
161}
162
Zachary Turner4aa87532016-11-17 01:37:42 +0000163static int DiskFilesOrDirectories(llvm::StringRef partial_file_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000164 bool only_directories, bool &saw_directory,
165 StringList &matches) {
166 // I'm going to use the "glob" function with GLOB_TILDE for user directory
167 // expansion.
168 // If it is not defined on your host system, you'll need to implement it
169 // yourself...
170
Zachary Turner4aa87532016-11-17 01:37:42 +0000171 size_t partial_name_len = partial_file_name.size();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000172
173 if (partial_name_len >= PATH_MAX)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000174 return matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000175
Kate Stoneb9c1b512016-09-06 20:57:50 +0000176 // This copy of the string will be cut up into the directory part, and the
Zachary Turner4aa87532016-11-17 01:37:42 +0000177 // remainder. end_ptr below will point to the place of the remainder in this
178 // string. Then when we've resolved the containing directory, and opened it,
179 // we'll read the directory contents and overwrite the partial_name_copy
180 // starting from end_ptr with each of the matches. Thus we will preserve the
181 // form the user originally typed.
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000182
Kate Stoneb9c1b512016-09-06 20:57:50 +0000183 char partial_name_copy[PATH_MAX];
Zachary Turner4aa87532016-11-17 01:37:42 +0000184 memcpy(partial_name_copy, partial_file_name.data(), partial_name_len);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000185 partial_name_copy[partial_name_len] = '\0';
186
187 // We'll need to save a copy of the remainder for comparison, which we do
188 // here.
189 char remainder[PATH_MAX];
190
191 // end_ptr will point past the last / in partial_name_copy, or if there is no
192 // slash to the beginning of the string.
193 char *end_ptr;
194
195 end_ptr = strrchr(partial_name_copy, '/');
196
197 // This will store the resolved form of the containing directory
198 llvm::SmallString<64> containing_part;
199
200 if (end_ptr == nullptr) {
201 // There's no directory. If the thing begins with a "~" then this is a bare
202 // user name.
203 if (*partial_name_copy == '~') {
204 // Nothing here but the user name. We could just put a slash on the end,
205 // but for completeness sake we'll resolve the user name and only put a
206 // slash
207 // on the end if it exists.
208 llvm::SmallString<64> resolved_username(partial_name_copy);
209 FileSpec::ResolveUsername(resolved_username);
210
211 // Not sure how this would happen, a username longer than PATH_MAX?
212 // Still...
213 if (resolved_username.size() == 0) {
214 // The user name didn't resolve, let's look in the password database for
215 // matches.
216 // The user name database contains duplicates, and is not in
217 // alphabetical order, so
218 // we'll use a set to manage that for us.
219 FileSpec::ResolvePartialUsername(partial_name_copy, matches);
220 if (matches.GetSize() > 0)
221 saw_directory = true;
222 return matches.GetSize();
223 } else {
224 // The thing exists, put a '/' on the end, and return it...
225 // FIXME: complete user names here:
226 partial_name_copy[partial_name_len] = '/';
227 partial_name_copy[partial_name_len + 1] = '\0';
228 matches.AppendString(partial_name_copy);
229 saw_directory = true;
230 return matches.GetSize();
231 }
232 } else {
233 // The containing part is the CWD, and the whole string is the remainder.
234 containing_part = ".";
235 strcpy(remainder, partial_name_copy);
236 end_ptr = partial_name_copy;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000237 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000238 } else {
239 if (end_ptr == partial_name_copy) {
240 // We're completing a file or directory in the root volume.
241 containing_part = "/";
242 } else {
243 containing_part.append(partial_name_copy, end_ptr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000244 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000245 // Push end_ptr past the final "/" and set remainder.
246 end_ptr++;
247 strcpy(remainder, end_ptr);
248 }
249
250 // Look for a user name in the containing part, and if it's there, resolve it
251 // and stick the
252 // result back into the containing_part:
253
254 if (*partial_name_copy == '~') {
255 FileSpec::ResolveUsername(containing_part);
256 // User name doesn't exist, we're not getting any further...
257 if (containing_part.empty())
258 return matches.GetSize();
259 }
260
261 // Okay, containing_part is now the directory we want to open and look for
262 // files:
263
264 size_t baselen = end_ptr - partial_name_copy;
265
266 DiskFilesOrDirectoriesBaton parameters;
267 parameters.remainder = remainder;
268 parameters.partial_name_copy = partial_name_copy;
269 parameters.only_directories = only_directories;
270 parameters.saw_directory = &saw_directory;
271 parameters.matches = &matches;
272 parameters.end_ptr = end_ptr;
273 parameters.baselen = baselen;
274
275 FileSpec::EnumerateDirectory(containing_part.c_str(), true, true, true,
276 DiskFilesOrDirectoriesCallback, &parameters);
277
278 return matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000279}
280
Kate Stoneb9c1b512016-09-06 20:57:50 +0000281int CommandCompletions::DiskFiles(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000282 llvm::StringRef partial_file_name,
Greg Claytonf21fead2013-05-14 23:43:18 +0000283 int match_start_point,
284 int max_return_elements,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000285 SearchFilter *searcher, bool &word_complete,
286 StringList &matches) {
287 int ret_val =
288 DiskFilesOrDirectories(partial_file_name, false, word_complete, matches);
289 word_complete = !word_complete;
290 return ret_val;
291}
292
293int CommandCompletions::DiskDirectories(
Zachary Turner4aa87532016-11-17 01:37:42 +0000294 CommandInterpreter &interpreter, llvm::StringRef partial_file_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000295 int match_start_point, int max_return_elements, SearchFilter *searcher,
296 bool &word_complete, StringList &matches) {
297 int ret_val =
298 DiskFilesOrDirectories(partial_file_name, true, word_complete, matches);
299 word_complete = false;
300 return ret_val;
301}
302
303int CommandCompletions::Modules(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000304 llvm::StringRef partial_file_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000305 int match_start_point, int max_return_elements,
306 SearchFilter *searcher, bool &word_complete,
307 StringList &matches) {
308 word_complete = true;
309 ModuleCompleter completer(interpreter, partial_file_name, match_start_point,
310 max_return_elements, matches);
311
312 if (searcher == nullptr) {
313 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
314 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
315 completer.DoCompletion(&null_searcher);
316 } else {
317 completer.DoCompletion(searcher);
318 }
319 return matches.GetSize();
320}
321
322int CommandCompletions::Symbols(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000323 llvm::StringRef partial_file_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000324 int match_start_point, int max_return_elements,
325 SearchFilter *searcher, bool &word_complete,
326 StringList &matches) {
327 word_complete = true;
328 SymbolCompleter completer(interpreter, partial_file_name, match_start_point,
329 max_return_elements, matches);
330
331 if (searcher == nullptr) {
332 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
333 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
334 completer.DoCompletion(&null_searcher);
335 } else {
336 completer.DoCompletion(searcher);
337 }
338 return matches.GetSize();
339}
340
341int CommandCompletions::SettingsNames(
Zachary Turner4aa87532016-11-17 01:37:42 +0000342 CommandInterpreter &interpreter, llvm::StringRef partial_setting_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000343 int match_start_point, int max_return_elements, SearchFilter *searcher,
344 bool &word_complete, StringList &matches) {
345 // Cache the full setting name list
346 static StringList g_property_names;
347 if (g_property_names.GetSize() == 0) {
348 // Generate the full setting name list on demand
349 lldb::OptionValuePropertiesSP properties_sp(
350 interpreter.GetDebugger().GetValueProperties());
351 if (properties_sp) {
352 StreamString strm;
353 properties_sp->DumpValue(nullptr, strm, OptionValue::eDumpOptionName);
354 const std::string &str = strm.GetString();
355 g_property_names.SplitIntoLines(str.c_str(), str.size());
356 }
357 }
358
359 size_t exact_matches_idx = SIZE_MAX;
360 const size_t num_matches = g_property_names.AutoComplete(
361 partial_setting_name, matches, exact_matches_idx);
362 word_complete = exact_matches_idx != SIZE_MAX;
363 return num_matches;
364}
365
366int CommandCompletions::PlatformPluginNames(
Zachary Turner4aa87532016-11-17 01:37:42 +0000367 CommandInterpreter &interpreter, llvm::StringRef partial_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000368 int match_start_point, int max_return_elements, SearchFilter *searcher,
369 bool &word_complete, lldb_private::StringList &matches) {
370 const uint32_t num_matches =
371 PluginManager::AutoCompletePlatformName(partial_name, matches);
372 word_complete = num_matches == 1;
373 return num_matches;
374}
375
376int CommandCompletions::ArchitectureNames(
Zachary Turner4aa87532016-11-17 01:37:42 +0000377 CommandInterpreter &interpreter, llvm::StringRef partial_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000378 int match_start_point, int max_return_elements, SearchFilter *searcher,
379 bool &word_complete, lldb_private::StringList &matches) {
380 const uint32_t num_matches = ArchSpec::AutoComplete(partial_name, matches);
381 word_complete = num_matches == 1;
382 return num_matches;
383}
384
385int CommandCompletions::VariablePath(
Zachary Turner4aa87532016-11-17 01:37:42 +0000386 CommandInterpreter &interpreter, llvm::StringRef partial_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000387 int match_start_point, int max_return_elements, SearchFilter *searcher,
388 bool &word_complete, lldb_private::StringList &matches) {
389 return Variable::AutoComplete(interpreter.GetExecutionContext(), partial_name,
390 matches, word_complete);
Greg Claytonf21fead2013-05-14 23:43:18 +0000391}
392
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000393CommandCompletions::Completer::Completer(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000394 llvm::StringRef completion_str,
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000395 int match_start_point,
396 int max_return_elements,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000397 StringList &matches)
398 : m_interpreter(interpreter), m_completion_str(completion_str),
399 m_match_start_point(match_start_point),
400 m_max_return_elements(max_return_elements), m_matches(matches) {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000401
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000402CommandCompletions::Completer::~Completer() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000403
404//----------------------------------------------------------------------
405// SourceFileCompleter
406//----------------------------------------------------------------------
407
Kate Stoneb9c1b512016-09-06 20:57:50 +0000408CommandCompletions::SourceFileCompleter::SourceFileCompleter(
409 CommandInterpreter &interpreter, bool include_support_files,
Zachary Turner4aa87532016-11-17 01:37:42 +0000410 llvm::StringRef completion_str, int match_start_point,
411 int max_return_elements, StringList &matches)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000412 : CommandCompletions::Completer(interpreter, completion_str,
413 match_start_point, max_return_elements,
414 matches),
415 m_include_support_files(include_support_files), m_matching_files() {
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000416 FileSpec partial_spec(m_completion_str, false);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000417 m_file_name = partial_spec.GetFilename().GetCString();
418 m_dir_name = partial_spec.GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000419}
420
Kate Stoneb9c1b512016-09-06 20:57:50 +0000421Searcher::Depth CommandCompletions::SourceFileCompleter::GetDepth() {
422 return eDepthCompUnit;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000423}
424
425Searcher::CallbackReturn
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000426CommandCompletions::SourceFileCompleter::SearchCallback(SearchFilter &filter,
427 SymbolContext &context,
428 Address *addr,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000429 bool complete) {
430 if (context.comp_unit != nullptr) {
431 if (m_include_support_files) {
432 FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
433 for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++) {
434 const FileSpec &sfile_spec =
435 supporting_files.GetFileSpecAtIndex(sfiles);
436 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
437 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
438 bool match = false;
439 if (m_file_name && sfile_file_name &&
440 strstr(sfile_file_name, m_file_name) == sfile_file_name)
441 match = true;
442 if (match && m_dir_name && sfile_dir_name &&
443 strstr(sfile_dir_name, m_dir_name) != sfile_dir_name)
444 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000445
Kate Stoneb9c1b512016-09-06 20:57:50 +0000446 if (match) {
447 m_matching_files.AppendIfUnique(sfile_spec);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000448 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000449 }
450 } else {
451 const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
452 const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000453
Kate Stoneb9c1b512016-09-06 20:57:50 +0000454 bool match = false;
455 if (m_file_name && cur_file_name &&
456 strstr(cur_file_name, m_file_name) == cur_file_name)
457 match = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000458
Kate Stoneb9c1b512016-09-06 20:57:50 +0000459 if (match && m_dir_name && cur_dir_name &&
460 strstr(cur_dir_name, m_dir_name) != cur_dir_name)
461 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000462
Kate Stoneb9c1b512016-09-06 20:57:50 +0000463 if (match) {
464 m_matching_files.AppendIfUnique(context.comp_unit);
465 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000466 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000467 }
468 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000469}
470
471size_t
Kate Stoneb9c1b512016-09-06 20:57:50 +0000472CommandCompletions::SourceFileCompleter::DoCompletion(SearchFilter *filter) {
473 filter->Search(*this);
474 // Now convert the filelist to completions:
475 for (size_t i = 0; i < m_matching_files.GetSize(); i++) {
476 m_matches.AppendString(
477 m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
478 }
479 return m_matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000480}
481
482//----------------------------------------------------------------------
483// SymbolCompleter
484//----------------------------------------------------------------------
485
Kate Stoneb9c1b512016-09-06 20:57:50 +0000486static bool regex_chars(const char comp) {
487 return (comp == '[' || comp == ']' || comp == '(' || comp == ')' ||
488 comp == '{' || comp == '}' || comp == '+' || comp == '.' ||
489 comp == '*' || comp == '|' || comp == '^' || comp == '$' ||
490 comp == '\\' || comp == '?');
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000491}
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000492
Kate Stoneb9c1b512016-09-06 20:57:50 +0000493CommandCompletions::SymbolCompleter::SymbolCompleter(
Zachary Turner4aa87532016-11-17 01:37:42 +0000494 CommandInterpreter &interpreter, llvm::StringRef completion_str,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000495 int match_start_point, int max_return_elements, StringList &matches)
496 : CommandCompletions::Completer(interpreter, completion_str,
497 match_start_point, max_return_elements,
498 matches) {
499 std::string regex_str;
Zachary Turner4aa87532016-11-17 01:37:42 +0000500 if (!completion_str.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000501 regex_str.append("^");
502 regex_str.append(completion_str);
503 } else {
504 // Match anything since the completion string is empty
505 regex_str.append(".");
506 }
507 std::string::iterator pos =
508 find_if(regex_str.begin() + 1, regex_str.end(), regex_chars);
509 while (pos < regex_str.end()) {
510 pos = regex_str.insert(pos, '\\');
511 pos = find_if(pos + 2, regex_str.end(), regex_chars);
512 }
Zachary Turner95eae422016-09-21 16:01:28 +0000513 m_regex.Compile(regex_str);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000514}
515
Kate Stoneb9c1b512016-09-06 20:57:50 +0000516Searcher::Depth CommandCompletions::SymbolCompleter::GetDepth() {
517 return eDepthModule;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000518}
519
Kate Stoneb9c1b512016-09-06 20:57:50 +0000520Searcher::CallbackReturn CommandCompletions::SymbolCompleter::SearchCallback(
521 SearchFilter &filter, SymbolContext &context, Address *addr,
522 bool complete) {
523 if (context.module_sp) {
524 SymbolContextList sc_list;
525 const bool include_symbols = true;
526 const bool include_inlines = true;
527 const bool append = true;
528 context.module_sp->FindFunctions(m_regex, include_symbols, include_inlines,
529 append, sc_list);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000530
Kate Stoneb9c1b512016-09-06 20:57:50 +0000531 SymbolContext sc;
532 // Now add the functions & symbols to the list - only add if unique:
533 for (uint32_t i = 0; i < sc_list.GetSize(); i++) {
534 if (sc_list.GetContextAtIndex(i, sc)) {
535 ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
536 if (!func_name.IsEmpty())
537 m_match_set.insert(func_name);
538 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000539 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000540 }
541 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000542}
543
Kate Stoneb9c1b512016-09-06 20:57:50 +0000544size_t CommandCompletions::SymbolCompleter::DoCompletion(SearchFilter *filter) {
545 filter->Search(*this);
546 collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
547 for (pos = m_match_set.begin(); pos != end; pos++)
548 m_matches.AppendString((*pos).GetCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000549
Kate Stoneb9c1b512016-09-06 20:57:50 +0000550 return m_matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000551}
552
553//----------------------------------------------------------------------
554// ModuleCompleter
555//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000556CommandCompletions::ModuleCompleter::ModuleCompleter(
Zachary Turner4aa87532016-11-17 01:37:42 +0000557 CommandInterpreter &interpreter, llvm::StringRef completion_str,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000558 int match_start_point, int max_return_elements, StringList &matches)
559 : CommandCompletions::Completer(interpreter, completion_str,
560 match_start_point, max_return_elements,
561 matches) {
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000562 FileSpec partial_spec(m_completion_str, false);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000563 m_file_name = partial_spec.GetFilename().GetCString();
564 m_dir_name = partial_spec.GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000565}
566
Kate Stoneb9c1b512016-09-06 20:57:50 +0000567Searcher::Depth CommandCompletions::ModuleCompleter::GetDepth() {
568 return eDepthModule;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000569}
570
Kate Stoneb9c1b512016-09-06 20:57:50 +0000571Searcher::CallbackReturn CommandCompletions::ModuleCompleter::SearchCallback(
572 SearchFilter &filter, SymbolContext &context, Address *addr,
573 bool complete) {
574 if (context.module_sp) {
575 const char *cur_file_name =
576 context.module_sp->GetFileSpec().GetFilename().GetCString();
577 const char *cur_dir_name =
578 context.module_sp->GetFileSpec().GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000579
Kate Stoneb9c1b512016-09-06 20:57:50 +0000580 bool match = false;
581 if (m_file_name && cur_file_name &&
582 strstr(cur_file_name, m_file_name) == cur_file_name)
583 match = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000584
Kate Stoneb9c1b512016-09-06 20:57:50 +0000585 if (match && m_dir_name && cur_dir_name &&
586 strstr(cur_dir_name, m_dir_name) != cur_dir_name)
587 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000588
Kate Stoneb9c1b512016-09-06 20:57:50 +0000589 if (match) {
590 m_matches.AppendString(cur_file_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000591 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000592 }
593 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000594}
595
Kate Stoneb9c1b512016-09-06 20:57:50 +0000596size_t CommandCompletions::ModuleCompleter::DoCompletion(SearchFilter *filter) {
597 filter->Search(*this);
598 return m_matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000599}