blob: b1418334c9646b3c117a025cd077b8beabbb31e1 [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/CommandCompletions.h"
27#include "lldb/Interpreter/CommandInterpreter.h"
Zachary Turner633a29c2015-03-04 01:58:01 +000028#include "lldb/Interpreter/OptionValueProperties.h"
Greg Clayton1f746072012-08-29 21:13:06 +000029#include "lldb/Symbol/CompileUnit.h"
Greg Claytonf21fead2013-05-14 23:43:18 +000030#include "lldb/Symbol/Variable.h"
Greg Clayton9b62fd22011-02-01 05:15:22 +000031#include "lldb/Target/Target.h"
Pavel Labath145d95c2018-04-17 18:53:35 +000032#include "lldb/Utility/Args.h"
Zachary Turner5713a052017-03-22 18:40:07 +000033#include "lldb/Utility/FileSpec.h"
Zachary Turner2f3df612017-04-06 21:28:29 +000034#include "lldb/Utility/StreamString.h"
Zachary Turner2cc5a182017-03-13 00:41:01 +000035#include "lldb/Utility/TildeExpressionResolver.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000036
Zachary Turner190fadc2016-03-22 17:58:09 +000037#include "llvm/ADT/SmallString.h"
Zachary Turner7d86ee52017-03-08 17:56:08 +000038#include "llvm/Support/FileSystem.h"
Zachary Turner2cc5a182017-03-13 00:41:01 +000039#include "llvm/Support/Path.h"
Zachary Turner190fadc2016-03-22 17:58:09 +000040
Chris Lattner30fdc8d2010-06-08 16:52:24 +000041using namespace lldb_private;
42
43CommandCompletions::CommonCompletionElement
Kate Stoneb9c1b512016-09-06 20:57:50 +000044 CommandCompletions::g_common_completions[] = {
45 {eCustomCompletion, nullptr},
46 {eSourceFileCompletion, CommandCompletions::SourceFiles},
47 {eDiskFileCompletion, CommandCompletions::DiskFiles},
48 {eDiskDirectoryCompletion, CommandCompletions::DiskDirectories},
49 {eSymbolCompletion, CommandCompletions::Symbols},
50 {eModuleCompletion, CommandCompletions::Modules},
51 {eSettingsNameCompletion, CommandCompletions::SettingsNames},
52 {ePlatformPluginCompletion, CommandCompletions::PlatformPluginNames},
53 {eArchitectureCompletion, CommandCompletions::ArchitectureNames},
54 {eVariablePathCompletion, CommandCompletions::VariablePath},
55 {eNoCompletion, nullptr} // This one has to be last in the list.
Chris Lattner30fdc8d2010-06-08 16:52:24 +000056};
57
Kate Stoneb9c1b512016-09-06 20:57:50 +000058bool CommandCompletions::InvokeCommonCompletionCallbacks(
59 CommandInterpreter &interpreter, uint32_t completion_mask,
Zachary Turner4aa87532016-11-17 01:37:42 +000060 llvm::StringRef completion_str, int match_start_point,
61 int max_return_elements, SearchFilter *searcher, bool &word_complete,
62 StringList &matches) {
Kate Stoneb9c1b512016-09-06 20:57:50 +000063 bool handled = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000064
Kate Stoneb9c1b512016-09-06 20:57:50 +000065 if (completion_mask & eCustomCompletion)
66 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000067
Kate Stoneb9c1b512016-09-06 20:57:50 +000068 for (int i = 0;; i++) {
69 if (g_common_completions[i].type == eNoCompletion)
70 break;
71 else if ((g_common_completions[i].type & completion_mask) ==
72 g_common_completions[i].type &&
73 g_common_completions[i].callback != nullptr) {
74 handled = true;
75 g_common_completions[i].callback(interpreter, completion_str,
76 match_start_point, max_return_elements,
77 searcher, word_complete, matches);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000078 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000079 }
80 return handled;
Chris Lattner30fdc8d2010-06-08 16:52:24 +000081}
82
Kate Stoneb9c1b512016-09-06 20:57:50 +000083int CommandCompletions::SourceFiles(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +000084 llvm::StringRef partial_file_name,
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +000085 int match_start_point,
86 int max_return_elements,
Kate Stoneb9c1b512016-09-06 20:57:50 +000087 SearchFilter *searcher, bool &word_complete,
88 StringList &matches) {
89 word_complete = true;
90 // Find some way to switch "include support files..."
91 SourceFileCompleter completer(interpreter, false, partial_file_name,
92 match_start_point, max_return_elements,
93 matches);
94
95 if (searcher == nullptr) {
96 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
97 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
98 completer.DoCompletion(&null_searcher);
99 } else {
100 completer.DoCompletion(searcher);
101 }
102 return matches.GetSize();
Jim Ingham558ce122010-06-30 05:02:46 +0000103}
104
Zachary Turner2cc5a182017-03-13 00:41:01 +0000105static int DiskFilesOrDirectories(const llvm::Twine &partial_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000106 bool only_directories, bool &saw_directory,
Zachary Turner2cc5a182017-03-13 00:41:01 +0000107 StringList &matches,
108 TildeExpressionResolver &Resolver) {
109 matches.Clear();
Kate Stoneb9c1b512016-09-06 20:57:50 +0000110
Zachary Turner2cc5a182017-03-13 00:41:01 +0000111 llvm::SmallString<256> CompletionBuffer;
112 llvm::SmallString<256> Storage;
113 partial_name.toVector(CompletionBuffer);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000114
Zachary Turner2cc5a182017-03-13 00:41:01 +0000115 if (CompletionBuffer.size() >= PATH_MAX)
116 return 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000117
Zachary Turner2cc5a182017-03-13 00:41:01 +0000118 namespace fs = llvm::sys::fs;
119 namespace path = llvm::sys::path;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000120
Zachary Turner2cc5a182017-03-13 00:41:01 +0000121 llvm::StringRef SearchDir;
122 llvm::StringRef PartialItem;
Kate Stoneb9c1b512016-09-06 20:57:50 +0000123
Zachary Turner2cc5a182017-03-13 00:41:01 +0000124 if (CompletionBuffer.startswith("~")) {
125 llvm::StringRef Buffer(CompletionBuffer);
Zachary Turner5c5091f2017-03-16 22:28:04 +0000126 size_t FirstSep =
127 Buffer.find_if([](char c) { return path::is_separator(c); });
Kate Stoneb9c1b512016-09-06 20:57:50 +0000128
Zachary Turner2cc5a182017-03-13 00:41:01 +0000129 llvm::StringRef Username = Buffer.take_front(FirstSep);
130 llvm::StringRef Remainder;
131 if (FirstSep != llvm::StringRef::npos)
132 Remainder = Buffer.drop_front(FirstSep + 1);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000133
Zachary Turner2cc5a182017-03-13 00:41:01 +0000134 llvm::SmallString<PATH_MAX> Resolved;
135 if (!Resolver.ResolveExact(Username, Resolved)) {
136 // We couldn't resolve it as a full username. If there were no slashes
137 // then this might be a partial username. We try to resolve it as such
138 // but after that, we're done regardless of any matches.
139 if (FirstSep == llvm::StringRef::npos) {
140 llvm::StringSet<> MatchSet;
141 saw_directory = Resolver.ResolvePartial(Username, MatchSet);
142 for (const auto &S : MatchSet) {
143 Resolved = S.getKey();
144 path::append(Resolved, path::get_separator());
145 matches.AppendString(Resolved);
146 }
147 saw_directory = (matches.GetSize() > 0);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000148 }
Zachary Turner0734e6a2017-03-12 20:01:37 +0000149 return matches.GetSize();
Zachary Turner2cc5a182017-03-13 00:41:01 +0000150 }
151
Adrian Prantl05097242018-04-30 16:49:04 +0000152 // If there was no trailing slash, then we're done as soon as we resolve
153 // the expression to the correct directory. Otherwise we need to continue
Zachary Turner2cc5a182017-03-13 00:41:01 +0000154 // looking for matches within that directory.
155 if (FirstSep == llvm::StringRef::npos) {
156 // Make sure it ends with a separator.
157 path::append(CompletionBuffer, path::get_separator());
158 saw_directory = true;
159 matches.AppendString(CompletionBuffer);
160 return 1;
161 }
162
163 // We want to keep the form the user typed, so we special case this to
164 // search in the fully resolved directory, but CompletionBuffer keeps the
165 // unmodified form that the user typed.
166 Storage = Resolved;
Raphael Isemann17843882018-01-22 09:17:16 +0000167 SearchDir = Storage;
Zachary Turner2cc5a182017-03-13 00:41:01 +0000168 } else {
169 SearchDir = path::parent_path(CompletionBuffer);
Zachary Turnerd5bd3a12017-03-12 18:18:50 +0000170 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000171
Zachary Turner2cc5a182017-03-13 00:41:01 +0000172 size_t FullPrefixLen = CompletionBuffer.size();
Zachary Turner0734e6a2017-03-12 20:01:37 +0000173
Zachary Turner2cc5a182017-03-13 00:41:01 +0000174 PartialItem = path::filename(CompletionBuffer);
175 if (PartialItem == ".")
176 PartialItem = llvm::StringRef();
Zachary Turner0734e6a2017-03-12 20:01:37 +0000177
Zachary Turner426d1372017-04-15 02:44:53 +0000178 if (SearchDir.empty()) {
179 llvm::sys::fs::current_path(Storage);
180 SearchDir = Storage;
181 }
Zachary Turner2cc5a182017-03-13 00:41:01 +0000182 assert(!PartialItem.contains(path::get_separator()));
Zachary Turner0734e6a2017-03-12 20:01:37 +0000183
Zachary Turner2cc5a182017-03-13 00:41:01 +0000184 // SearchDir now contains the directory to search in, and Prefix contains the
185 // text we want to match against items in that directory.
186
187 std::error_code EC;
188 fs::directory_iterator Iter(SearchDir, EC, false);
189 fs::directory_iterator End;
190 for (; Iter != End && !EC; Iter.increment(EC)) {
191 auto &Entry = *Iter;
192
193 auto Name = path::filename(Entry.path());
194
195 // Omit ".", ".."
196 if (Name == "." || Name == ".." || !Name.startswith(PartialItem))
197 continue;
198
199 // We have a match.
200
Peter Collingbourne0dfdb442017-10-10 22:19:46 +0000201 llvm::ErrorOr<fs::basic_file_status> st = Entry.status();
202 if (!st)
Zachary Turner2cc5a182017-03-13 00:41:01 +0000203 continue;
204
205 // If it's a symlink, then we treat it as a directory as long as the target
206 // is a directory.
Peter Collingbourne0dfdb442017-10-10 22:19:46 +0000207 bool is_dir = fs::is_directory(*st);
208 if (fs::is_symlink_file(*st)) {
Zachary Turner2cc5a182017-03-13 00:41:01 +0000209 fs::file_status target_st;
210 if (!fs::status(Entry.path(), target_st))
211 is_dir = fs::is_directory(target_st);
212 }
213 if (only_directories && !is_dir)
214 continue;
215
216 // Shrink it back down so that it just has the original prefix the user
217 // typed and remove the part of the name which is common to the located
218 // item and what the user typed.
219 CompletionBuffer.resize(FullPrefixLen);
220 Name = Name.drop_front(PartialItem.size());
221 CompletionBuffer.append(Name);
222
223 if (is_dir) {
224 saw_directory = true;
225 path::append(CompletionBuffer, path::get_separator());
226 }
227
228 matches.AppendString(CompletionBuffer);
229 }
Zachary Turner0734e6a2017-03-12 20:01:37 +0000230
Kate Stoneb9c1b512016-09-06 20:57:50 +0000231 return matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000232}
233
Kate Stoneb9c1b512016-09-06 20:57:50 +0000234int CommandCompletions::DiskFiles(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000235 llvm::StringRef partial_file_name,
Greg Claytonf21fead2013-05-14 23:43:18 +0000236 int match_start_point,
237 int max_return_elements,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000238 SearchFilter *searcher, bool &word_complete,
239 StringList &matches) {
Zachary Turner2cc5a182017-03-13 00:41:01 +0000240 word_complete = false;
241 StandardTildeExpressionResolver Resolver;
242 return DiskFiles(partial_file_name, matches, Resolver);
243}
244
245int CommandCompletions::DiskFiles(const llvm::Twine &partial_file_name,
246 StringList &matches,
247 TildeExpressionResolver &Resolver) {
248 bool word_complete;
249 int ret_val = DiskFilesOrDirectories(partial_file_name, false, word_complete,
250 matches, Resolver);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000251 return ret_val;
252}
253
254int CommandCompletions::DiskDirectories(
Zachary Turner4aa87532016-11-17 01:37:42 +0000255 CommandInterpreter &interpreter, llvm::StringRef partial_file_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000256 int match_start_point, int max_return_elements, SearchFilter *searcher,
257 bool &word_complete, StringList &matches) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000258 word_complete = false;
Zachary Turner2cc5a182017-03-13 00:41:01 +0000259 StandardTildeExpressionResolver Resolver;
260 return DiskDirectories(partial_file_name, matches, Resolver);
261}
262
263int CommandCompletions::DiskDirectories(const llvm::Twine &partial_file_name,
264 StringList &matches,
265 TildeExpressionResolver &Resolver) {
266 bool word_complete;
267 int ret_val = DiskFilesOrDirectories(partial_file_name, true, word_complete,
268 matches, Resolver);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000269 return ret_val;
270}
271
272int CommandCompletions::Modules(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000273 llvm::StringRef partial_file_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000274 int match_start_point, int max_return_elements,
275 SearchFilter *searcher, bool &word_complete,
276 StringList &matches) {
277 word_complete = true;
278 ModuleCompleter completer(interpreter, partial_file_name, match_start_point,
279 max_return_elements, matches);
280
281 if (searcher == nullptr) {
282 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
283 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
284 completer.DoCompletion(&null_searcher);
285 } else {
286 completer.DoCompletion(searcher);
287 }
288 return matches.GetSize();
289}
290
291int CommandCompletions::Symbols(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000292 llvm::StringRef partial_file_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000293 int match_start_point, int max_return_elements,
294 SearchFilter *searcher, bool &word_complete,
295 StringList &matches) {
296 word_complete = true;
297 SymbolCompleter completer(interpreter, partial_file_name, match_start_point,
298 max_return_elements, matches);
299
300 if (searcher == nullptr) {
301 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
302 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
303 completer.DoCompletion(&null_searcher);
304 } else {
305 completer.DoCompletion(searcher);
306 }
307 return matches.GetSize();
308}
309
310int CommandCompletions::SettingsNames(
Zachary Turner4aa87532016-11-17 01:37:42 +0000311 CommandInterpreter &interpreter, llvm::StringRef partial_setting_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000312 int match_start_point, int max_return_elements, SearchFilter *searcher,
313 bool &word_complete, StringList &matches) {
314 // Cache the full setting name list
315 static StringList g_property_names;
316 if (g_property_names.GetSize() == 0) {
317 // Generate the full setting name list on demand
318 lldb::OptionValuePropertiesSP properties_sp(
319 interpreter.GetDebugger().GetValueProperties());
320 if (properties_sp) {
321 StreamString strm;
322 properties_sp->DumpValue(nullptr, strm, OptionValue::eDumpOptionName);
323 const std::string &str = strm.GetString();
324 g_property_names.SplitIntoLines(str.c_str(), str.size());
325 }
326 }
327
328 size_t exact_matches_idx = SIZE_MAX;
329 const size_t num_matches = g_property_names.AutoComplete(
330 partial_setting_name, matches, exact_matches_idx);
331 word_complete = exact_matches_idx != SIZE_MAX;
332 return num_matches;
333}
334
335int CommandCompletions::PlatformPluginNames(
Zachary Turner4aa87532016-11-17 01:37:42 +0000336 CommandInterpreter &interpreter, llvm::StringRef partial_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000337 int match_start_point, int max_return_elements, SearchFilter *searcher,
338 bool &word_complete, lldb_private::StringList &matches) {
339 const uint32_t num_matches =
340 PluginManager::AutoCompletePlatformName(partial_name, matches);
341 word_complete = num_matches == 1;
342 return num_matches;
343}
344
345int CommandCompletions::ArchitectureNames(
Zachary Turner4aa87532016-11-17 01:37:42 +0000346 CommandInterpreter &interpreter, llvm::StringRef partial_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000347 int match_start_point, int max_return_elements, SearchFilter *searcher,
348 bool &word_complete, lldb_private::StringList &matches) {
349 const uint32_t num_matches = ArchSpec::AutoComplete(partial_name, matches);
350 word_complete = num_matches == 1;
351 return num_matches;
352}
353
354int CommandCompletions::VariablePath(
Zachary Turner4aa87532016-11-17 01:37:42 +0000355 CommandInterpreter &interpreter, llvm::StringRef partial_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000356 int match_start_point, int max_return_elements, SearchFilter *searcher,
357 bool &word_complete, lldb_private::StringList &matches) {
358 return Variable::AutoComplete(interpreter.GetExecutionContext(), partial_name,
359 matches, word_complete);
Greg Claytonf21fead2013-05-14 23:43:18 +0000360}
361
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000362CommandCompletions::Completer::Completer(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000363 llvm::StringRef completion_str,
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000364 int match_start_point,
365 int max_return_elements,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000366 StringList &matches)
367 : m_interpreter(interpreter), m_completion_str(completion_str),
368 m_match_start_point(match_start_point),
369 m_max_return_elements(max_return_elements), m_matches(matches) {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000370
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000371CommandCompletions::Completer::~Completer() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000372
373//----------------------------------------------------------------------
374// SourceFileCompleter
375//----------------------------------------------------------------------
376
Kate Stoneb9c1b512016-09-06 20:57:50 +0000377CommandCompletions::SourceFileCompleter::SourceFileCompleter(
378 CommandInterpreter &interpreter, bool include_support_files,
Zachary Turner4aa87532016-11-17 01:37:42 +0000379 llvm::StringRef completion_str, int match_start_point,
380 int max_return_elements, StringList &matches)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000381 : CommandCompletions::Completer(interpreter, completion_str,
382 match_start_point, max_return_elements,
383 matches),
384 m_include_support_files(include_support_files), m_matching_files() {
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000385 FileSpec partial_spec(m_completion_str, false);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000386 m_file_name = partial_spec.GetFilename().GetCString();
387 m_dir_name = partial_spec.GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000388}
389
Kate Stoneb9c1b512016-09-06 20:57:50 +0000390Searcher::Depth CommandCompletions::SourceFileCompleter::GetDepth() {
391 return eDepthCompUnit;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000392}
393
394Searcher::CallbackReturn
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000395CommandCompletions::SourceFileCompleter::SearchCallback(SearchFilter &filter,
396 SymbolContext &context,
397 Address *addr,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000398 bool complete) {
399 if (context.comp_unit != nullptr) {
400 if (m_include_support_files) {
401 FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
402 for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++) {
403 const FileSpec &sfile_spec =
404 supporting_files.GetFileSpecAtIndex(sfiles);
405 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
406 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
407 bool match = false;
408 if (m_file_name && sfile_file_name &&
409 strstr(sfile_file_name, m_file_name) == sfile_file_name)
410 match = true;
411 if (match && m_dir_name && sfile_dir_name &&
412 strstr(sfile_dir_name, m_dir_name) != sfile_dir_name)
413 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000414
Kate Stoneb9c1b512016-09-06 20:57:50 +0000415 if (match) {
416 m_matching_files.AppendIfUnique(sfile_spec);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000417 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000418 }
419 } else {
420 const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
421 const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000422
Kate Stoneb9c1b512016-09-06 20:57:50 +0000423 bool match = false;
424 if (m_file_name && cur_file_name &&
425 strstr(cur_file_name, m_file_name) == cur_file_name)
426 match = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000427
Kate Stoneb9c1b512016-09-06 20:57:50 +0000428 if (match && m_dir_name && cur_dir_name &&
429 strstr(cur_dir_name, m_dir_name) != cur_dir_name)
430 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000431
Kate Stoneb9c1b512016-09-06 20:57:50 +0000432 if (match) {
433 m_matching_files.AppendIfUnique(context.comp_unit);
434 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000435 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000436 }
437 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000438}
439
440size_t
Kate Stoneb9c1b512016-09-06 20:57:50 +0000441CommandCompletions::SourceFileCompleter::DoCompletion(SearchFilter *filter) {
442 filter->Search(*this);
443 // Now convert the filelist to completions:
444 for (size_t i = 0; i < m_matching_files.GetSize(); i++) {
445 m_matches.AppendString(
446 m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
447 }
448 return m_matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000449}
450
451//----------------------------------------------------------------------
452// SymbolCompleter
453//----------------------------------------------------------------------
454
Kate Stoneb9c1b512016-09-06 20:57:50 +0000455static bool regex_chars(const char comp) {
456 return (comp == '[' || comp == ']' || comp == '(' || comp == ')' ||
457 comp == '{' || comp == '}' || comp == '+' || comp == '.' ||
458 comp == '*' || comp == '|' || comp == '^' || comp == '$' ||
459 comp == '\\' || comp == '?');
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000460}
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000461
Kate Stoneb9c1b512016-09-06 20:57:50 +0000462CommandCompletions::SymbolCompleter::SymbolCompleter(
Zachary Turner4aa87532016-11-17 01:37:42 +0000463 CommandInterpreter &interpreter, llvm::StringRef completion_str,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000464 int match_start_point, int max_return_elements, StringList &matches)
465 : CommandCompletions::Completer(interpreter, completion_str,
466 match_start_point, max_return_elements,
467 matches) {
468 std::string regex_str;
Zachary Turner4aa87532016-11-17 01:37:42 +0000469 if (!completion_str.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000470 regex_str.append("^");
471 regex_str.append(completion_str);
472 } else {
473 // Match anything since the completion string is empty
474 regex_str.append(".");
475 }
476 std::string::iterator pos =
477 find_if(regex_str.begin() + 1, regex_str.end(), regex_chars);
478 while (pos < regex_str.end()) {
479 pos = regex_str.insert(pos, '\\');
480 pos = find_if(pos + 2, regex_str.end(), regex_chars);
481 }
Zachary Turner95eae422016-09-21 16:01:28 +0000482 m_regex.Compile(regex_str);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000483}
484
Kate Stoneb9c1b512016-09-06 20:57:50 +0000485Searcher::Depth CommandCompletions::SymbolCompleter::GetDepth() {
486 return eDepthModule;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000487}
488
Kate Stoneb9c1b512016-09-06 20:57:50 +0000489Searcher::CallbackReturn CommandCompletions::SymbolCompleter::SearchCallback(
490 SearchFilter &filter, SymbolContext &context, Address *addr,
491 bool complete) {
492 if (context.module_sp) {
493 SymbolContextList sc_list;
494 const bool include_symbols = true;
495 const bool include_inlines = true;
496 const bool append = true;
497 context.module_sp->FindFunctions(m_regex, include_symbols, include_inlines,
498 append, sc_list);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000499
Kate Stoneb9c1b512016-09-06 20:57:50 +0000500 SymbolContext sc;
501 // Now add the functions & symbols to the list - only add if unique:
502 for (uint32_t i = 0; i < sc_list.GetSize(); i++) {
503 if (sc_list.GetContextAtIndex(i, sc)) {
504 ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
505 if (!func_name.IsEmpty())
506 m_match_set.insert(func_name);
507 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000508 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000509 }
510 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000511}
512
Kate Stoneb9c1b512016-09-06 20:57:50 +0000513size_t CommandCompletions::SymbolCompleter::DoCompletion(SearchFilter *filter) {
514 filter->Search(*this);
515 collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
516 for (pos = m_match_set.begin(); pos != end; pos++)
517 m_matches.AppendString((*pos).GetCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000518
Kate Stoneb9c1b512016-09-06 20:57:50 +0000519 return m_matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000520}
521
522//----------------------------------------------------------------------
523// ModuleCompleter
524//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000525CommandCompletions::ModuleCompleter::ModuleCompleter(
Zachary Turner4aa87532016-11-17 01:37:42 +0000526 CommandInterpreter &interpreter, llvm::StringRef completion_str,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000527 int match_start_point, int max_return_elements, StringList &matches)
528 : CommandCompletions::Completer(interpreter, completion_str,
529 match_start_point, max_return_elements,
530 matches) {
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000531 FileSpec partial_spec(m_completion_str, false);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000532 m_file_name = partial_spec.GetFilename().GetCString();
533 m_dir_name = partial_spec.GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000534}
535
Kate Stoneb9c1b512016-09-06 20:57:50 +0000536Searcher::Depth CommandCompletions::ModuleCompleter::GetDepth() {
537 return eDepthModule;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000538}
539
Kate Stoneb9c1b512016-09-06 20:57:50 +0000540Searcher::CallbackReturn CommandCompletions::ModuleCompleter::SearchCallback(
541 SearchFilter &filter, SymbolContext &context, Address *addr,
542 bool complete) {
543 if (context.module_sp) {
544 const char *cur_file_name =
545 context.module_sp->GetFileSpec().GetFilename().GetCString();
546 const char *cur_dir_name =
547 context.module_sp->GetFileSpec().GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000548
Kate Stoneb9c1b512016-09-06 20:57:50 +0000549 bool match = false;
550 if (m_file_name && cur_file_name &&
551 strstr(cur_file_name, m_file_name) == cur_file_name)
552 match = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000553
Kate Stoneb9c1b512016-09-06 20:57:50 +0000554 if (match && m_dir_name && cur_dir_name &&
555 strstr(cur_dir_name, m_dir_name) != cur_dir_name)
556 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000557
Kate Stoneb9c1b512016-09-06 20:57:50 +0000558 if (match) {
559 m_matches.AppendString(cur_file_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000560 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000561 }
562 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000563}
564
Kate Stoneb9c1b512016-09-06 20:57:50 +0000565size_t CommandCompletions::ModuleCompleter::DoCompletion(SearchFilter *filter) {
566 filter->Search(*this);
567 return m_matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000568}