blob: dbb0b7e94691b54f7b85bee2c33603866a548384 [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 Isemann4621e0b2018-06-18 20:11:38 +0000167 llvm::StringRef RemainderDir = path::parent_path(Remainder.str());
168 if (!RemainderDir.empty()) {
169 // Append the remaining path to the resolved directory.
170 Storage.append(path::get_separator());
171 Storage.append(RemainderDir);
172 }
Raphael Isemann17843882018-01-22 09:17:16 +0000173 SearchDir = Storage;
Zachary Turner2cc5a182017-03-13 00:41:01 +0000174 } else {
175 SearchDir = path::parent_path(CompletionBuffer);
Zachary Turnerd5bd3a12017-03-12 18:18:50 +0000176 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000177
Zachary Turner2cc5a182017-03-13 00:41:01 +0000178 size_t FullPrefixLen = CompletionBuffer.size();
Zachary Turner0734e6a2017-03-12 20:01:37 +0000179
Zachary Turner2cc5a182017-03-13 00:41:01 +0000180 PartialItem = path::filename(CompletionBuffer);
181 if (PartialItem == ".")
182 PartialItem = llvm::StringRef();
Zachary Turner0734e6a2017-03-12 20:01:37 +0000183
Zachary Turner426d1372017-04-15 02:44:53 +0000184 if (SearchDir.empty()) {
185 llvm::sys::fs::current_path(Storage);
186 SearchDir = Storage;
187 }
Zachary Turner2cc5a182017-03-13 00:41:01 +0000188 assert(!PartialItem.contains(path::get_separator()));
Zachary Turner0734e6a2017-03-12 20:01:37 +0000189
Zachary Turner2cc5a182017-03-13 00:41:01 +0000190 // SearchDir now contains the directory to search in, and Prefix contains the
191 // text we want to match against items in that directory.
192
193 std::error_code EC;
194 fs::directory_iterator Iter(SearchDir, EC, false);
195 fs::directory_iterator End;
196 for (; Iter != End && !EC; Iter.increment(EC)) {
197 auto &Entry = *Iter;
198
199 auto Name = path::filename(Entry.path());
200
201 // Omit ".", ".."
202 if (Name == "." || Name == ".." || !Name.startswith(PartialItem))
203 continue;
204
205 // We have a match.
206
Peter Collingbourne0dfdb442017-10-10 22:19:46 +0000207 llvm::ErrorOr<fs::basic_file_status> st = Entry.status();
208 if (!st)
Zachary Turner2cc5a182017-03-13 00:41:01 +0000209 continue;
210
211 // If it's a symlink, then we treat it as a directory as long as the target
212 // is a directory.
Peter Collingbourne0dfdb442017-10-10 22:19:46 +0000213 bool is_dir = fs::is_directory(*st);
214 if (fs::is_symlink_file(*st)) {
Zachary Turner2cc5a182017-03-13 00:41:01 +0000215 fs::file_status target_st;
216 if (!fs::status(Entry.path(), target_st))
217 is_dir = fs::is_directory(target_st);
218 }
219 if (only_directories && !is_dir)
220 continue;
221
222 // Shrink it back down so that it just has the original prefix the user
223 // typed and remove the part of the name which is common to the located
224 // item and what the user typed.
225 CompletionBuffer.resize(FullPrefixLen);
226 Name = Name.drop_front(PartialItem.size());
227 CompletionBuffer.append(Name);
228
229 if (is_dir) {
230 saw_directory = true;
231 path::append(CompletionBuffer, path::get_separator());
232 }
233
234 matches.AppendString(CompletionBuffer);
235 }
Zachary Turner0734e6a2017-03-12 20:01:37 +0000236
Kate Stoneb9c1b512016-09-06 20:57:50 +0000237 return matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000238}
239
Kate Stoneb9c1b512016-09-06 20:57:50 +0000240int CommandCompletions::DiskFiles(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000241 llvm::StringRef partial_file_name,
Greg Claytonf21fead2013-05-14 23:43:18 +0000242 int match_start_point,
243 int max_return_elements,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000244 SearchFilter *searcher, bool &word_complete,
245 StringList &matches) {
Zachary Turner2cc5a182017-03-13 00:41:01 +0000246 word_complete = false;
247 StandardTildeExpressionResolver Resolver;
248 return DiskFiles(partial_file_name, matches, Resolver);
249}
250
251int CommandCompletions::DiskFiles(const llvm::Twine &partial_file_name,
252 StringList &matches,
253 TildeExpressionResolver &Resolver) {
254 bool word_complete;
255 int ret_val = DiskFilesOrDirectories(partial_file_name, false, word_complete,
256 matches, Resolver);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000257 return ret_val;
258}
259
260int CommandCompletions::DiskDirectories(
Zachary Turner4aa87532016-11-17 01:37:42 +0000261 CommandInterpreter &interpreter, llvm::StringRef partial_file_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000262 int match_start_point, int max_return_elements, SearchFilter *searcher,
263 bool &word_complete, StringList &matches) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000264 word_complete = false;
Zachary Turner2cc5a182017-03-13 00:41:01 +0000265 StandardTildeExpressionResolver Resolver;
266 return DiskDirectories(partial_file_name, matches, Resolver);
267}
268
269int CommandCompletions::DiskDirectories(const llvm::Twine &partial_file_name,
270 StringList &matches,
271 TildeExpressionResolver &Resolver) {
272 bool word_complete;
273 int ret_val = DiskFilesOrDirectories(partial_file_name, true, word_complete,
274 matches, Resolver);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000275 return ret_val;
276}
277
278int CommandCompletions::Modules(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000279 llvm::StringRef partial_file_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000280 int match_start_point, int max_return_elements,
281 SearchFilter *searcher, bool &word_complete,
282 StringList &matches) {
283 word_complete = true;
284 ModuleCompleter completer(interpreter, partial_file_name, match_start_point,
285 max_return_elements, matches);
286
287 if (searcher == nullptr) {
288 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
289 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
290 completer.DoCompletion(&null_searcher);
291 } else {
292 completer.DoCompletion(searcher);
293 }
294 return matches.GetSize();
295}
296
297int CommandCompletions::Symbols(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000298 llvm::StringRef partial_file_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000299 int match_start_point, int max_return_elements,
300 SearchFilter *searcher, bool &word_complete,
301 StringList &matches) {
302 word_complete = true;
303 SymbolCompleter completer(interpreter, partial_file_name, match_start_point,
304 max_return_elements, matches);
305
306 if (searcher == nullptr) {
307 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
308 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
309 completer.DoCompletion(&null_searcher);
310 } else {
311 completer.DoCompletion(searcher);
312 }
313 return matches.GetSize();
314}
315
316int CommandCompletions::SettingsNames(
Zachary Turner4aa87532016-11-17 01:37:42 +0000317 CommandInterpreter &interpreter, llvm::StringRef partial_setting_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000318 int match_start_point, int max_return_elements, SearchFilter *searcher,
319 bool &word_complete, StringList &matches) {
320 // Cache the full setting name list
321 static StringList g_property_names;
322 if (g_property_names.GetSize() == 0) {
323 // Generate the full setting name list on demand
324 lldb::OptionValuePropertiesSP properties_sp(
325 interpreter.GetDebugger().GetValueProperties());
326 if (properties_sp) {
327 StreamString strm;
328 properties_sp->DumpValue(nullptr, strm, OptionValue::eDumpOptionName);
329 const std::string &str = strm.GetString();
330 g_property_names.SplitIntoLines(str.c_str(), str.size());
331 }
332 }
333
334 size_t exact_matches_idx = SIZE_MAX;
335 const size_t num_matches = g_property_names.AutoComplete(
336 partial_setting_name, matches, exact_matches_idx);
337 word_complete = exact_matches_idx != SIZE_MAX;
338 return num_matches;
339}
340
341int CommandCompletions::PlatformPluginNames(
Zachary Turner4aa87532016-11-17 01:37:42 +0000342 CommandInterpreter &interpreter, llvm::StringRef partial_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000343 int match_start_point, int max_return_elements, SearchFilter *searcher,
344 bool &word_complete, lldb_private::StringList &matches) {
345 const uint32_t num_matches =
346 PluginManager::AutoCompletePlatformName(partial_name, matches);
347 word_complete = num_matches == 1;
348 return num_matches;
349}
350
351int CommandCompletions::ArchitectureNames(
Zachary Turner4aa87532016-11-17 01:37:42 +0000352 CommandInterpreter &interpreter, llvm::StringRef partial_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000353 int match_start_point, int max_return_elements, SearchFilter *searcher,
354 bool &word_complete, lldb_private::StringList &matches) {
355 const uint32_t num_matches = ArchSpec::AutoComplete(partial_name, matches);
356 word_complete = num_matches == 1;
357 return num_matches;
358}
359
360int CommandCompletions::VariablePath(
Zachary Turner4aa87532016-11-17 01:37:42 +0000361 CommandInterpreter &interpreter, llvm::StringRef partial_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000362 int match_start_point, int max_return_elements, SearchFilter *searcher,
363 bool &word_complete, lldb_private::StringList &matches) {
364 return Variable::AutoComplete(interpreter.GetExecutionContext(), partial_name,
365 matches, word_complete);
Greg Claytonf21fead2013-05-14 23:43:18 +0000366}
367
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000368CommandCompletions::Completer::Completer(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000369 llvm::StringRef completion_str,
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000370 int match_start_point,
371 int max_return_elements,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000372 StringList &matches)
373 : m_interpreter(interpreter), m_completion_str(completion_str),
374 m_match_start_point(match_start_point),
375 m_max_return_elements(max_return_elements), m_matches(matches) {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000376
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000377CommandCompletions::Completer::~Completer() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000378
379//----------------------------------------------------------------------
380// SourceFileCompleter
381//----------------------------------------------------------------------
382
Kate Stoneb9c1b512016-09-06 20:57:50 +0000383CommandCompletions::SourceFileCompleter::SourceFileCompleter(
384 CommandInterpreter &interpreter, bool include_support_files,
Zachary Turner4aa87532016-11-17 01:37:42 +0000385 llvm::StringRef completion_str, int match_start_point,
386 int max_return_elements, StringList &matches)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000387 : CommandCompletions::Completer(interpreter, completion_str,
388 match_start_point, max_return_elements,
389 matches),
390 m_include_support_files(include_support_files), m_matching_files() {
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000391 FileSpec partial_spec(m_completion_str, false);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000392 m_file_name = partial_spec.GetFilename().GetCString();
393 m_dir_name = partial_spec.GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000394}
395
Kate Stoneb9c1b512016-09-06 20:57:50 +0000396Searcher::Depth CommandCompletions::SourceFileCompleter::GetDepth() {
397 return eDepthCompUnit;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000398}
399
400Searcher::CallbackReturn
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000401CommandCompletions::SourceFileCompleter::SearchCallback(SearchFilter &filter,
402 SymbolContext &context,
403 Address *addr,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000404 bool complete) {
405 if (context.comp_unit != nullptr) {
406 if (m_include_support_files) {
407 FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
408 for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++) {
409 const FileSpec &sfile_spec =
410 supporting_files.GetFileSpecAtIndex(sfiles);
411 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
412 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
413 bool match = false;
414 if (m_file_name && sfile_file_name &&
415 strstr(sfile_file_name, m_file_name) == sfile_file_name)
416 match = true;
417 if (match && m_dir_name && sfile_dir_name &&
418 strstr(sfile_dir_name, m_dir_name) != sfile_dir_name)
419 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000420
Kate Stoneb9c1b512016-09-06 20:57:50 +0000421 if (match) {
422 m_matching_files.AppendIfUnique(sfile_spec);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000423 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000424 }
425 } else {
426 const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
427 const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000428
Kate Stoneb9c1b512016-09-06 20:57:50 +0000429 bool match = false;
430 if (m_file_name && cur_file_name &&
431 strstr(cur_file_name, m_file_name) == cur_file_name)
432 match = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000433
Kate Stoneb9c1b512016-09-06 20:57:50 +0000434 if (match && m_dir_name && cur_dir_name &&
435 strstr(cur_dir_name, m_dir_name) != cur_dir_name)
436 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000437
Kate Stoneb9c1b512016-09-06 20:57:50 +0000438 if (match) {
439 m_matching_files.AppendIfUnique(context.comp_unit);
440 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000441 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000442 }
443 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000444}
445
446size_t
Kate Stoneb9c1b512016-09-06 20:57:50 +0000447CommandCompletions::SourceFileCompleter::DoCompletion(SearchFilter *filter) {
448 filter->Search(*this);
449 // Now convert the filelist to completions:
450 for (size_t i = 0; i < m_matching_files.GetSize(); i++) {
451 m_matches.AppendString(
452 m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
453 }
454 return m_matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000455}
456
457//----------------------------------------------------------------------
458// SymbolCompleter
459//----------------------------------------------------------------------
460
Kate Stoneb9c1b512016-09-06 20:57:50 +0000461static bool regex_chars(const char comp) {
462 return (comp == '[' || comp == ']' || comp == '(' || comp == ')' ||
463 comp == '{' || comp == '}' || comp == '+' || comp == '.' ||
464 comp == '*' || comp == '|' || comp == '^' || comp == '$' ||
465 comp == '\\' || comp == '?');
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000466}
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000467
Kate Stoneb9c1b512016-09-06 20:57:50 +0000468CommandCompletions::SymbolCompleter::SymbolCompleter(
Zachary Turner4aa87532016-11-17 01:37:42 +0000469 CommandInterpreter &interpreter, llvm::StringRef completion_str,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000470 int match_start_point, int max_return_elements, StringList &matches)
471 : CommandCompletions::Completer(interpreter, completion_str,
472 match_start_point, max_return_elements,
473 matches) {
474 std::string regex_str;
Zachary Turner4aa87532016-11-17 01:37:42 +0000475 if (!completion_str.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000476 regex_str.append("^");
477 regex_str.append(completion_str);
478 } else {
479 // Match anything since the completion string is empty
480 regex_str.append(".");
481 }
482 std::string::iterator pos =
483 find_if(regex_str.begin() + 1, regex_str.end(), regex_chars);
484 while (pos < regex_str.end()) {
485 pos = regex_str.insert(pos, '\\');
486 pos = find_if(pos + 2, regex_str.end(), regex_chars);
487 }
Zachary Turner95eae422016-09-21 16:01:28 +0000488 m_regex.Compile(regex_str);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000489}
490
Kate Stoneb9c1b512016-09-06 20:57:50 +0000491Searcher::Depth CommandCompletions::SymbolCompleter::GetDepth() {
492 return eDepthModule;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000493}
494
Kate Stoneb9c1b512016-09-06 20:57:50 +0000495Searcher::CallbackReturn CommandCompletions::SymbolCompleter::SearchCallback(
496 SearchFilter &filter, SymbolContext &context, Address *addr,
497 bool complete) {
498 if (context.module_sp) {
499 SymbolContextList sc_list;
500 const bool include_symbols = true;
501 const bool include_inlines = true;
502 const bool append = true;
503 context.module_sp->FindFunctions(m_regex, include_symbols, include_inlines,
504 append, sc_list);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000505
Kate Stoneb9c1b512016-09-06 20:57:50 +0000506 SymbolContext sc;
507 // Now add the functions & symbols to the list - only add if unique:
508 for (uint32_t i = 0; i < sc_list.GetSize(); i++) {
509 if (sc_list.GetContextAtIndex(i, sc)) {
510 ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
511 if (!func_name.IsEmpty())
512 m_match_set.insert(func_name);
513 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000514 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000515 }
516 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000517}
518
Kate Stoneb9c1b512016-09-06 20:57:50 +0000519size_t CommandCompletions::SymbolCompleter::DoCompletion(SearchFilter *filter) {
520 filter->Search(*this);
521 collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
522 for (pos = m_match_set.begin(); pos != end; pos++)
523 m_matches.AppendString((*pos).GetCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000524
Kate Stoneb9c1b512016-09-06 20:57:50 +0000525 return m_matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000526}
527
528//----------------------------------------------------------------------
529// ModuleCompleter
530//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000531CommandCompletions::ModuleCompleter::ModuleCompleter(
Zachary Turner4aa87532016-11-17 01:37:42 +0000532 CommandInterpreter &interpreter, llvm::StringRef completion_str,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000533 int match_start_point, int max_return_elements, StringList &matches)
534 : CommandCompletions::Completer(interpreter, completion_str,
535 match_start_point, max_return_elements,
536 matches) {
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000537 FileSpec partial_spec(m_completion_str, false);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000538 m_file_name = partial_spec.GetFilename().GetCString();
539 m_dir_name = partial_spec.GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000540}
541
Kate Stoneb9c1b512016-09-06 20:57:50 +0000542Searcher::Depth CommandCompletions::ModuleCompleter::GetDepth() {
543 return eDepthModule;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000544}
545
Kate Stoneb9c1b512016-09-06 20:57:50 +0000546Searcher::CallbackReturn CommandCompletions::ModuleCompleter::SearchCallback(
547 SearchFilter &filter, SymbolContext &context, Address *addr,
548 bool complete) {
549 if (context.module_sp) {
550 const char *cur_file_name =
551 context.module_sp->GetFileSpec().GetFilename().GetCString();
552 const char *cur_dir_name =
553 context.module_sp->GetFileSpec().GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000554
Kate Stoneb9c1b512016-09-06 20:57:50 +0000555 bool match = false;
556 if (m_file_name && cur_file_name &&
557 strstr(cur_file_name, m_file_name) == cur_file_name)
558 match = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000559
Kate Stoneb9c1b512016-09-06 20:57:50 +0000560 if (match && m_dir_name && cur_dir_name &&
561 strstr(cur_dir_name, m_dir_name) != cur_dir_name)
562 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000563
Kate Stoneb9c1b512016-09-06 20:57:50 +0000564 if (match) {
565 m_matches.AppendString(cur_file_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000566 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000567 }
568 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000569}
570
Kate Stoneb9c1b512016-09-06 20:57:50 +0000571size_t CommandCompletions::ModuleCompleter::DoCompletion(SearchFilter *filter) {
572 filter->Search(*this);
573 return m_matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000574}