blob: 16e4de017d5f448510a93376f551a2cf97a75b5d [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"
25#include "lldb/Host/FileSpec.h"
26#include "lldb/Host/FileSystem.h"
Greg Clayton9b62fd22011-02-01 05:15:22 +000027#include "lldb/Interpreter/Args.h"
28#include "lldb/Interpreter/CommandCompletions.h"
29#include "lldb/Interpreter/CommandInterpreter.h"
Zachary Turner633a29c2015-03-04 01:58:01 +000030#include "lldb/Interpreter/OptionValueProperties.h"
Greg Clayton1f746072012-08-29 21:13:06 +000031#include "lldb/Symbol/CompileUnit.h"
Greg Claytonf21fead2013-05-14 23:43:18 +000032#include "lldb/Symbol/Variable.h"
Greg Clayton9b62fd22011-02-01 05:15:22 +000033#include "lldb/Target/Target.h"
34#include "lldb/Utility/CleanUp.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);
126 size_t FirstSep = Buffer.find_if(path::is_separator);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000127
Zachary Turner2cc5a182017-03-13 00:41:01 +0000128 llvm::StringRef Username = Buffer.take_front(FirstSep);
129 llvm::StringRef Remainder;
130 if (FirstSep != llvm::StringRef::npos)
131 Remainder = Buffer.drop_front(FirstSep + 1);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000132
Zachary Turner2cc5a182017-03-13 00:41:01 +0000133 llvm::SmallString<PATH_MAX> Resolved;
134 if (!Resolver.ResolveExact(Username, Resolved)) {
135 // We couldn't resolve it as a full username. If there were no slashes
136 // then this might be a partial username. We try to resolve it as such
137 // but after that, we're done regardless of any matches.
138 if (FirstSep == llvm::StringRef::npos) {
139 llvm::StringSet<> MatchSet;
140 saw_directory = Resolver.ResolvePartial(Username, MatchSet);
141 for (const auto &S : MatchSet) {
142 Resolved = S.getKey();
143 path::append(Resolved, path::get_separator());
144 matches.AppendString(Resolved);
145 }
146 saw_directory = (matches.GetSize() > 0);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000147 }
Zachary Turner0734e6a2017-03-12 20:01:37 +0000148 return matches.GetSize();
Zachary Turner2cc5a182017-03-13 00:41:01 +0000149 }
150
151 // If there was no trailing slash, then we're done as soon as we resolve the
152 // expression to the correct directory. Otherwise we need to continue
153 // looking for matches within that directory.
154 if (FirstSep == llvm::StringRef::npos) {
155 // Make sure it ends with a separator.
156 path::append(CompletionBuffer, path::get_separator());
157 saw_directory = true;
158 matches.AppendString(CompletionBuffer);
159 return 1;
160 }
161
162 // We want to keep the form the user typed, so we special case this to
163 // search in the fully resolved directory, but CompletionBuffer keeps the
164 // unmodified form that the user typed.
165 Storage = Resolved;
166 SearchDir = Resolved;
167 } else {
168 SearchDir = path::parent_path(CompletionBuffer);
Zachary Turnerd5bd3a12017-03-12 18:18:50 +0000169 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000170
Zachary Turner2cc5a182017-03-13 00:41:01 +0000171 size_t FullPrefixLen = CompletionBuffer.size();
Zachary Turner0734e6a2017-03-12 20:01:37 +0000172
Zachary Turner2cc5a182017-03-13 00:41:01 +0000173 PartialItem = path::filename(CompletionBuffer);
174 if (PartialItem == ".")
175 PartialItem = llvm::StringRef();
Zachary Turner0734e6a2017-03-12 20:01:37 +0000176
Zachary Turner2cc5a182017-03-13 00:41:01 +0000177 assert(!SearchDir.empty());
178 assert(!PartialItem.contains(path::get_separator()));
Zachary Turner0734e6a2017-03-12 20:01:37 +0000179
Zachary Turner2cc5a182017-03-13 00:41:01 +0000180 // SearchDir now contains the directory to search in, and Prefix contains the
181 // text we want to match against items in that directory.
182
183 std::error_code EC;
184 fs::directory_iterator Iter(SearchDir, EC, false);
185 fs::directory_iterator End;
186 for (; Iter != End && !EC; Iter.increment(EC)) {
187 auto &Entry = *Iter;
188
189 auto Name = path::filename(Entry.path());
190
191 // Omit ".", ".."
192 if (Name == "." || Name == ".." || !Name.startswith(PartialItem))
193 continue;
194
195 // We have a match.
196
197 fs::file_status st;
198 if (EC = Entry.status(st))
199 continue;
200
201 // If it's a symlink, then we treat it as a directory as long as the target
202 // is a directory.
203 bool is_dir = fs::is_directory(st);
204 if (fs::is_symlink_file(st)) {
205 fs::file_status target_st;
206 if (!fs::status(Entry.path(), target_st))
207 is_dir = fs::is_directory(target_st);
208 }
209 if (only_directories && !is_dir)
210 continue;
211
212 // Shrink it back down so that it just has the original prefix the user
213 // typed and remove the part of the name which is common to the located
214 // item and what the user typed.
215 CompletionBuffer.resize(FullPrefixLen);
216 Name = Name.drop_front(PartialItem.size());
217 CompletionBuffer.append(Name);
218
219 if (is_dir) {
220 saw_directory = true;
221 path::append(CompletionBuffer, path::get_separator());
222 }
223
224 matches.AppendString(CompletionBuffer);
225 }
Zachary Turner0734e6a2017-03-12 20:01:37 +0000226
Kate Stoneb9c1b512016-09-06 20:57:50 +0000227 return matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000228}
229
Kate Stoneb9c1b512016-09-06 20:57:50 +0000230int CommandCompletions::DiskFiles(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000231 llvm::StringRef partial_file_name,
Greg Claytonf21fead2013-05-14 23:43:18 +0000232 int match_start_point,
233 int max_return_elements,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000234 SearchFilter *searcher, bool &word_complete,
235 StringList &matches) {
Zachary Turner2cc5a182017-03-13 00:41:01 +0000236 word_complete = false;
237 StandardTildeExpressionResolver Resolver;
238 return DiskFiles(partial_file_name, matches, Resolver);
239}
240
241int CommandCompletions::DiskFiles(const llvm::Twine &partial_file_name,
242 StringList &matches,
243 TildeExpressionResolver &Resolver) {
244 bool word_complete;
245 int ret_val = DiskFilesOrDirectories(partial_file_name, false, word_complete,
246 matches, Resolver);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000247 return ret_val;
248}
249
250int CommandCompletions::DiskDirectories(
Zachary Turner4aa87532016-11-17 01:37:42 +0000251 CommandInterpreter &interpreter, llvm::StringRef partial_file_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000252 int match_start_point, int max_return_elements, SearchFilter *searcher,
253 bool &word_complete, StringList &matches) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000254 word_complete = false;
Zachary Turner2cc5a182017-03-13 00:41:01 +0000255 StandardTildeExpressionResolver Resolver;
256 return DiskDirectories(partial_file_name, matches, Resolver);
257}
258
259int CommandCompletions::DiskDirectories(const llvm::Twine &partial_file_name,
260 StringList &matches,
261 TildeExpressionResolver &Resolver) {
262 bool word_complete;
263 int ret_val = DiskFilesOrDirectories(partial_file_name, true, word_complete,
264 matches, Resolver);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000265 return ret_val;
266}
267
268int CommandCompletions::Modules(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000269 llvm::StringRef partial_file_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000270 int match_start_point, int max_return_elements,
271 SearchFilter *searcher, bool &word_complete,
272 StringList &matches) {
273 word_complete = true;
274 ModuleCompleter completer(interpreter, partial_file_name, match_start_point,
275 max_return_elements, matches);
276
277 if (searcher == nullptr) {
278 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
279 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
280 completer.DoCompletion(&null_searcher);
281 } else {
282 completer.DoCompletion(searcher);
283 }
284 return matches.GetSize();
285}
286
287int CommandCompletions::Symbols(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000288 llvm::StringRef partial_file_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000289 int match_start_point, int max_return_elements,
290 SearchFilter *searcher, bool &word_complete,
291 StringList &matches) {
292 word_complete = true;
293 SymbolCompleter completer(interpreter, partial_file_name, match_start_point,
294 max_return_elements, matches);
295
296 if (searcher == nullptr) {
297 lldb::TargetSP target_sp = interpreter.GetDebugger().GetSelectedTarget();
298 SearchFilterForUnconstrainedSearches null_searcher(target_sp);
299 completer.DoCompletion(&null_searcher);
300 } else {
301 completer.DoCompletion(searcher);
302 }
303 return matches.GetSize();
304}
305
306int CommandCompletions::SettingsNames(
Zachary Turner4aa87532016-11-17 01:37:42 +0000307 CommandInterpreter &interpreter, llvm::StringRef partial_setting_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000308 int match_start_point, int max_return_elements, SearchFilter *searcher,
309 bool &word_complete, StringList &matches) {
310 // Cache the full setting name list
311 static StringList g_property_names;
312 if (g_property_names.GetSize() == 0) {
313 // Generate the full setting name list on demand
314 lldb::OptionValuePropertiesSP properties_sp(
315 interpreter.GetDebugger().GetValueProperties());
316 if (properties_sp) {
317 StreamString strm;
318 properties_sp->DumpValue(nullptr, strm, OptionValue::eDumpOptionName);
319 const std::string &str = strm.GetString();
320 g_property_names.SplitIntoLines(str.c_str(), str.size());
321 }
322 }
323
324 size_t exact_matches_idx = SIZE_MAX;
325 const size_t num_matches = g_property_names.AutoComplete(
326 partial_setting_name, matches, exact_matches_idx);
327 word_complete = exact_matches_idx != SIZE_MAX;
328 return num_matches;
329}
330
331int CommandCompletions::PlatformPluginNames(
Zachary Turner4aa87532016-11-17 01:37:42 +0000332 CommandInterpreter &interpreter, llvm::StringRef partial_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000333 int match_start_point, int max_return_elements, SearchFilter *searcher,
334 bool &word_complete, lldb_private::StringList &matches) {
335 const uint32_t num_matches =
336 PluginManager::AutoCompletePlatformName(partial_name, matches);
337 word_complete = num_matches == 1;
338 return num_matches;
339}
340
341int CommandCompletions::ArchitectureNames(
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 = ArchSpec::AutoComplete(partial_name, matches);
346 word_complete = num_matches == 1;
347 return num_matches;
348}
349
350int CommandCompletions::VariablePath(
Zachary Turner4aa87532016-11-17 01:37:42 +0000351 CommandInterpreter &interpreter, llvm::StringRef partial_name,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000352 int match_start_point, int max_return_elements, SearchFilter *searcher,
353 bool &word_complete, lldb_private::StringList &matches) {
354 return Variable::AutoComplete(interpreter.GetExecutionContext(), partial_name,
355 matches, word_complete);
Greg Claytonf21fead2013-05-14 23:43:18 +0000356}
357
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000358CommandCompletions::Completer::Completer(CommandInterpreter &interpreter,
Zachary Turner4aa87532016-11-17 01:37:42 +0000359 llvm::StringRef completion_str,
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000360 int match_start_point,
361 int max_return_elements,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000362 StringList &matches)
363 : m_interpreter(interpreter), m_completion_str(completion_str),
364 m_match_start_point(match_start_point),
365 m_max_return_elements(max_return_elements), m_matches(matches) {}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000366
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000367CommandCompletions::Completer::~Completer() = default;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000368
369//----------------------------------------------------------------------
370// SourceFileCompleter
371//----------------------------------------------------------------------
372
Kate Stoneb9c1b512016-09-06 20:57:50 +0000373CommandCompletions::SourceFileCompleter::SourceFileCompleter(
374 CommandInterpreter &interpreter, bool include_support_files,
Zachary Turner4aa87532016-11-17 01:37:42 +0000375 llvm::StringRef completion_str, int match_start_point,
376 int max_return_elements, StringList &matches)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000377 : CommandCompletions::Completer(interpreter, completion_str,
378 match_start_point, max_return_elements,
379 matches),
380 m_include_support_files(include_support_files), m_matching_files() {
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000381 FileSpec partial_spec(m_completion_str, false);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000382 m_file_name = partial_spec.GetFilename().GetCString();
383 m_dir_name = partial_spec.GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000384}
385
Kate Stoneb9c1b512016-09-06 20:57:50 +0000386Searcher::Depth CommandCompletions::SourceFileCompleter::GetDepth() {
387 return eDepthCompUnit;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000388}
389
390Searcher::CallbackReturn
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000391CommandCompletions::SourceFileCompleter::SearchCallback(SearchFilter &filter,
392 SymbolContext &context,
393 Address *addr,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000394 bool complete) {
395 if (context.comp_unit != nullptr) {
396 if (m_include_support_files) {
397 FileSpecList supporting_files = context.comp_unit->GetSupportFiles();
398 for (size_t sfiles = 0; sfiles < supporting_files.GetSize(); sfiles++) {
399 const FileSpec &sfile_spec =
400 supporting_files.GetFileSpecAtIndex(sfiles);
401 const char *sfile_file_name = sfile_spec.GetFilename().GetCString();
402 const char *sfile_dir_name = sfile_spec.GetFilename().GetCString();
403 bool match = false;
404 if (m_file_name && sfile_file_name &&
405 strstr(sfile_file_name, m_file_name) == sfile_file_name)
406 match = true;
407 if (match && m_dir_name && sfile_dir_name &&
408 strstr(sfile_dir_name, m_dir_name) != sfile_dir_name)
409 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000410
Kate Stoneb9c1b512016-09-06 20:57:50 +0000411 if (match) {
412 m_matching_files.AppendIfUnique(sfile_spec);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000413 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000414 }
415 } else {
416 const char *cur_file_name = context.comp_unit->GetFilename().GetCString();
417 const char *cur_dir_name = context.comp_unit->GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000418
Kate Stoneb9c1b512016-09-06 20:57:50 +0000419 bool match = false;
420 if (m_file_name && cur_file_name &&
421 strstr(cur_file_name, m_file_name) == cur_file_name)
422 match = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000423
Kate Stoneb9c1b512016-09-06 20:57:50 +0000424 if (match && m_dir_name && cur_dir_name &&
425 strstr(cur_dir_name, m_dir_name) != cur_dir_name)
426 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000427
Kate Stoneb9c1b512016-09-06 20:57:50 +0000428 if (match) {
429 m_matching_files.AppendIfUnique(context.comp_unit);
430 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000431 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000432 }
433 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000434}
435
436size_t
Kate Stoneb9c1b512016-09-06 20:57:50 +0000437CommandCompletions::SourceFileCompleter::DoCompletion(SearchFilter *filter) {
438 filter->Search(*this);
439 // Now convert the filelist to completions:
440 for (size_t i = 0; i < m_matching_files.GetSize(); i++) {
441 m_matches.AppendString(
442 m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString());
443 }
444 return m_matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000445}
446
447//----------------------------------------------------------------------
448// SymbolCompleter
449//----------------------------------------------------------------------
450
Kate Stoneb9c1b512016-09-06 20:57:50 +0000451static bool regex_chars(const char comp) {
452 return (comp == '[' || comp == ']' || comp == '(' || comp == ')' ||
453 comp == '{' || comp == '}' || comp == '+' || comp == '.' ||
454 comp == '*' || comp == '|' || comp == '^' || comp == '$' ||
455 comp == '\\' || comp == '?');
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000456}
Eugene Zelenkoc8ecc2a2016-02-19 19:33:46 +0000457
Kate Stoneb9c1b512016-09-06 20:57:50 +0000458CommandCompletions::SymbolCompleter::SymbolCompleter(
Zachary Turner4aa87532016-11-17 01:37:42 +0000459 CommandInterpreter &interpreter, llvm::StringRef completion_str,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000460 int match_start_point, int max_return_elements, StringList &matches)
461 : CommandCompletions::Completer(interpreter, completion_str,
462 match_start_point, max_return_elements,
463 matches) {
464 std::string regex_str;
Zachary Turner4aa87532016-11-17 01:37:42 +0000465 if (!completion_str.empty()) {
Kate Stoneb9c1b512016-09-06 20:57:50 +0000466 regex_str.append("^");
467 regex_str.append(completion_str);
468 } else {
469 // Match anything since the completion string is empty
470 regex_str.append(".");
471 }
472 std::string::iterator pos =
473 find_if(regex_str.begin() + 1, regex_str.end(), regex_chars);
474 while (pos < regex_str.end()) {
475 pos = regex_str.insert(pos, '\\');
476 pos = find_if(pos + 2, regex_str.end(), regex_chars);
477 }
Zachary Turner95eae422016-09-21 16:01:28 +0000478 m_regex.Compile(regex_str);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000479}
480
Kate Stoneb9c1b512016-09-06 20:57:50 +0000481Searcher::Depth CommandCompletions::SymbolCompleter::GetDepth() {
482 return eDepthModule;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000483}
484
Kate Stoneb9c1b512016-09-06 20:57:50 +0000485Searcher::CallbackReturn CommandCompletions::SymbolCompleter::SearchCallback(
486 SearchFilter &filter, SymbolContext &context, Address *addr,
487 bool complete) {
488 if (context.module_sp) {
489 SymbolContextList sc_list;
490 const bool include_symbols = true;
491 const bool include_inlines = true;
492 const bool append = true;
493 context.module_sp->FindFunctions(m_regex, include_symbols, include_inlines,
494 append, sc_list);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000495
Kate Stoneb9c1b512016-09-06 20:57:50 +0000496 SymbolContext sc;
497 // Now add the functions & symbols to the list - only add if unique:
498 for (uint32_t i = 0; i < sc_list.GetSize(); i++) {
499 if (sc_list.GetContextAtIndex(i, sc)) {
500 ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled);
501 if (!func_name.IsEmpty())
502 m_match_set.insert(func_name);
503 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000504 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000505 }
506 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000507}
508
Kate Stoneb9c1b512016-09-06 20:57:50 +0000509size_t CommandCompletions::SymbolCompleter::DoCompletion(SearchFilter *filter) {
510 filter->Search(*this);
511 collection::iterator pos = m_match_set.begin(), end = m_match_set.end();
512 for (pos = m_match_set.begin(); pos != end; pos++)
513 m_matches.AppendString((*pos).GetCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000514
Kate Stoneb9c1b512016-09-06 20:57:50 +0000515 return m_matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000516}
517
518//----------------------------------------------------------------------
519// ModuleCompleter
520//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +0000521CommandCompletions::ModuleCompleter::ModuleCompleter(
Zachary Turner4aa87532016-11-17 01:37:42 +0000522 CommandInterpreter &interpreter, llvm::StringRef completion_str,
Kate Stoneb9c1b512016-09-06 20:57:50 +0000523 int match_start_point, int max_return_elements, StringList &matches)
524 : CommandCompletions::Completer(interpreter, completion_str,
525 match_start_point, max_return_elements,
526 matches) {
Malcolm Parsons771ef6d2016-11-02 20:34:10 +0000527 FileSpec partial_spec(m_completion_str, false);
Kate Stoneb9c1b512016-09-06 20:57:50 +0000528 m_file_name = partial_spec.GetFilename().GetCString();
529 m_dir_name = partial_spec.GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000530}
531
Kate Stoneb9c1b512016-09-06 20:57:50 +0000532Searcher::Depth CommandCompletions::ModuleCompleter::GetDepth() {
533 return eDepthModule;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000534}
535
Kate Stoneb9c1b512016-09-06 20:57:50 +0000536Searcher::CallbackReturn CommandCompletions::ModuleCompleter::SearchCallback(
537 SearchFilter &filter, SymbolContext &context, Address *addr,
538 bool complete) {
539 if (context.module_sp) {
540 const char *cur_file_name =
541 context.module_sp->GetFileSpec().GetFilename().GetCString();
542 const char *cur_dir_name =
543 context.module_sp->GetFileSpec().GetDirectory().GetCString();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000544
Kate Stoneb9c1b512016-09-06 20:57:50 +0000545 bool match = false;
546 if (m_file_name && cur_file_name &&
547 strstr(cur_file_name, m_file_name) == cur_file_name)
548 match = true;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000549
Kate Stoneb9c1b512016-09-06 20:57:50 +0000550 if (match && m_dir_name && cur_dir_name &&
551 strstr(cur_dir_name, m_dir_name) != cur_dir_name)
552 match = false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000553
Kate Stoneb9c1b512016-09-06 20:57:50 +0000554 if (match) {
555 m_matches.AppendString(cur_file_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000556 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000557 }
558 return Searcher::eCallbackReturnContinue;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000559}
560
Kate Stoneb9c1b512016-09-06 20:57:50 +0000561size_t CommandCompletions::ModuleCompleter::DoCompletion(SearchFilter *filter) {
562 filter->Search(*this);
563 return m_matches.GetSize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000564}