blob: fd84e1c4f85738923277343081de4fe02d4c8038 [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"
Zachary Turner2cc5a182017-03-13 00:41:01 +000019#include "llvm/ADT/StringSet.h"
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +000020
Chris Lattner30fdc8d2010-06-08 16:52:24 +000021// Project includes
Greg Clayton9b62fd22011-02-01 05:15:22 +000022#include "lldb/Core/FileSpecList.h"
Greg Clayton1f746072012-08-29 21:13:06 +000023#include "lldb/Core/Module.h"
Zachary Turner190fadc2016-03-22 17:58:09 +000024#include "lldb/Core/PluginManager.h"
Zachary Turner190fadc2016-03-22 17:58:09 +000025#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"
Zachary Turner5713a052017-03-22 18:40:07 +000034#include "lldb/Utility/FileSpec.h"
Zachary Turner2f3df612017-04-06 21:28:29 +000035#include "lldb/Utility/StreamString.h"
Zachary Turner2cc5a182017-03-13 00:41:01 +000036#include "lldb/Utility/TildeExpressionResolver.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000037
Zachary Turner190fadc2016-03-22 17:58:09 +000038#include "llvm/ADT/SmallString.h"
Zachary Turner7d86ee52017-03-08 17:56:08 +000039#include "llvm/Support/FileSystem.h"
Zachary Turner2cc5a182017-03-13 00:41:01 +000040#include "llvm/Support/Path.h"
Zachary Turner190fadc2016-03-22 17:58:09 +000041
Chris Lattner30fdc8d2010-06-08 16:52:24 +000042using namespace lldb_private;
43
44CommandCompletions::CommonCompletionElement
Kate Stoneb9c1b512016-09-06 20:57:50 +000045 CommandCompletions::g_common_completions[] = {
46 {eCustomCompletion, nullptr},
47 {eSourceFileCompletion, CommandCompletions::SourceFiles},
48 {eDiskFileCompletion, CommandCompletions::DiskFiles},
49 {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories},
50 {eSymbolCompletion, CommandCompletions::Symbols},
51 {eModuleCompletion, CommandCompletions::Modules},
52 {eSettingsNameCompletion, CommandCompletions::SettingsNames},
53 {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames},
54 {eArchitectureCompletion, CommandCompletions::ArchitectureNames},
55 {eVariablePathCompletion, CommandCompletions::VariablePath},
56 {eNoCompletion, nullptr} // This one has to be last in the list.
Chris Lattner30fdc8d2010-06-08 16:52:24 +000057};
58
Kate Stoneb9c1b512016-09-06 20:57:50 +000059bool CommandCompletions::InvokeCommonCompletionCallbacks(
60 CommandInterpreter &interpreter, uint32_t completion_mask,
Zachary Turner4aa87532016-11-17 01:37:42 +000061 llvm::StringRef completion_str, int match_start_point,
62 int max_return_elements, SearchFilter *searcher, bool &word_complete,
63 StringList &matches) {
Kate Stoneb9c1b512016-09-06 20:57:50 +000064 bool handled = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000065
Kate Stoneb9c1b512016-09-06 20:57:50 +000066 if (completion_mask & eCustomCompletion)
67 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000068
Kate Stoneb9c1b512016-09-06 20:57:50 +000069 for (int i = 0;; i++) {
70 if (g_common_completions[i].type == eNoCompletion)
71 break;
72 else if ((g_common_completions[i].type & completion_mask) ==
73 g_common_completions[i].type &&
74 g_common_completions[i].callback != nullptr) {
75 handled = true;
76 g_common_completions[i].callback(interpreter, completion_str,
77 match_start_point, max_return_elements,
78 searcher, word_complete, matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000079 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000080 }
81 return handled;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000082}
83
Kate Stoneb9c1b512016-09-06 20:57:50 +000084int CommandCompletions::SourceFiles(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +000085 llvm::StringRef partial_file_name,
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +000086 int match_start_point,
87 int max_return_elements,
Kate Stoneb9c1b512016-09-06 20:57:50 +000088 SearchFilter *searcher, bool &word_complete,
89 StringList &matches) {
90 word_complete = true;
91 // Find some way to switch "include support files..."
92 SourceFileCompleter completer(interpreter, false, partial_file_name,
93 match_start_point, max_return_elements,
94 matches);
95
96 if (searcher == nullptr) {
97 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
98 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
99 completer.DoCompletion(&null_searcher);
100 } else {
101 completer.DoCompletion(searcher);
102 }
103 return matches.GetSize();
Jim Ingham558ce122010-06-30 05:02:46 +0000104}
105
Zachary Turner2cc5a182017-03-13 00:41:01 +0000106static int DiskFilesOrDirectories(const llvm::Twine &partial_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000107 bool only_directories, bool &saw_directory,
Zachary Turner2cc5a182017-03-13 00:41:01 +0000108 StringList &matches,
109 TildeExpressionResolver &Resolver) {
110 matches.Clear();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000111
Zachary Turner2cc5a182017-03-13 00:41:01 +0000112 llvm::SmallString<256> CompletionBuffer;
113 llvm::SmallString<256> Storage;
114 partial_name.toVector(CompletionBuffer);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000115
Zachary Turner2cc5a182017-03-13 00:41:01 +0000116 if (CompletionBuffer.size() >= PATH_MAX)
117 return 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000118
Zachary Turner2cc5a182017-03-13 00:41:01 +0000119 namespace fs = llvm::sys::fs;
120 namespace path = llvm::sys::path;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000121
Zachary Turner2cc5a182017-03-13 00:41:01 +0000122 llvm::StringRef SearchDir;
123 llvm::StringRef PartialItem;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000124
Zachary Turner2cc5a182017-03-13 00:41:01 +0000125 if (CompletionBuffer.startswith("~")) {
126 llvm::StringRef Buffer(CompletionBuffer);
Zachary Turner5c5091f2017-03-16 22:28:04 +0000127 size_t FirstSep =
128 Buffer.find_if([](char c) { return path::is_separator(c); });
Kate Stoneb9c1b512016-09-06 20:57:50 +0000129
Zachary Turner2cc5a182017-03-13 00:41:01 +0000130 llvm::StringRef Username = Buffer.take_front(FirstSep);
131 llvm::StringRef Remainder;
132 if (FirstSep != llvm::StringRef::npos)
133 Remainder = Buffer.drop_front(FirstSep + 1);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000134
Zachary Turner2cc5a182017-03-13 00:41:01 +0000135 llvm::SmallString<PATH_MAX> Resolved;
136 if (!Resolver.ResolveExact(Username, Resolved)) {
137 // We couldn't resolve it as a full username. If there were no slashes
138 // then this might be a partial username. We try to resolve it as such
139 // but after that, we're done regardless of any matches.
140 if (FirstSep == llvm::StringRef::npos) {
141 llvm::StringSet<> MatchSet;
142 saw_directory = Resolver.ResolvePartial(Username, MatchSet);
143 for (const auto &S : MatchSet) {
144 Resolved = S.getKey();
145 path::append(Resolved, path::get_separator());
146 matches.AppendString(Resolved);
147 }
148 saw_directory = (matches.GetSize() > 0);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000149 }
Zachary Turner0734e6a2017-03-12 20:01:37 +0000150 return matches.GetSize();
Zachary Turner2cc5a182017-03-13 00:41:01 +0000151 }
152
153 // If there was no trailing slash, then we're done as soon as we resolve the
154 // expression to the correct directory. Otherwise we need to continue
155 // looking for matches within that directory.
156 if (FirstSep == llvm::StringRef::npos) {
157 // Make sure it ends with a separator.
158 path::append(CompletionBuffer, path::get_separator());
159 saw_directory = true;
160 matches.AppendString(CompletionBuffer);
161 return 1;
162 }
163
164 // We want to keep the form the user typed, so we special case this to
165 // search in the fully resolved directory, but CompletionBuffer keeps the
166 // unmodified form that the user typed.
167 Storage = Resolved;
168 SearchDir = Resolved;
169 } else {
170 SearchDir = path::parent_path(CompletionBuffer);
Zachary Turnerd5bd3a12017-03-12 18:18:50 +0000171 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000172
Zachary Turner2cc5a182017-03-13 00:41:01 +0000173 size_t FullPrefixLen = CompletionBuffer.size();
Zachary Turner0734e6a2017-03-12 20:01:37 +0000174
Zachary Turner2cc5a182017-03-13 00:41:01 +0000175 PartialItem = path::filename(CompletionBuffer);
176 if (PartialItem == ".")
177 PartialItem = llvm::StringRef();
Zachary Turner0734e6a2017-03-12 20:01:37 +0000178
Zachary Turner426d1372017-04-15 02:44:53 +0000179 if (SearchDir.empty()) {
180 llvm::sys::fs::current_path(Storage);
181 SearchDir = Storage;
182 }
Zachary Turner2cc5a182017-03-13 00:41:01 +0000183 assert(!PartialItem.contains(path::get_separator()));
Zachary Turner0734e6a2017-03-12 20:01:37 +0000184
Zachary Turner2cc5a182017-03-13 00:41:01 +0000185 // SearchDir now contains the directory to search in, and Prefix contains the
186 // text we want to match against items in that directory.
187
188 std::error_code EC;
189 fs::directory_iterator Iter(SearchDir, EC, false);
190 fs::directory_iterator End;
191 for (; Iter != End && !EC; Iter.increment(EC)) {
192 auto &Entry = *Iter;
193
194 auto Name = path::filename(Entry.path());
195
196 // Omit ".", ".."
197 if (Name == "." || Name == ".." || !Name.startswith(PartialItem))
198 continue;
199
200 // We have a match.
201
202 fs::file_status st;
Zachary Turner1f875342017-03-13 02:44:39 +0000203 if ((EC = Entry.status(st)))
Zachary Turner2cc5a182017-03-13 00:41:01 +0000204 continue;
205
206 // If it's a symlink, then we treat it as a directory as long as the target
207 // is a directory.
208 bool is_dir = fs::is_directory(st);
209 if (fs::is_symlink_file(st)) {
210 fs::file_status target_st;
211 if (!fs::status(Entry.path(), target_st))
212 is_dir = fs::is_directory(target_st);
213 }
214 if (only_directories && !is_dir)
215 continue;
216
217 // Shrink it back down so that it just has the original prefix the user
218 // typed and remove the part of the name which is common to the located
219 // item and what the user typed.
220 CompletionBuffer.resize(FullPrefixLen);
221 Name = Name.drop_front(PartialItem.size());
222 CompletionBuffer.append(Name);
223
224 if (is_dir) {
225 saw_directory = true;
226 path::append(CompletionBuffer, path::get_separator());
227 }
228
229 matches.AppendString(CompletionBuffer);
230 }
Zachary Turner0734e6a2017-03-12 20:01:37 +0000231
Kate Stoneb9c1b512016-09-06 20:57:50 +0000232 return matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000233}
234
Kate Stoneb9c1b512016-09-06 20:57:50 +0000235int CommandCompletions::DiskFiles(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000236 llvm::StringRef partial_file_name,
Greg Claytonf21fead2013-05-14 23:43:18 +0000237 int match_start_point,
238 int max_return_elements,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000239 SearchFilter *searcher, bool &word_complete,
240 StringList &matches) {
Zachary Turner2cc5a182017-03-13 00:41:01 +0000241 word_complete = false;
242 StandardTildeExpressionResolver Resolver;
243 return DiskFiles(partial_file_name, matches, Resolver);
244}
245
246int CommandCompletions::DiskFiles(const llvm::Twine &partial_file_name,
247 StringList &matches,
248 TildeExpressionResolver &Resolver) {
249 bool word_complete;
250 int ret_val = DiskFilesOrDirectories(partial_file_name, false, word_complete,
251 matches, Resolver);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000252 return ret_val;
253}
254
255int CommandCompletions::DiskDirectories(
Zachary Turner4aa87532016-11-17 01:37:42 +0000256 CommandInterpreter &interpreter, llvm::StringRef partial_file_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000257 int match_start_point, int max_return_elements, SearchFilter *searcher,
258 bool &word_complete, StringList &matches) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000259 word_complete = false;
Zachary Turner2cc5a182017-03-13 00:41:01 +0000260 StandardTildeExpressionResolver Resolver;
261 return DiskDirectories(partial_file_name, matches, Resolver);
262}
263
264int CommandCompletions::DiskDirectories(const llvm::Twine &partial_file_name,
265 StringList &matches,
266 TildeExpressionResolver &Resolver) {
267 bool word_complete;
268 int ret_val = DiskFilesOrDirectories(partial_file_name, true, word_complete,
269 matches, Resolver);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000270 return ret_val;
271}
272
273int CommandCompletions::Modules(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000274 llvm::StringRef partial_file_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000275 int match_start_point, int max_return_elements,
276 SearchFilter *searcher, bool &word_complete,
277 StringList &matches) {
278 word_complete = true;
279 ModuleCompleter completer(interpreter, partial_file_name, match_start_point,
280 max_return_elements, matches);
281
282 if (searcher == nullptr) {
283 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
284 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
285 completer.DoCompletion(&null_searcher);
286 } else {
287 completer.DoCompletion(searcher);
288 }
289 return matches.GetSize();
290}
291
292int CommandCompletions::Symbols(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000293 llvm::StringRef partial_file_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000294 int match_start_point, int max_return_elements,
295 SearchFilter *searcher, bool &word_complete,
296 StringList &matches) {
297 word_complete = true;
298 SymbolCompleter completer(interpreter, partial_file_name, match_start_point,
299 max_return_elements, matches);
300
301 if (searcher == nullptr) {
302 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
303 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
304 completer.DoCompletion(&null_searcher);
305 } else {
306 completer.DoCompletion(searcher);
307 }
308 return matches.GetSize();
309}
310
311int CommandCompletions::SettingsNames(
Zachary Turner4aa87532016-11-17 01:37:42 +0000312 CommandInterpreter &interpreter, llvm::StringRef partial_setting_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000313 int match_start_point, int max_return_elements, SearchFilter *searcher,
314 bool &word_complete, StringList &matches) {
315 // Cache the full setting name list
316 static StringList g_property_names;
317 if (g_property_names.GetSize() == 0) {
318 // Generate the full setting name list on demand
319 lldb::OptionValuePropertiesSP properties_sp(
320 interpreter.GetDebugger().GetValueProperties());
321 if (properties_sp) {
322 StreamString strm;
323 properties_sp->DumpValue(nullptr, strm, OptionValue::eDumpOptionName);
324 const std::string &str = strm.GetString();
325 g_property_names.SplitIntoLines(str.c_str(), str.size());
326 }
327 }
328
329 size_t exact_matches_idx = SIZE_MAX;
330 const size_t num_matches = g_property_names.AutoComplete(
331 partial_setting_name, matches, exact_matches_idx);
332 word_complete = exact_matches_idx != SIZE_MAX;
333 return num_matches;
334}
335
336int CommandCompletions::PlatformPluginNames(
Zachary Turner4aa87532016-11-17 01:37:42 +0000337 CommandInterpreter &interpreter, llvm::StringRef partial_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000338 int match_start_point, int max_return_elements, SearchFilter *searcher,
339 bool &word_complete, lldb_private::StringList &matches) {
340 const uint32_t num_matches =
341 PluginManager::AutoCompletePlatformName(partial_name, matches);
342 word_complete = num_matches == 1;
343 return num_matches;
344}
345
346int CommandCompletions::ArchitectureNames(
Zachary Turner4aa87532016-11-17 01:37:42 +0000347 CommandInterpreter &interpreter, llvm::StringRef partial_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000348 int match_start_point, int max_return_elements, SearchFilter *searcher,
349 bool &word_complete, lldb_private::StringList &matches) {
350 const uint32_t num_matches = ArchSpec::AutoComplete(partial_name, matches);
351 word_complete = num_matches == 1;
352 return num_matches;
353}
354
355int CommandCompletions::VariablePath(
Zachary Turner4aa87532016-11-17 01:37:42 +0000356 CommandInterpreter &interpreter, llvm::StringRef partial_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000357 int match_start_point, int max_return_elements, SearchFilter *searcher,
358 bool &word_complete, lldb_private::StringList &matches) {
359 return Variable::AutoComplete(interpreter.GetExecutionContext(), partial_name,
360 matches, word_complete);
Greg Claytonf21fead2013-05-14 23:43:18 +0000361}
362
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000363CommandCompletions::Completer::Completer(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000364 llvm::StringRef completion_str,
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000365 int match_start_point,
366 int max_return_elements,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000367 StringList &matches)
368 : m_interpreter(interpreter), m_completion_str(completion_str),
369 m_match_start_point(match_start_point),
370 m_max_return_elements(max_return_elements), m_matches(matches) {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000371
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000372CommandCompletions::Completer::~Completer() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000373
374//----------------------------------------------------------------------
375// SourceFileCompleter
376//----------------------------------------------------------------------
377
Kate Stoneb9c1b512016-09-06 20:57:50 +0000378CommandCompletions::SourceFileCompleter::SourceFileCompleter(
379 CommandInterpreter &interpreter, bool include_support_files,
Zachary Turner4aa87532016-11-17 01:37:42 +0000380 llvm::StringRef completion_str, int match_start_point,
381 int max_return_elements, StringList &matches)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000382 : CommandCompletions::Completer(interpreter, completion_str,
383 match_start_point, max_return_elements,
384 matches),
385 m_include_support_files(include_support_files), m_matching_files() {
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000386 FileSpec partial_spec(m_completion_str, false);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000387 m_file_name = partial_spec.GetFilename().GetCString();
388 m_dir_name = partial_spec.GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000389}
390
Kate Stoneb9c1b512016-09-06 20:57:50 +0000391Searcher::Depth CommandCompletions::SourceFileCompleter::GetDepth() {
392 return eDepthCompUnit;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000393}
394
395Searcher::CallbackReturn
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000396CommandCompletions::SourceFileCompleter::SearchCallback(SearchFilter &filter,
397 SymbolContext &context,
398 Address *addr,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000399 bool complete) {
400 if (context.comp_unit != nullptr) {
401 if (m_include_support_files) {
402 FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
403 for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++) {
404 const FileSpec &sfile_spec =
405 supporting_files.GetFileSpecAtIndex(sfiles);
406 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
407 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
408 bool match = false;
409 if (m_file_name && sfile_file_name &&
410 strstr(sfile_file_name, m_file_name) == sfile_file_name)
411 match = true;
412 if (match && m_dir_name && sfile_dir_name &&
413 strstr(sfile_dir_name, m_dir_name) != sfile_dir_name)
414 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000415
Kate Stoneb9c1b512016-09-06 20:57:50 +0000416 if (match) {
417 m_matching_files.AppendIfUnique(sfile_spec);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000418 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000419 }
420 } else {
421 const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
422 const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000423
Kate Stoneb9c1b512016-09-06 20:57:50 +0000424 bool match = false;
425 if (m_file_name && cur_file_name &&
426 strstr(cur_file_name, m_file_name) == cur_file_name)
427 match = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000428
Kate Stoneb9c1b512016-09-06 20:57:50 +0000429 if (match && m_dir_name && cur_dir_name &&
430 strstr(cur_dir_name, m_dir_name) != cur_dir_name)
431 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000432
Kate Stoneb9c1b512016-09-06 20:57:50 +0000433 if (match) {
434 m_matching_files.AppendIfUnique(context.comp_unit);
435 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000436 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000437 }
438 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000439}
440
441size_t
Kate Stoneb9c1b512016-09-06 20:57:50 +0000442CommandCompletions::SourceFileCompleter::DoCompletion(SearchFilter *filter) {
443 filter->Search(*this);
444 // Now convert the filelist to completions:
445 for (size_t i = 0; i < m_matching_files.GetSize(); i++) {
446 m_matches.AppendString(
447 m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
448 }
449 return m_matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000450}
451
452//----------------------------------------------------------------------
453// SymbolCompleter
454//----------------------------------------------------------------------
455
Kate Stoneb9c1b512016-09-06 20:57:50 +0000456static bool regex_chars(const char comp) {
457 return (comp == '[' || comp == ']' || comp == '(' || comp == ')' ||
458 comp == '{' || comp == '}' || comp == '+' || comp == '.' ||
459 comp == '*' || comp == '|' || comp == '^' || comp == '$' ||
460 comp == '\\' || comp == '?');
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000461}
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000462
Kate Stoneb9c1b512016-09-06 20:57:50 +0000463CommandCompletions::SymbolCompleter::SymbolCompleter(
Zachary Turner4aa87532016-11-17 01:37:42 +0000464 CommandInterpreter &interpreter, llvm::StringRef completion_str,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000465 int match_start_point, int max_return_elements, StringList &matches)
466 : CommandCompletions::Completer(interpreter, completion_str,
467 match_start_point, max_return_elements,
468 matches) {
469 std::string regex_str;
Zachary Turner4aa87532016-11-17 01:37:42 +0000470 if (!completion_str.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000471 regex_str.append("^");
472 regex_str.append(completion_str);
473 } else {
474 // Match anything since the completion string is empty
475 regex_str.append(".");
476 }
477 std::string::iterator pos =
478 find_if(regex_str.begin() + 1, regex_str.end(), regex_chars);
479 while (pos < regex_str.end()) {
480 pos = regex_str.insert(pos, '\\');
481 pos = find_if(pos + 2, regex_str.end(), regex_chars);
482 }
Zachary Turner95eae422016-09-21 16:01:28 +0000483 m_regex.Compile(regex_str);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000484}
485
Kate Stoneb9c1b512016-09-06 20:57:50 +0000486Searcher::Depth CommandCompletions::SymbolCompleter::GetDepth() {
487 return eDepthModule;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000488}
489
Kate Stoneb9c1b512016-09-06 20:57:50 +0000490Searcher::CallbackReturn CommandCompletions::SymbolCompleter::SearchCallback(
491 SearchFilter &filter, SymbolContext &context, Address *addr,
492 bool complete) {
493 if (context.module_sp) {
494 SymbolContextList sc_list;
495 const bool include_symbols = true;
496 const bool include_inlines = true;
497 const bool append = true;
498 context.module_sp->FindFunctions(m_regex, include_symbols, include_inlines,
499 append, sc_list);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000500
Kate Stoneb9c1b512016-09-06 20:57:50 +0000501 SymbolContext sc;
502 // Now add the functions & symbols to the list - only add if unique:
503 for (uint32_t i = 0; i < sc_list.GetSize(); i++) {
504 if (sc_list.GetContextAtIndex(i, sc)) {
505 ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
506 if (!func_name.IsEmpty())
507 m_match_set.insert(func_name);
508 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000509 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000510 }
511 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000512}
513
Kate Stoneb9c1b512016-09-06 20:57:50 +0000514size_t CommandCompletions::SymbolCompleter::DoCompletion(SearchFilter *filter) {
515 filter->Search(*this);
516 collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
517 for (pos = m_match_set.begin(); pos != end; pos++)
518 m_matches.AppendString((*pos).GetCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000519
Kate Stoneb9c1b512016-09-06 20:57:50 +0000520 return m_matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000521}
522
523//----------------------------------------------------------------------
524// ModuleCompleter
525//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000526CommandCompletions::ModuleCompleter::ModuleCompleter(
Zachary Turner4aa87532016-11-17 01:37:42 +0000527 CommandInterpreter &interpreter, llvm::StringRef completion_str,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000528 int match_start_point, int max_return_elements, StringList &matches)
529 : CommandCompletions::Completer(interpreter, completion_str,
530 match_start_point, max_return_elements,
531 matches) {
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000532 FileSpec partial_spec(m_completion_str, false);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000533 m_file_name = partial_spec.GetFilename().GetCString();
534 m_dir_name = partial_spec.GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000535}
536
Kate Stoneb9c1b512016-09-06 20:57:50 +0000537Searcher::Depth CommandCompletions::ModuleCompleter::GetDepth() {
538 return eDepthModule;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000539}
540
Kate Stoneb9c1b512016-09-06 20:57:50 +0000541Searcher::CallbackReturn CommandCompletions::ModuleCompleter::SearchCallback(
542 SearchFilter &filter, SymbolContext &context, Address *addr,
543 bool complete) {
544 if (context.module_sp) {
545 const char *cur_file_name =
546 context.module_sp->GetFileSpec().GetFilename().GetCString();
547 const char *cur_dir_name =
548 context.module_sp->GetFileSpec().GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000549
Kate Stoneb9c1b512016-09-06 20:57:50 +0000550 bool match = false;
551 if (m_file_name && cur_file_name &&
552 strstr(cur_file_name, m_file_name) == cur_file_name)
553 match = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000554
Kate Stoneb9c1b512016-09-06 20:57:50 +0000555 if (match && m_dir_name && cur_dir_name &&
556 strstr(cur_dir_name, m_dir_name) != cur_dir_name)
557 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000558
Kate Stoneb9c1b512016-09-06 20:57:50 +0000559 if (match) {
560 m_matches.AppendString(cur_file_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000561 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000562 }
563 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000564}
565
Kate Stoneb9c1b512016-09-06 20:57:50 +0000566size_t CommandCompletions::ModuleCompleter::DoCompletion(SearchFilter *filter) {
567 filter->Search(*this);
568 return m_matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000569}